Sap La S4D400 en 24 Ex
Sap La S4D400 en 24 Ex
.
.
EXERCISES AND SOLUTIONS
.
Course Version: 24
Exercise Duration: 6 Hours 35 Minutes
Material Number: 50164578
SAP Copyrights, Trademarks and
Disclaimers
No part of this publication may be reproduced or transmitted in any form or for any purpose without the
express permission of SAP SE or an SAP affiliate company.
SAP and other SAP products and services mentioned herein as well as their respective logos are
trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other
countries. Please see https://www.sap.com/corporate/en/legal/copyright.html for additional
trademark information and notices.
Some software products marketed by SAP SE and its distributors contain proprietary software
components of other software vendors.
National product specifications may vary.
These materials may have been machine translated and may contain grammatical errors or
inaccuracies.
These materials are provided by SAP SE or an SAP affiliate company for informational purposes only,
without representation or warranty of any kind, and SAP SE or its affiliated companies shall not be liable
for errors or omissions with respect to the materials. The only warranties for SAP SE or SAP affiliate
company products and services are those that are set forth in the express warranty statements
accompanying such products and services, if any. Nothing herein should be construed as constituting an
additional warranty.
In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business
outlined in this document or any related presentation, or to develop or release any functionality
mentioned therein. This document, or any related presentation, and SAP SE’s or its affiliated companies’
strategy and possible future developments, products, and/or platform directions and functionality are
all subject to change and may be changed by SAP SE or its affiliated companies at any time for any
reason without notice. The information in this document is not a commitment, promise, or legal
obligation to deliver any material, code, or functionality. All forward-looking statements are subject to
various risks and uncertainties that could cause actual results to differ materially from expectations.
Readers are cautioned not to place undue reliance on these forward-looking statements, which speak
only as of their dates, and they should not be relied upon in making purchasing decisions.
Demonstration
Procedure
Warning or Caution
Hint
Facilitated Discussion
In this exercise, you start your ABAP cloud project and analyze some existing ABAP code to
get familiar with some basic features of the ABAP development environment.
Note:
You are not required to read the code in this exercise. Instead, concentrate on the
navigation and display functions in the development environment.
2. Open the Properties tab to display the administrative data of development object /DMO/
CL_FLIGHT_LEGACY.
3. Locate the ABAP class /DMO/CL_FLIGHT_LEGACY in the Project Explorer view on the left
of the display.
4. Find the string get_instance( )->get in the source code of ABAP class /DMO/
CL_FLIGHT_LEGACY.
Note:
There has to be exactly one blank between the brackets.
6. A few code lines down there is a line starting with SELECT. Without navigating away,
display some information about code element /dmo/travel after keyword FROM.
In this exercise, you start your ABAP cloud project and analyze some existing ABAP code to
get familiar with some basic features of the ABAP development environment.
c) Choose Import and select the file containing the service key that you have been given.
f) When you see the message, You have been successfully logged on, close the browser
window and return to Eclipse.
Note:
You are not required to read the code in this exercise. Instead, concentrate on the
navigation and display functions in the development environment.
2. Open the Properties tab to display the administrative data of development object /DMO/
CL_FLIGHT_LEGACY.
a) Place the cursor anywhere in the source code of class /DMO/CL_FLIGHT_LEGACY.
b) In the tab strip below the editor view, navigate to tab Properties.
c) Analyze the administrative data that are displayed there, for example the original
language, the time stamp of the last change or the user that at first created the object.
3. Locate the ABAP class /DMO/CL_FLIGHT_LEGACY in the Project Explorer view on the left
of the display.
a) Place the cursor anywhere in the source code of the class /DMO/CL_FLIGHT_LEGACY.
b) On the tool bar of the project explorer, choose Link with Editor. This should expand a
part of the tree under your ABAP project with the ABAP class /DMO/
CL_FLIGHT_LEGACY as its end point.
4. Find the string get_instance( )->get in the source code of ABAP class /DMO/
CL_FLIGHT_LEGACY.
Note:
There has to be exactly one blank between the brackets.
a) Place the cursor in the first row of the source code of class /DMO/
CL_FLIGHT_LEGACY.
c) In the input field labeled with Find: enter get_instance( )->get and choose Find.
6. A few code lines down there is a line starting with SELECT. Without navigating away,
display some information about code element /dmo/travel after keyword FROM.
a) In the code line starting with SELECT, place the cursor on /dmo/booking and choose
Source Code → Show Code Element Information. Alternatively, press F2.
Note:
There is no need to read or understand the documentation at this point. If
you are familiar with the Structured Query Language (SQL) you can have a
look at the first paragraph in section Effect.
In this exercise, you first add package /LRN/S4D400_EXERCISE to the list of Favorite
Packages. You then create a new package under the superpackage ZLOCAL (suggested name:
ZS4D400_## where ## is your group number).
Note:
This package will be the home for all development objects that you will create in
this course.
Attribute Value
Name ZS4D400_##, where ## is your group
number
Description My ABAP Package
2. In your ABAP Cloud project, create a new package with the attributes listed above. When
you are prompted for a transport choose the transport request in which you are involved.
If no transport request is listed, create a new request.
3. Ensure that your new package has been added to the Favorite Packages.
In this exercise, you first add package /LRN/S4D400_EXERCISE to the list of Favorite
Packages. You then create a new package under the superpackage ZLOCAL (suggested name:
ZS4D400_## where ## is your group number).
Note:
This package will be the home for all development objects that you will create in
this course.
Attribute Value
Name ZS4D400_##, where ## is your group
number
Description My ABAP Package
d) From the list of matching items, select /LRN/S4D400_EXERCISE, then choose OK.
2. In your ABAP Cloud project, create a new package with the attributes listed above. When
you are prompted for a transport choose the transport request in which you are involved.
If no transport request is listed, create a new request.
a) In the Project Explorer, right-click on your ABAP Cloud Project and choose New →
ABAP Package .
g) Choose Next.
k) Choose Next.
l) Check if there is a transport request listed under option Choose from requests in which
I am involved. If this is the case, choose this option. If the list is empty, choose the
option Create a new request and enter a request description, for example ABAP
Exercises.
m) Choose Finish.
3. Ensure that your new package has been added to the Favorite Packages.
a) In the Project Explorer on the left, expand your ABAP cloud project and then sub node
Favorite Packages.
b) Make sure your own package, ZS4D400_##, is listed here. If not, add it like you added
package /LRN/S4D400_EXERCISE earlier.
1. In your package, create a new ABAP class with the name ZCL_##_HELLO_WORLD. Ensure
that it uses the interface IF_OO_ADT_CLASSRUN. When you are prompted to assign the
class to a transport request, use the transport request that you created in the previous
task.
1. In your package, create a new ABAP class with the name ZCL_##_HELLO_WORLD. Ensure
that it uses the interface IF_OO_ADT_CLASSRUN. When you are prompted to assign the
class to a transport request, use the transport request that you created in the previous
task.
a) Choose File → New → ABAP Class.
c) Enter the name ZCL_##_HELLO_WORLD where ## is your group number, and enter a
description for your class.
e) Enter the filter text IF_OO_ADT_CLASSRUN. Double-click the matching entry in the hit
list.
f) Choose Next.
g) Select Choose from requests in which I am involved and your own transport request.
h) Choose Finish.
b) If the Console view is not visible, open it by choosing Window → Show view → Other.
Double-click Console in the hit list.
In this exercise, you create a program that does a calculation based on two numbers, then
formats and outputs the result.
Template:
none
Solution:
3. Implement a value assignment for each of the two numeric variables. Assign a negative
value to the first variable and a positive value to the second variable.
1. Implement an arithmetic expression that calculates the ratio of the two numbers. Store
the result in a variable that you declare using an inline declaration (suggested name:
result).
2. Implement a string template that puts together a text like this:“6 / 3 = 2”, with the actual
values of the variables instead of 6, 3, and 2. Store the result in a variable that you declare
using an inline declaration (suggested name: output).
In this exercise, you create a program that does a calculation based on two numbers, then
formats and outputs the result.
Template:
none
Solution:
b) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_COMPUTE, where ## stands for your group number.
c) Enter a description.
e) Enter IF_OO_ADT_CLASSRUN. When the interface appears in the hit list, double-click it
to add it to the class definition.
f) Choose Next.
3. Implement a value assignment for each of the two numeric variables. Assign a negative
value to the first variable and a positive value to the second variable.
a) Add the following code:
number1 = -8.
number2 = 3.
1. Implement an arithmetic expression that calculates the ratio of the two numbers. Store
the result in a variable that you declare using an inline declaration (suggested name:
result).
a) Add the following code:
2. Implement a string template that puts together a text like this:“6 / 3 = 2”, with the actual
values of the variables instead of 6, 3, and 2. Store the result in a variable that you declare
using an inline declaration (suggested name: output).
a) Add the following code:
Due to the inline declaration, variable result is of integer type and ABAP rounds the
result using the “half-up” rounding rule.
b) In the code line with the inline declaration, replace DATA(result) with result.
b) Compare your code to the following extract from the model solution:
METHOD if_oo_adt_classrun~main.
* Declarations
**************************
* Input Values
**************************
number1 = -8.
number2 = 3.
* Calculation
**************************
* Output
**************************
out->write( output ).
ENDMETHOD.
In this exercise, you enable the program for the four basic calculation operations and handle
error situations.
Template:
Solution:
1. Declare a variable for the calculation operator (suggested name: op). The variable needs a
type of fixed length to hold one of the following values: “+”, “-”, “*”, or “/”.
2. Directly after the value assignment for variables number1 and number2, add a value
assignment to set the new variable op to value “/”.
3. Use a suitable control structure to fill the variable result with different arithmetic
expressions, depending on the value of the variable op.
4. Adjust the string template to use the content of op, rather than the literal character “/”.
5. Activate and test the application with different values for number1, number2, and op.
1. In the CASE control structure, add a branch that is executed for any other values of op.
2. In this branch, fill output with a suitable text to describe the error situation.
Note:
We suggest that at this point, you replace the inline declaration of the variable
output with an explicit declaration at the beginning of the method.
3. Use a suitable control structure to make sure the output variable is only filled with the
calculation result if it is not already filled with an error text.
4. Activate and test the application with different values for number1, number2, and op.
1. Inside the branch for division (op has value “/”), surround the calculation with a pair of
TRY and ENDTRY statements.
2. Before the ENDTRY statement, add a CATCH-block for the exception that is raised in case
of a division by zero error.
3. In the CATCH-block, fill the output variable with a suitable error text.
4. Activate and test the application with different values for number1, number2, and op. In
particular, test the handling of the error situations: invalid operator and division by zero.
In this exercise, you enable the program for the four basic calculation operations and handle
error situations.
Template:
Solution:
c) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_BRANCH, where ## stands for your group number.
1. Declare a variable for the calculation operator (suggested name: op). The variable needs a
type of fixed length to hold one of the following values: “+”, “-”, “*”, or “/”.
a) Add the highlighted code:
2. Directly after the value assignment for variables number1 and number2, add a value
assignment to set the new variable op to value “/”.
a) Add the highlighted code:
number1 = 123.
number2 = 0.
op = '/'.
3. Use a suitable control structure to fill the variable result with different arithmetic
expressions, depending on the value of the variable op.
a) Add the highlighted code:
CASE op.
WHEN '+'.
result = number1 + number2.
WHEN '-'.
result = number1 - number2.
WHEN '*'.
result = number1 * number2.
WHEN '/'.
result = number1 / number2.
ENDCASE.
4. Adjust the string template to use the content of op, rather than the literal character “/”.
a) Adjust the string template as follows:
5. Activate and test the application with different values for number1, number2, and op.
The result is always zero (0.00) because none of the four WHEN branches is executed.
1. In the CASE control structure, add a branch that is executed for any other values of op.
CASE op.
WHEN '+'.
result = number1 + number2.
WHEN '-'.
result = number1 - number2.
WHEN '*'.
result = number1 * number2.
WHEN '/'.
result = number1 / number2.
WHEN OTHERS.
ENDCASE.
2. In this branch, fill output with a suitable text to describe the error situation.
Note:
We suggest that at this point, you replace the inline declaration of the variable
output with an explicit declaration at the beginning of the method.
b) Replace the inline declaration DATA(output) with the explicitly declared variable
output.
3. Use a suitable control structure to make sure the output variable is only filled with the
calculation result if it is not already filled with an error text.
a) Add the highlighted code:
4. Activate and test the application with different values for number1, number2, and op.
1. Inside the branch for division (op has value “/”), surround the calculation with a pair of
TRY and ENDTRY statements.
WHEN '/'.
TRY.
result = number1 / number2.
ENDTRY.
WHEN OTHERS.
2. Before the ENDTRY statement, add a CATCH-block for the exception that is raised in case
of a division by zero error.
a) Add the highlighted code:
TRY.
result = number1 / number2.
CATCH cx_sy_zerodivide.
ENDTRY.
3. In the CATCH-block, fill the output variable with a suitable error text.
a) Add the highlighted code:
TRY.
result = number1 / number2.
CATCH cx_sy_zerodivide.
output = |Division by zero is not defined|.
ENDTRY.
4. Activate and test the application with different values for number1, number2, and op. In
particular, test the handling of the error situations: invalid operator and division by zero.
a) Proceed as you have done before.
b) Compare your code to the following extract from the model solution:
METHOD if_oo_adt_classrun~main.
* Declarations
**************************
* Input Values
**************************
number1 = 123.
number2 = 0.
op = '/'.
* Calculation
**************************
CASE op.
WHEN '+'.
result = number1 + number2.
WHEN '-'.
result = number1 - number2.
WHEN '*'.
result = number1 * number2.
WHEN '/'.
TRY.
result = number1 / number2.
CATCH cx_sy_zerodivide.
output = |Division by zero is not defined|.
ENDTRY.
WHEN OTHERS.
ENDCASE.
ENDIF.
* Output
**************************
out->write( output ).
ENDMETHOD.
In this exercise, you use iterations and simple internal tables to calculate and display the
Fibonacci numbers.
Note:
The Fibonacci numbers are a sequence of numbers in which each number is the
sum of the two preceding ones. The sequence starts with 0 and 1, and each
subsequent number is the sum of the two previous numbers. The sequence has
various mathematical properties, patterns, and applications in fields such as
mathematics, computer science, nature, and art.
Template:
none
Solution:
3. Declare a simple internal table to store the Fibonacci numbers (suggested name:
numbers).
5. Inside the iteration, implement a case distinction based on the built-in iteration counter: In
the first iteration, add the value 0 to the internal table numbers. In the second iteration,
add the value 1 to the end of internal table numbers.
Hint:
The built-in iteration counter is system field sy-index.
6. Add a branch that is executed for all other values. In this branch, calculate the new entry
as the sum of the two preceding entries in numbers.
Hint:
Access the preceding entries using index sy-index - 1 and sy-index -
2.
2. Implement a loop over the internal table numbers to read the Fibonacci numbers one by
one into a variable number.
Hint:
Use an inline declaration for number.
3. Declare an integer variable (suggested name: counter), that you set to zero before the
loop and increase by 1 in each iteration.
Hint:
You can use an inline declaration for counter.
4. In each iteration, add a new row to the internal table output which contains the content of
counter (l4 characters wide, left-justified), a colon (;) and the content of number (10
characters wide, right justified).
Hint:
Use a string template with suitable format options to adjust the format.
Which format options are used to set the width and the alignment?
1. At the end of the method, call the method out->write to write the content of output to
the console. Supply the importing parameter name with a suitable caption.
In this exercise, you use iterations and simple internal tables to calculate and display the
Fibonacci numbers.
Note:
The Fibonacci numbers are a sequence of numbers in which each number is the
sum of the two preceding ones. The sequence starts with 0 and 1, and each
subsequent number is the sum of the two previous numbers. The sequence has
various mathematical properties, patterns, and applications in fields such as
mathematics, computer science, nature, and art.
Template:
none
Solution:
b) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_ITERATE, where ## stands for your group number.
c) Enter a description.
e) Enter IF_OO_ADT_CLASSRUN. When the interface appears in the hit list, double-click it
to add it to the class definition.
f) Choose Next.
3. Declare a simple internal table to store the Fibonacci numbers (suggested name:
numbers).
a) Add the following code:
DO max_count TIMES.
ENDDO.
5. Inside the iteration, implement a case distinction based on the built-in iteration counter: In
the first iteration, add the value 0 to the internal table numbers. In the second iteration,
add the value 1 to the end of internal table numbers.
Hint:
The built-in iteration counter is system field sy-index.
CASE sy-index.
WHEN 1.
APPEND 0 TO numbers.
WHEN 2.
APPEND 1 TO numbers.
ENDCASE.
6. Add a branch that is executed for all other values. In this branch, calculate the new entry
as the sum of the two preceding entries in numbers.
Hint:
Access the preceding entries using index sy-index - 1 and sy-index -
2.
CASE sy-index.
WHEN 1.
APPEND 0 TO numbers.
WHEN 2.
APPEND 1 TO numbers.
WHEN OTHERS.
APPEND numbers[ sy-index - 2 ]
+ numbers[ sy-index - 1 ]
TO numbers.
ENDCASE.
2. Implement a loop over the internal table numbers to read the Fibonacci numbers one by
one into a variable number.
Hint:
Use an inline declaration for number.
ENDLOOP.
3. Declare an integer variable (suggested name: counter), that you set to zero before the
loop and increase by 1 in each iteration.
Hint:
You can use an inline declaration for counter.
DATA(counter) = 0.
LOOP AT numbers INTO DATA(number).
counter = counter + 1.
ENDLOOP.
4. In each iteration, add a new row to the internal table output which contains the content of
counter (l4 characters wide, left-justified), a colon (;) and the content of number (10
characters wide, right justified).
Hint:
Use a string template with suitable format options to adjust the format.
Which format options are used to set the width and the alignment?
DATA(counter) = 0.
LOOP AT numbers INTO DATA(number).
counter = counter + 1.
ENDLOOP.
1. At the end of the method, call the method out->write to write the content of output to
the console. Supply the importing parameter name with a suitable caption.
a) After ENDLOOP., add the following code:
out->write(
data = output
name = |The first { max_count } Fibonacci Numbers|
) .
In this exercise, you analyze ABAP code using the ABAP debugger.
Template:
Solution:
Task 1: Preparation
Copy the class that you want to debug.
1. Open the source code of global class /LRN/CL_S4D400_BTT_DEBUG in the ABAP editor.
1. Set a breakpoint at the first statement that does not define a type or declare a data object.
Hint:
TYPES defines a data type, CONSTANTS declares a constant data object,
DATA declares a variable data object.
3. Display the value of data object loan_remaining and loan_total in the Variables view.
1. Execute a single step to debug the value assignment in the current line.
2. Display the content of data object spec_repay_mode. Then execute another single step
to see which WHEN branch of the CASE - control structure is executed.
3. Set a watch point for variable loan_remaining and resume program execution. Where
does the program execution stop again?
4. Display the content of data object repayment_plan. Then execute another single step to
see how it is filled with the APPEND statement.
Note:
Because repayment_plan is an internal table, it not only displays in the
Variables view but also in the ABAP Internal Table (Debugger) view below the
editor.
5. Inspect the string template in the APPEND statement and relate it to the resulting first row
in internal table repayment_plan. Display the content of the data objects that appear in
the embedded expressions.
6. Set another watch point for variable repayment_plan and resume program execution for
a few times. Whenever execution reaches one of the watch points, analyze the value of
loan_remaining and new rows are added to repayment_plan.
7. After a while, set a statement break point for all EXIT statements and delete the two watch
points.
8. Resume program execution until you reach the first EXIT statement. Deactivate the
statement breakpoint for the EXIT statement. Then execute single steps until you reach
the output part of the program.
9. Open the Console view. Execute the remaining program and pursue the output on the
console view.
Note:
Do not press F5 to debug the output. Use F6 instead.
Note:
As you will learn later in the course out->write( ... ) is not an ABAP
statement but a reusable code block that consists of many ABAP statements.
By pressing F5 you Step Into this code to analyze it in detail. With F6 you Step
Over the code block, treating it like a single statement.
10. When the application is terminated, do not forget to switch back to the ABAP perspective.
In this exercise, you analyze ABAP code using the ABAP debugger.
Template:
Solution:
Task 1: Preparation
Copy the class that you want to debug.
1. Open the source code of global class /LRN/CL_S4D400_BTT_DEBUG in the ABAP editor.
a) In the Eclipse toolbar, choose Open ABAP Development Object. Alternatively, press
Ctrl + Shift + A.
c) Enter the name of your package (ZS4D400_##, where ## stands for your group
number) and the name for the new class (ZCL_##_DEBUG), then choose Next.
b) If the Console view is not visible, open it by choosing Window → Show view → Other.
Double-click Console in the hit list.
1. Set a breakpoint at the first statement that does not define a type or declare a data object.
Hint:
TYPES defines a data type, CONSTANTS declares a constant data object,
DATA declares a variable data object.
a) Double-click the left-hand margin of the editor next to the line loan_remaining =
loan_total.to set a break point.
b) If you are asked whether you want to switch to the Debug perspective, mark
Remember my decision and choose OK.
3. Display the value of data object loan_remaining and loan_total in the Variables view.
a) In the current code line (the one with a green background) double-click
loan_remaining.
1. Execute a single step to debug the value assignment in the current line.
a) In the toolbar, choose Step Into (F5) or press F5.
2. Display the content of data object spec_repay_mode. Then execute another single step
to see which WHEN branch of the CASE - control structure is executed.
a) In the next code line, double-click spec_repay_mode.
b) Press F5 to see that the program jumps to code line WHEN 'Q'..
3. Set a watch point for variable loan_remaining and resume program execution. Where
does the program execution stop again?
a) In the Variables view, right-click on LOAN_REMAINING and choose Set Watchpoint.
4. Display the content of data object repayment_plan. Then execute another single step to
see how it is filled with the APPEND statement.
Note:
Because repayment_plan is an internal table, it not only displays in the
Variables view but also in the ABAP Internal Table (Debugger) view below the
editor.
5. Inspect the string template in the APPEND statement and relate it to the resulting first row
in internal table repayment_plan. Display the content of the data objects that appear in
the embedded expressions.
a) Double-click the data objects that appear between the curly brackets to display their
contents.
6. Set another watch point for variable repayment_plan and resume program execution for
a few times. Whenever execution reaches one of the watch points, analyze the value of
loan_remaining and new rows are added to repayment_plan.
a) In the Variables view, right-click on REPAYMENT_PLAN and choose Set Watchpoint.
c) Analyze the data objects in the Variables view and the ABAP Internal Table (Debugger)
view.
7. After a while, set a statement break point for all EXIT statements and delete the two watch
points.
a) Navigate to the Breakpoints view.
Hint:
You find the Breakpoints view next to the Variables view.
b) In the toolbar of the Breakpoints view, expand the dropdown button on the very left
and choose Add Statement Breakpoint ....
c) On the dialog window that appears, enter EXIT as search string, click on the value EXIT
in the hitlist, and choose OK.
d) In the Breakpoints view, right-click the watch point LOAN_REMAINING and choose
Remove.
e) In the Breakpoints view, right-click the watch point REPAYMENT_PLAN and choose
Remove.
8. Resume program execution until you reach the first EXIT statement. Deactivate the
statement breakpoint for the EXIT statement. Then execute single steps until you reach
the output part of the program.
a) Press F8 to resume program execution.
b) Switch to the Breakpoints view and deselect the line that says EXIT [Statement].
c) Press F5 until you reach the first code line that starts with out->write(.
9. Open the Console view. Execute the remaining program and pursue the output on the
console view.
Note:
Do not press F5 to debug the output. Use F6 instead.
Note:
As you will learn later in the course out->write( ... ) is not an ABAP
statement but a reusable code block that consists of many ABAP statements.
By pressing F5 you Step Into this code to analyze it in detail. With F6 you Step
Over the code block, treating it like a single statement.
a) Press F6 several times until you reach the end of the application.
b) Analyze the addition output on the Console view and compare it to the string template
in the previous code line.
10. When the application is terminated, do not forget to switch back to the ABAP perspective.
a) Choose ABAP on the very right of the Eclipse toolbar.
none
Solution:
1. Inside the global class, create a new local class lcl_connection. Use code completion to
generate the code, but make sure you remove the create private addition from the
generated code.
Table 1: Attributes
Attribute Name Scope Data Type
carrier_id instance /DMO/CARRIER_ID
conn_counter static I
Note:
Because the if_oo_adt_classrun~main method does not contain
executable code, yet, there is nothing to test or debug at this point.
none
Solution:
b) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_LOCAL_CLASS, where ## is your group number. Enter a description.
d) Enter IF_OO_ADT_CLASSRUN. When the interface appears in the hit list, double-click it
to add it to the class definition.
e) Choose Next.
1. Inside the global class, create a new local class lcl_connection. Use code completion to
generate the code, but make sure you remove the create private addition from the
generated code.
a) Switch to the Local Types tab.
d) While there is still a frame visible around lcl in the line class lcl definition
create private., complete the name of the class to lcl_connection.
e) Delete the words create private at the end of the code row class
lcl_connection definition..
Table 1: Attributes
Attribute Name Scope Data Type
carrier_id instance /DMO/CARRIER_ID
conn_counter static I
a) After line PUBLIC SECTION. and before line PROTECTED SECTION., add the
following code:
Note:
Because the if_oo_adt_classrun~main method does not contain
executable code, yet, there is nothing to test or debug at this point.
b) Compare your code on tab Local Types to the following extract from the model
solution:
*"* use this source file for the definition and implementation of
*"* local helper classes, interface definitions and type
*"* declarations
PUBLIC SECTION.
PROTECTED SECTION.
PRIVATE SECTION.
ENDCLASS.
ENDCLASS.
In this exercise, you create and manage instances of your local class.
Template:
Solution:
2. Create an instance of the class and set the attributes carrier_id and connection_id
(Suggested values: “LH” for attribute carrier_id and “0400” for attribute
connection_id.
3. Activate the class and use the debugger to analyze step by step what happens.
2. After instantiating the class and setting the attributes, append the object reference to the
internal table.
3. Create two more instances of class lcl_connection, set their instance attributes to
different values than in the first instance and append the references to the new instances
to internal table connections. Use the same reference variable connection for all three
instances.
4. Activate the class and use the debugger to analyze step by step what happens.
In this exercise, you create and manage instances of your local class.
Template:
Solution:
c) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_INSTANCES, where ## stands for your group number.
METHOD if_oo_adt_classrun~main.
ENDMETHOD.
2. Create an instance of the class and set the attributes carrier_id and connection_id
(Suggested values: “LH” for attribute carrier_id and “0400” for attribute
connection_id.
a) Add the highlighted code:
connection = new #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
Hint:
After typing the component selector (->), press Strg + Space to choose
the attribute names from a suggestion list.
3. Activate the class and use the debugger to analyze step by step what happens.
a) Press Ctrl + F3 to activate the class.
b) Double-click the left-hand margin of the editor next to the line connection = new
#( ).to set a break point.
e) Press F5 to go one step further in the debugger. Check that the value of connection
has changed.
f) In the Variables view, expand the branch connection to display the initial attributes of
the class.
g) Press F5 to go one step further in the debugger. Check that the value of carrier_id
has changed.
connection = new #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
2. After instantiating the class and setting the attributes, append the object reference to the
internal table.
a) Add the highlighted code:
connection = NEW #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
3. Create two more instances of class lcl_connection, set their instance attributes to
different values than in the first instance and append the references to the new instances
to internal table connections. Use the same reference variable connection for all three
instances.
a) Add the highlighted code:
connection = NEW #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
connection = NEW #( ).
connection->carrier_id = 'AA'.
connection->connection_id = '0017'.
connection = NEW #( ).
connection->carrier_id = 'SQ'.
connection->connection_id = '0001'.
4. Activate the class and use the debugger to analyze step by step what happens.
a) Press Ctrl + F3 to activate the class.
b) Double-click the left-hand margin of the editor next to the first line connection =
new #( ).to remove the break point.
c) Double-click the left-hand margin of the editor next to the first line APPEND
connection TO connections.to set a new break point.
g) Press F5 to go one step further in the debugger. Check that the content of
connections has changed.
h) In the Variables view, expand the branch connections to display content of the
internal table.
i) Press F5 several times until you reach the end of the program. While you do so, check
the content of the internal table.
j) Compare your code on tab Global Class to the following extract from the model
solution:
METHOD if_oo_adt_classrun~main.
* First Instance
**********************************************************************
connection = NEW #( ).
connection->carrier_id = 'LH'.
connection->connection_id = '0400'.
* Second Instance
**********************************************************************
connection = NEW #( ).
connection->carrier_id = 'AA'.
connection->connection_id = '0017'.
* Third Instance
**********************************************************************
connection = NEW #( ).
connection->carrier_id = 'SQ'.
connection->connection_id = '0001'.
ENDMETHOD.
In this exercise, you create and manage instances of your local class.
Template:
Solution:
2. Add a method get_output to the public section of the class. It should have one returning
parameter r_outputof global table typeSTRING_TABLE.
Note:
Remember to surround the name of the returning parameter with VALUE( ).
3. Add a method set_attributes to the public section of the class. It should have one
importing parameter for each instance attribute of the class. Use the same types for the
parameters that you used to type the attributes. To distinguish the parameters from the
attributes, add prefix i_ to the parameter names. In addition, the method should raise
exception CX_ABAP_INVALID_VALUE.
2. At the end of the method, add a loop over the internal table connections with reference
variable connection as a work area.
3. In the loop, call functional method get_output for each instance in turn and write the
result to the console.
Hint:
You can use the call of method get_output directly as input for out-
>write( ).
4. Activate the class. Execute it as a console app and analyze the console output.
1. For the first instance of class lcl_connection, replace the direct access to attributes
carrier_id and connection_id with a call of the instance method
set_attributes( ). Use code completion to insert the full signature of the method.
Hint:
Press Ctrl + Space after you typed the component select (->) to display a
list of available attributes and methods. Choose the method and then press
Shift + Enter to insert the full signature of the method.
2. Handle the exception. Surround the method call with TRY. and ENDTRY.. Add a CATCH-
Block to handle exception CX_ABAP_INVALID_VALUE. Make sure the new instance is only
added to internal table connections if the method call was successful.
3. Repeat the previous step for the other two instances of class lcl_connection.
In this exercise, you create and manage instances of your local class.
Template:
Solution:
c) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_METHODS, where ## stands for your group number.
2. Add a method get_output to the public section of the class. It should have one returning
parameter r_outputof global table typeSTRING_TABLE.
Note:
Remember to surround the name of the returning parameter with VALUE( ).
PUBLIC SECTION.
METHODS get_output
returning
value(r_output) type string_table.
PROTECTED SECTION.
Note:
For the moment, ignore the syntax error Implementation missing for
method "GET_OUTPUT".
3. Add a method set_attributes to the public section of the class. It should have one
importing parameter for each instance attribute of the class. Use the same types for the
parameters that you used to type the attributes. To distinguish the parameters from the
attributes, add prefix i_ to the parameter names. In addition, the method should raise
exception CX_ABAP_INVALID_VALUE.
a) Add the highlighted code:
PUBLIC SECTION.
METHODS set_attributes
IMPORTING
i_carrier_id TYPE /dmo/carrier_id
i_connection_id TYPE /dmo/connection_id
RAISING
cx_abap_invalid_value.
METHODS get_output
returning
value(r_output) type string_table.
PROTECTED SECTION.
Note:
For the moment, ignore the syntax error Implementation missing for
method "SET_ATTRIBUTES".
METHOD get_output.
ENDMETHOD.
METHOD set_attributes.
carrier_id = i_carrier_id.
connection_id = i_connection_id.
ENDMETHOD.
2. At the end of the method, add a loop over the internal table connections with reference
variable connection as a work area.
ENDLOOP.
3. In the loop, call functional method get_output for each instance in turn and write the
result to the console.
Hint:
You can use the call of method get_output directly as input for out-
>write( ).
out->write( connection->get_output( ) ).
ENDLOOP.
4. Activate the class. Execute it as a console app and analyze the console output.
a) Press Ctrl + F3 to activate the class.
1. For the first instance of class lcl_connection, replace the direct access to attributes
carrier_id and connection_id with a call of the instance method
set_attributes( ). Use code completion to insert the full signature of the method.
Hint:
Press Ctrl + Space after you typed the component select (->) to display a
list of available attributes and methods. Choose the method and then press
Shift + Enter to insert the full signature of the method.
a) Place the cursor in the next line after the first connection = NEW #( )..
d) Pass values to the importing parameters. Use the same literals that you used
previously to set the attributes of this instance.
e) Remove or comment the direct access to the instance attributes for this instance.
2. Handle the exception. Surround the method call with TRY. and ENDTRY.. Add a CATCH-
Block to handle exception CX_ABAP_INVALID_VALUE. Make sure the new instance is only
added to internal table connections if the method call was successful.
d) Between the CATCH statement and the ENDTRY statement add out-
>write( `Method call failed` ).
e) Move the APPEND statement up to between the method call and CATCH statement.
TRY.
connection->set_attributes(
EXPORTING
i_carrier_id = 'LH'
i_connection_id = '0400'
).
* connection->carrier_id = 'LH'.
* connection->connection_id = '0400'.
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
3. Repeat the previous step for the other two instances of class lcl_connection.
a) After this step, the implementation of method if_oo_adt_classrun~main should
look similar to this:
METHOD if_oo_adt_classrun~main.
* First Instance
**********************************************************************
connection = NEW #( ).
TRY.
connection->set_attributes(
EXPORTING
i_carrier_id = 'LH'
i_connection_id = '0400'
).
* connection->carrier_id = 'LH'.
* connection->connection_id = '0400'.
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
* Second instance
**********************************************************************
connection = NEW #( ).
TRY.
connection->set_attributes(
EXPORTING
i_carrier_id = 'AA'
i_connection_id = '0017'
).
* connection->carrier_id = 'AA'.
* connection->connection_id = '0017'.
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
* Third instance
**********************************************************************
connection = NEW #( ).
TRY.
connection->set_attributes(
EXPORTING
i_carrier_id = 'SQ'
i_connection_id = '0001'
).
* connection->carrier_id = 'SQ'.
* connection->connection_id = '0001'.
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
* Output
**********************************************************************
out->write( connection->get_output( ) ).
ENDLOOP.
ENDMETHOD.
In this exercise, you make the the static attribute of your class read-only and the instance
attributes private. You use a constructor to set their values.
Template:
Solution:
1. Set the visibility of the attribute carrier_id to private using a quick fix.
2. Set the visibility of the attribute connection_id to private using a quick fix.
2. Add an instance constructor to the local class lcl_connection using a quick fix. Ensure
that the constructor has importing parameters corresponding to attributes carrier_id
and connection_id.
5. In the constructor implementation, add a statement to increase the value of the static
attribute conn_counter by one. Make sure the statement is only executed if no exception
was raised.
6. Make sure that it is not possible to change the value of conn_counter from outside the
class.
Hint:
You can copy the parameter passing from the call of method
set_attributes for this instance.
4. Move the instance creation into the TRY block of the exception handling.
5. Repeat the previous steps for the other instances of your local class.
In this exercise, you make the the static attribute of your class read-only and the instance
attributes private. You use a constructor to set their values.
Template:
Solution:
e) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_CONSTRUCTOR, where ## stands for your group number.
1. Set the visibility of the attribute carrier_id to private using a quick fix.
a) Switch to the Local Types tab.
e) Check that the declaration of the attribute carrier_id has moved to the private
section.
2. Set the visibility of the attribute connection_id to private using a quick fix.
a) Go to the declaration of the attribute connection_id in the local class
lcl_connection.
d) Check that the declaration of attribute connection_id has moved to the private
section.
b) Press Ctrl + < to add a star sign (*) in front of each selected line.
c) Select all lines that belong to the implementation of the method set_attributes
including the corresponding ENDMETHOD. statement and press Ctrl + < again.
2. Add an instance constructor to the local class lcl_connection using a quick fix. Ensure
that the constructor has importing parameters corresponding to attributes carrier_id
and connection_id.
a) Place the cursor on the name of the class and press Ctrl + 1.
c) In the dialog box, ensure that carrier_id and connection_id are selected and
choose Finish.
METHODS constructor
IMPORTING
i_connection_id TYPE /dmo/connection_id
i_carrier_id TYPE /dmo/carrier_id
RAISING
cx_ABAP_INVALID_VALUE.
METHOD constructor.
me->connection_id = i_connection_id.
me->carrier_id = i_carrier_id.
ENDMETHOD.
5. In the constructor implementation, add a statement to increase the value of the static
attribute conn_counter by one. Make sure the statement is only executed if no exception
was raised.
a) Add the highlighted code:
me->connection_id = i_connection_id.
me->carrier_id = i_carrier_id.
conn_counter = conn_counter + 1.
ENDMETHOD.
6. Make sure that it is not possible to change the value of conn_counter from outside the
class.
a) Add READ-ONLY to the declaration of the static attribute conn_counter.
Hint:
You can copy the parameter passing from the call of method
set_attributes for this instance.
connection = NEW #(
i_carrier_id = 'LH'
i_connection_id = '0400'
).
b) Press Ctrl + < to add a star sign (*) in front of each selected line.
4. Move the instance creation into the TRY block of the exception handling.
a) Move the TRY. statement up, to before the instance creation.
TRY.
connection = NEW #(
i_carrier_id = 'LH'
i_connection_id = '0400'
).
* connection->set_attributes(
* EXPORTING
* i_carrier_id = 'LH'
* i_connection_id = '0400'
* ).
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
5. Repeat the previous steps for the other instances of your local class.
a) After this step, the implementation of the method if_oo_adt_classrun~main
should look similar to this:
METHOD if_oo_adt_classrun~main.
* First Instance
**********************************************************************
TRY.
connection = NEW #(
i_carrier_id = 'LH'
i_connection_id = '0400'
).
* connection->set_attributes(
* EXPORTING
* i_carrier_id = 'LH'
* i_connection_id = '0400'
* ).
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
* Second instance
**********************************************************************
TRY.
connection = NEW #(
i_carrier_id = 'AA'
i_connection_id = '0017'
).
APPEND connection TO connections.
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
* Third instance
**********************************************************************
TRY.
connection = NEW #(
i_carrier_id = 'SQ'
i_connection_id = '0001'
).
APPEND connection TO connections.
CATCH cx_abap_invalid_value.
out->write( `Method call failed` ).
ENDTRY.
* Output
**********************************************************************
LOOP AT connections INTO connection.
out->write( connection->get_output( ) ).
ENDLOOP.
ENDMETHOD.
In this exercise, you extend your local class with attributes for the departure airport and the
destination airport, and read the values for these attributes from a database table.
Template:
Solution:
Note:
The new attributes are not filled yet. In order to fill them we will add a SELECT
statement to the constructor in one of the next tasks of this exercise.
Table 2: Attributes
Attribute Name Scope Data Type
airport_from_id instance /DMO/AIRPORT_FROM_ID
3. Extend the implementation of the method get_output. Append more string templates to
the returning parameter r_output. Embed the new attributes as expressions into the
string templates.
1. Open the development object that contains the definition of the database table /DMO/
CONNECTION.
Which fields have the description Flight Reference Scenario: From Airport and Flight
Reference Scenario: To Airport?
3. After the ENDIF. statement, add a SELECT statement that reads a single record from
database table /DMO/CONNECTION.
4. Implement the FIELDS clause. Read the table fields airport_from_id and
airport_to_id.
Hint:
Use auto-completion (Ctrl + Space) to enter the field names.
5. Implement the WHERE condition. Restrict all key fields of the database table (except for
the client field) with the values of importing parameters i_carrier_id and
i_connection_id. Do not forget to escape the parameters with prefix @.
Hint:
Use auto-completion (Ctrl + Space) to enter the element names and
parameter names.
Why is it not necessary to specify the client field in the WERE condition?
6. Implement the INTO clause. Store the SELECT result in the attributes airport_from_id,
and airport_to_id. Do not forget to escape the attributes with prefix @.
Hint:
Use auto-completion (Ctrl + Space) to enter the attribute names.
7. Implement error handling after the SELECT statement. Check the content of the system
field sy-subrc. If it does not equal zero, raise exception CX_ABAP_INVALID_VALUE.
8. Activate the class. Execute it and analyze the console output. Check that the output for
the new attributes displays data.
In this exercise, you extend your local class with attributes for the departure airport and the
destination airport, and read the values for these attributes from a database table.
Template:
Solution:
e) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_SELECT, where ## stands for your group number.
Note:
The new attributes are not filled yet. In order to fill them we will add a SELECT
statement to the constructor in one of the next tasks of this exercise.
Table 2: Attributes
Attribute Name Scope Data Type
airport_from_id instance /DMO/AIRPORT_FROM_ID
PRIVATE SECTION.
DATA carrier_id TYPE /dmo/carrier_id.
DATA connection_id TYPE /dmo/connection_id.
ENDCLASS.
3. Extend the implementation of the method get_output. Append more string templates to
the returning parameter r_output. Embed the new attributes as expressions into the
string templates.
a) Navigate to the implementation of the method get_output.
1. Open the development object that contains the definition of the database table /DMO/
CONNECTION.
a) From the eclipse toolbar, choose Open ABAP Development Object or press Ctrl +
Shift + A.
Which fields have the description Flight Reference Scenario: From Airport and Flight
Reference Scenario: To Airport?
3. After the ENDIF. statement, add a SELECT statement that reads a single record from
database table /DMO/CONNECTION.
a) Add the highlighted code:
SELECT SINGLE
FROM /dmo/connection
4. Implement the FIELDS clause. Read the table fields airport_from_id and
airport_to_id.
Hint:
Use auto-completion (Ctrl + Space) to enter the field names.
c) After a comma and a blank press Ctrl + Space again and choose airport_to_id.
5. Implement the WHERE condition. Restrict all key fields of the database table (except for
the client field) with the values of importing parameters i_carrier_id and
i_connection_id. Do not forget to escape the parameters with prefix @.
Hint:
Use auto-completion (Ctrl + Space) to enter the element names and
parameter names.
Why is it not necessary to specify the client field in the WERE condition?
6. Implement the INTO clause. Store the SELECT result in the attributes airport_from_id,
and airport_to_id. Do not forget to escape the attributes with prefix @.
Hint:
Use auto-completion (Ctrl + Space) to enter the attribute names.
SELECT SINGLE
FROM /dmo/connection
FIELDS airport_from_id, airport_to_id
WHERE carrier_id = @i_carrier_id
AND connection_id = @i_connection_id
INTO ( @airport_from_id, @airport_to_id ).
7. Implement error handling after the SELECT statement. Check the content of the system
field sy-subrc. If it does not equal zero, raise exception CX_ABAP_INVALID_VALUE.
a) Add the following code after the SELECT statement:
IF sy-subrc <> 0.
RAISE EXCEPTION TYPE cx_abap_invalid_value.
ENDIF.
8. Activate the class. Execute it and analyze the console output. Check that the output for
the new attributes displays data.
a) Press Ctrl + F3 to activate the class.
In this exercise, you read from a CDS view entity rather than from the database table directly.
This provides you with comfortable access to the name of the airline as well.
Template:
Solution:
1. Open the development object that contains the definition of the CDS view entity /DMO/
I_Connection.
Which are the alias names for fields airport_from_id and airport_to_id?
Which element is described as Flight Reference Scenario: Carrier Name? What is the
element type?
Note:
The new attribute is not filled, yet. In order to fill it we will adjust the SELECT
statement in the next task of this exercise.
Table 3: Attributes
Attribute Name Scope Data Type
carrier_name instance /DMO/CARRIER_NAME
3. Extend the implementation of method get_output. Add the carrier name to the string
template with the carrier identification.
2. After the commented code, add a SELECT statement that reads a single record from
database table /DMO/I_Conncetion.
Hint:
Use auto-completion (Ctrl + Space) to enter the names.
4. Implement the WHERE condition. Restrict the key elements of CDS view entity with the
values of importing parameters i_carrier_id and i_connection_id. Do not forget to
escape the parameters with prefix @.
Hint:
Use auto-completion (Ctrl + Space) to enter the element names and
parameter names.
5. Implement the INTO clause. Store the SELECT result in attributes airport_from_id,
airport_to_id, and airline_name. Do not forget to escape the attributes with prefix
@.
Hint:
Use auto-completion (Ctrl + Space) to enter the attribute names.
6. Activate the class. Execute it and analyze the console output. Check that the output for
the new attributes displays data.
In this exercise, you read from a CDS view entity rather than from the database table directly.
This provides you with comfortable access to the name of the airline as well.
Template:
Solution:
e) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_CDS, where ## stands for your group number.
1. Open the development object that contains the definition of the CDS view entity /DMO/
I_Connection.
a) From the eclipse toolbar, choose Open ABAP Development Object or press Ctrl +
Shift + A.
Which are the alias names for fields airport_from_id and airport_to_id?
Which element is described as Flight Reference Scenario: Carrier Name? What is the
element type?
Note:
The new attribute is not filled, yet. In order to fill it we will adjust the SELECT
statement in the next task of this exercise.
Table 3: Attributes
Attribute Name Scope Data Type
carrier_name instance /DMO/CARRIER_NAME
PRIVATE SECTION.
DATA carrier_id TYPE /dmo/carrier_id.
DATA connection_id TYPE /dmo/connection_id.
3. Extend the implementation of method get_output. Add the carrier name to the string
template with the carrier identification.
a) Navigate to the implementation of method get_output.
b) Press Ctrl + < to add a star sign (*) in front of each selected line.
2. After the commented code, add a SELECT statement that reads a single record from
database table /DMO/I_Conncetion.
a) Add the highlighted code:
* SELECT SINGLE
* FROM /dmo/connection
* FIELDS airport_from_id, airport_to_id
* WHERE carrier_id = @i_carrier_id
* AND connection_id = @i_connection_id
* INTO ( @airport_from_id, @airport_to_id ).
SELECT SINGLE
FROM /DMO/I_Connection
Hint:
Use auto-completion (Ctrl + Space) to enter the names.
c) After a comma and a blank press Ctrl + Space again and choose
DestinationAirport.
d) After a comma and a blank, type in a backslash (\) , press Ctrl + Space and choose
_Airline.
e) Immediately after _Airline, type in a dash sign (-) , press Ctrl + Space and
choose Name.
4. Implement the WHERE condition. Restrict the key elements of CDS view entity with the
values of importing parameters i_carrier_id and i_connection_id. Do not forget to
escape the parameters with prefix @.
Hint:
Use auto-completion (Ctrl + Space) to enter the element names and
parameter names.
No, the element list of the CDS view entity does not contain the client field.
5. Implement the INTO clause. Store the SELECT result in attributes airport_from_id,
airport_to_id, and airline_name. Do not forget to escape the attributes with prefix
@.
Hint:
Use auto-completion (Ctrl + Space) to enter the attribute names.
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS DepartureAirport, DestinationAirport, \_Airline-Name
WHERE AirlineID = @i_carrier_id
AND ConnectionID = @i_connection_id
INTO ( @airport_from_id, @airport_to_id, @carrier_name ).
6. Activate the class. Execute it and analyze the console output. Check that the output for
the new attributes displays data.
a) Press Ctrl + F3 to activate the class.
In this exercise, you declare a structured attribute, fill it using a SELECT statement and
access the structure components.
Template:
Solution:
4. Declare a new private instance attribute details and type it with structure type
st_details..
1. Adjust the implementation of the method get_output. Replace any access to the
attributes airport_from_id, airport_to_id, and carrier_name with the
corresponding component of attribute details.
Hint:
Do not type in the component names manually! After typing the structure
component selector (-), press Ctrl + Space to get a list of all components.
3. Activate the class. Execute it and analyze the console output. Check that the output
displays data for all attributes.
In this exercise, you declare a structured attribute, fill it using a SELECT statement and
access the structure components.
Template:
Solution:
e) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_STRUCTURE, where ## stands for your group number.
TYPES:
BEGIN OF st_details,
DepartureAirport TYPE /dmo/airport_from_id,
DestinationAirport TYPE /dmo/airport_to_id,
AirlineName TYPE /dmo/carrier_name,
END OF st_details.
b) Press Ctrl + < to add a star sign (*) in front of each selected line.
4. Declare a new private instance attribute details and type it with structure type
st_details..
a) Add the highlighted code:
1. Adjust the implementation of the method get_output. Replace any access to the
attributes airport_from_id, airport_to_id, and carrier_name with the
corresponding component of attribute details.
Hint:
Do not type in the component names manually! After typing the structure
component selector (-), press Ctrl + Space to get a list of all components.
APPEND |--------------------------------| TO
r_output.
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS DepartureAirport, DestinationAirport, \_Airline-Name
WHERE AirlineID = @i_carrier_id
AND ConnectionID = @i_connection_id
* INTO ( @airport_from_id, @airport_to_id, @carrier_name ).
INTO @details.
SELECT SINGLE
FROM /DMO/I_Connection
FIELDS DepartureAirport, DestinationAirport, \_Airline-Name as
AirlineName
WHERE AirlineID = @i_carrier_id
AND ConnectionID = @i_connection_id
INTO CORRESPONDING FIELDS OF @details.
3. Activate the class. Execute it and analyze the console output. Check that the output
displays data for all attributes.
a) Press Ctrl + F3 to activate the class.
In this exercise, you declare a table-like attribute, fill it using a SELECT statement and access
the content.
Template:
Solution:
4. Declare a new private static attribute airports and type it with table type
tt_airports..
1. Add a class constructor to the local class lcl_connection using a quick fix.
2. In the class constructor, implement a SELECT statement that reads all data sets from the
CDS view entity /DMO/I_Airports into the static attribute Airports .
2. At the beginning of the method, read the details of the departure airport into a structured
data object departure.
Hint:
Use a table expression Airports[ ... ] and an inline declaration for the
data object departure.
3. Similarly, read the details of the destination airport into a structured data object
destination.
4. Use the component name of the two structures to add the airport names to the output.
5. Optional: Omit the structured data object and use the table expressions directly in the
string templates.
6. Activate the class. Execute it and analyze the console output. Check that the output
displays data for all attributes.
In this exercise, you declare a table-like attribute, fill it using a SELECT statement and access
the content.
Template:
Solution:
e) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_ITAB, where ## stands for your group number.
TYPES:
BEGIN OF st_details,
DepartureAirport TYPE /dmo/airport_from_id,
DestinationAirport TYPE /dmo/airport_to_id,
AirlineName TYPE /dmo/carrier_name,
END OF st_details.
TYPES:
BEGIN OF st_airport,
AirportId TYPE /dmo/airport_id,
Name TYPE /dmo/airport_name,
END OF st_airport.
TYPES:
BEGIN OF st_airport,
AirportId TYPE /dmo/airport_id,
Name TYPE /dmo/airport_name,
END OF st_airport.
4. Declare a new private static attribute airports and type it with table type
tt_airports..
a) Add the highlighted code at the end of the class definition:
ENDCLASS.
1. Add a class constructor to the local class lcl_connection using a quick fix.
a) Place the cursor on the name of the class and press Ctrl + 1.
2. In the class constructor, implement a SELECT statement that reads all data sets from the
CDS view entity /DMO/I_Airports into the static attribute Airports .
2. At the beginning of the method, read the details of the departure airport into a structured
data object departure.
Hint:
Use a table expression Airports[ ... ] and an inline declaration for the
data object departure.
3. Similarly, read the details of the destination airport into a structured data object
destination.
a) Add the highlighted code:
4. Use the component name of the two structures to add the airport names to the output.
a) Add the highlighted code:
5. Optional: Omit the structured data object and use the table expressions directly in the
string templates.
a) Comment the code lines where you fill the structures departure and destination.
6. Activate the class. Execute it and analyze the console output. Check that the output
displays data for all attributes.
In this exercise, you analyze the business object interface /DMO/I_AgencyTP to find out
about its structure and the data manipulation operations it offers.
2. Analyze the source code. Open the ABAP language help to find more information.
What is the purpose of the statements interface;, use draft;, and extensible?
How many entities does the business object interface consist of? What are the alias
names of these entities?
Where do you find the non-standard operations that the interface offers?
1. Navigate to the CDS view entity /DMO/I_AgencyTP and analyze the source code.
2. Navigate to the data source of the CDS view entity /DMO/I_AgencyTP and analyze the
source code.
2. Analyze the source code. Open the ABAP language help to find more information.
Why are the definition and implementation of the global class /dmo/bp_r_agencytp both
empty?
How many methods are defined in the local class lhc_agency? What is their purpose?
In this exercise, you analyze the business object interface /DMO/I_AgencyTP to find out
about its structure and the data manipulation operations it offers.
2. Analyze the source code. Open the ABAP language help to find more information.
What is the purpose of the statements interface;, use draft;, and extensible?
interface; states that this behavior definition does not belong to the business object
itself but rather to a released interface on top of the business object. use draft;
stipulates that this interface supports the handling of interim versions of data (draft
instances). extensible indicates that extensions of this interface by partners and
customers are supported.
How many entities does the business object interface consist of? What are the alias
names of these entities?
The business object interface consists of only one entity because the behavior definition
contains only one DEFINE BEHAVIOR FOR ... statement. The alias name is /DMO/
Agency.
The interface offers operations create, update, delete because the behavior contains the
statements use create;, use update;, and use delete;
Where do you find the non-standard operations that the interface offers?
Non-standard operations are listed after the keyword use action. Note, that all actions
in this interface are draft actions. They are related to the handling of interim versions of
data.
1. Navigate to the CDS view entity /DMO/I_AgencyTP and analyze the source code.
a) Go to the statement define behavior for /DMO/I_AgencyTP.
b) Hold down the Ctrl key and left-click on /DMO/I_AgencyTP. Alternatively, place the
cursor on /DMO/I_AgencyTP and press F3..
There is only one element with the prefix key. The name of this view element is AgencyID.
2. Navigate to the data source of the CDS view entity /DMO/I_AgencyTP and analyze the
source code.
a) Go to the code fragment as projection on /DMO/R_AgencyTP.
b) Hold down the Ctrl key and left-click on /DMO/R_AgencyTP. Alternatively, place the
cursor on /DMO/R_AgencyTP and press F3..
The CDS view entity /DMO/R_AgencyTP reads from the CDS view entity /DMO/I_Agency.
No. CDS view entity /DMO/R_AgencyTP reads its data using the keyword as select
from and not with as projection on. The CDS view entity /DMO/R_AgencyTP belongs
to the definition of the business object itself.
2. Analyze the source code. Open the ABAP language help to find more information.
managed determines that this is a business object and not an interface or a projection. It
also indicates that for this business object the standard operations create, update, delete
are handled by the framework.
Yes, the statement field ( readonly ) AgencyID; declares that element AgencyID
must nor be changed. Note, that this is the key element of the CDS view entity /DMO/
R_AgencyTP.
This statement defines a consistency check (validation) for the business object. The name
indicates that it checks the content of the element Name of the CDS view entity /DMO/
R_AgencyTP.
The addition defines the trigger conditions: When a new data set is created (standard
operation create) the check is always performed. When a data set is changed (standard
operation update) the check is only performed in case the value of the element Name has
changed.
b) Hold down the Ctrl key and left-click on /dmo/bp_r_agencytp. Alternatively, place
the cursor on /dmo/bp_r_agencytp and press F3..
Why are the definition and implementation of the global class /dmo/bp_r_agencytp both
empty?
The global class /dmo/bp_r_agencytp is a behavior pool. It serves as a wrapper for one
or more local classes. The behavior implementation itself is located in those local classes.
How many methods are defined in the local class lhc_agency? What is their purpose?
There are five methods. Four methods implement validations (addition VALIDATE ON
SAVE) . One method implements authorization checks (addition FOR GLOBAL
AUTHORIZATION.
In this exercise, you use EML to perform the standard operation update for the root entity of
the business object /DMO/R_AGENCYTP. To avoid later inconsistencies, you do not access the
business object directly but via its released stable interface /DMO/_I_AGENCYTP.
Template:
none
Solution:
3. Check the current name of the travel agency with ID “0700##”, where ## stands for your
group number.)
1. Create a new ABAP class called ZCL_##_EML, where ## stands for your group number.
Ensure that the class implements the interface IF_OO_ADT_CLASSRUN.
2. Fill the internal table with a single line containing “0700##” as the value for the column
AGENCYID (where ## stands for your group number) and any new value for the column
NAME.
3. Implement an EML statement MODIFY ENTITIES for the business object interface /DMO/
I_AgencyTP. Update the data of the root entity, ensuring that only the field NAME is
changed.
Hint:
Remember that the interface behavior defines alias name /DMO/Agency for
the root entity /DMO/I_AgencyTP.
4. In order to get some visible result from the application, write a text literal to the console
using the method out->write.
6. Check whether the new name has been written to the database.
7. Add the COMMIT ENTITIES statement to your code to commit the changes.
8. Activate and test the class again. Confirm that the changes are now in the database.
In this exercise, you use EML to perform the standard operation update for the root entity of
the business object /DMO/R_AGENCYTP. To avoid later inconsistencies, you do not access the
business object directly but via its released stable interface /DMO/_I_AGENCYTP.
Template:
none
Solution:
3. Check the current name of the travel agency with ID “0700##”, where ## stands for your
group number.)
a) Scroll down to the entry with the value “0700##” in the column AgencyID and take a
note of the value in the column Name.
1. Create a new ABAP class called ZCL_##_EML, where ## stands for your group number.
Ensure that the class implements the interface IF_OO_ADT_CLASSRUN.
a) Choose File → New → ABAP Class.
b) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_EML, where ## is your group number. Enter a description.
d) Enter IF_OO_ADT_CLASSRUN. When the interface appears in the hit list, double-click it
to add it to the class definition.
e) Choose Next.
2. Fill the internal table with a single line containing “0700##” as the value for the column
AGENCYID (where ## stands for your group number) and any new value for the column
NAME.
a) Add some code similar to the highlighted code:
3. Implement an EML statement MODIFY ENTITIES for the business object interface /DMO/
I_AgencyTP. Update the data of the root entity, ensuring that only the field NAME is
changed.
Hint:
Remember that the interface behavior defines alias name /DMO/Agency for
the root entity /DMO/I_AgencyTP.
4. In order to get some visible result from the application, write a text literal to the console
using the method out->write.
a) After the MODIFY ENTITIES statement, add the following code:
6. Check whether the new name has been written to the database.
a) Return to the data preview for CDS view entity /DMO/I_AgencyTP.
Why has your data change not yet arrived in the database?
Your program stores the changes in the application buffer, but they are not written to
the database until a COMMIT ENTITIES statement.
7. Add the COMMIT ENTITIES statement to your code to commit the changes.
a) Return to the method IF_OO_ADT_CLASSRUN~MAIN in your global class ZCL_##_EML.
METHOD if_oo_adt_classrun~main.
COMMIT ENTITIES.
ENDMETHOD.
8. Activate and test the class again. Confirm that the changes are now in the database.
a) Press Ctrl + F3 to activate the class.
c) Return to the data preview for the CDS view entity /DMO/I_AgencyTP.
In the exercises of this unit, you will create an OData UI service. This UI service will form the
basis for an application that allows you to change the price of flights. Firstly, you create a
dedicated package for the required development objects. Then you copy a database table and
fill it with data.
Template:
Solution:
Attribute Value
Name ZS4D400_##_RAP, where ## stands for your
group number
Description Objects for OData UI Service
Add to Favorite Packages Checked
Superpackage ZS4D400_##, , where ## stands for your
group number
Package Type Development
Software Component ZLOCAL
Application Component CA
Transport Layer
1. Create a sub package under your own package ZS4D400_## (where ## stands for your
group number).
2. In the copy, adjust the source code of the method IF_OO_ADT_CLASSRUN~MAIN. Change
the value of the constant table_name to the name of your own database table.
In the exercises of this unit, you will create an OData UI service. This UI service will form the
basis for an application that allows you to change the price of flights. Firstly, you create a
dedicated package for the required development objects. Then you copy a database table and
fill it with data.
Template:
Solution:
Attribute Value
Name ZS4D400_##_RAP, where ## stands for your
group number
Description Objects for OData UI Service
Add to Favorite Packages Checked
Superpackage ZS4D400_##, , where ## stands for your
group number
Package Type Development
Software Component ZLOCAL
Application Component CA
Transport Layer
1. Create a sub package under your own package ZS4D400_## (where ## stands for your
group number).
a) In the Project Explorer, right-click on your ABAP package ZS4D400_## and choose
New → ABAP Package .
b) Enter the package name ZS4D400_##_RAP where ## stands for your group number.
e) Ensure that the field Superpackage contains the name of your already existing
package.
g) Choose Next.
k) Choose Next.
c) In the Project Explorer view, right-click database table /LRN/S4D400_APT to open the
context menu.
e) Enter the name of your package ZS4D400_##_RAP in the Package field. In the Name
field, enter the name Z##FLIGHT, where ## stands for your group number.
e) Enter the name of your package in the Package field. In the Name field, enter the name
ZCL_##_COPY, where ## stands for your group number.
2. In the copy, adjust the source code of the method IF_OO_ADT_CLASSRUN~MAIN. Change
the value of the constant table_name to the name of your own database table.
a) Make sure the value of the constant euqls the name of your database table.
c) Check the Console view. The last output should read: <...> was filled with data. If the
output reads <...> is not a table of the right type. make sure a database table of that
name exists, is active, and is an exact copy of the template table.
In this exercise, you generate the repository objects for an OData UI Service and preview the
service as an SAP Fiori app.
Template:
none
Solution:
You completed the previous exercises. You created the database table Z##FLIGHT (where ##
is your group number) and the database table contains data.
1. Start the object generator for your database table Z##FLIGHT(where ## is your group
number).
3. Ensure that the development objects are created in your sub package ZS4D400_##_RAP.
Caution:
Do not choose Next before you have entered all data.
6. Enter some text in the field Flight Price , for example a and a long text in the separate field
Currency Code (at least 6 characters), for example abcdef.
7. Enter abc in the second currency code field and a negative value in the Flight Price.
In this exercise, you generate the repository objects for an OData UI Service and preview the
service as an SAP Fiori app.
Template:
none
Solution:
You completed the previous exercises. You created the database table Z##FLIGHT (where ##
is your group number) and the database table contains data.
1. Start the object generator for your database table Z##FLIGHT(where ## is your group
number).
a) In the Project Explorer, expand the following path: Favorite
Packages → ZS4D400_## → ZS4D400_##_RAP → Dictionary → Database Tables
(where ## is your group number). Alternatively, open the definition of database table
Z##FLIGHT and, if necessary, link the Project Explorer view with the editor.
b) In the Project Explorer view, right-click database table Z##FLIGHT to open the context
menu.
c) From the context menu, choose Generate ABAP Repository Object ....
a) On the left-hand side of the dialog box, choose ABAP RESTful Application
Programming Model → OData UI Service.
3. Ensure that the development objects are created in your sub package ZS4D400_##_RAP.
a) When the window reads Enter Package at the top, ensure that the field Package
contains ZS4D400_##_RAP.
Caution:
Do not choose Next before you have entered all data.
a) On the left-hand side of the dialog box, choose Data Model. In the right-hand pane,
enter the Data Definition Name ZR_##_Flight and Alias Name Flight.
b) On the left-hand side of the dialog box, choose Behavior. In the right-hand pane, enter
the Behavior Implementation Class ZBP_R_##FLIGHT and the Draft Table Name
Z##FLIGHT_D.
c) On the left-hand side of the dialog box, choose Service Projection. In the right-hand
pane, enter the Name ZC_##Flight.
d) On the left-hand side of the dialog box, choose Service Projection Behavior. In the right-
hand pane, enter the Behavior Implementation Class ZBP_C_##FLIGHT.
e) On the left-hand side of the dialog box, choose Service Definition. In the right-hand
pane, enter the Name ZUI_##FLIGHT_O4.
f) On the left-hand side of the dialog box, click Service Binding. In the right-hand pane,
enter the Name ZUI_##FLIGHT_O4 and ensure the Binding Type is set to OData V4 -
UI.
b) When you are sure you have entered all names correctly choose Next.
b) Expand all sub nodes of the package to see the names of the generated development
objects.
c) In the Services section on the left-hand side, check the status of the service. If field
Local Service Endpoint contains the value Unpublished, the service is not yet published.
Edit,Delete, Share.
Fields Airline ID, Flight Number, Flight Date belong to the primary key of the database
table. Changing the primary key is never a good idea. By default, the generator sets all key
fields to write protected during update.
6. Enter some text in the field Flight Price , for example a and a long text in the separate field
Currency Code (at least 6 characters), for example abcdef.
No. The generated application includes technical input checks. Field Flight Price is based
on a numeric type and the technical type of field Currency Code is 5 characters long.
7. Enter abc in the second currency code field and a negative value in the Flight Price.
Yes, the checks for positive prices and valid currency codes are business logic. They have
to be implemented in the behavior of the business object.
In this exercise you define and implement validations for the price and currency code.
Template:
none
Solution:
You completed the previous exercises. You created and filled the database table Z##FLIGHT
(where ## is your group number) and generated the development objects for an OData UI
Service.
Hint:
Use code-completion wherever possible to enter the code.
3. Use a quick fix to create the validation implementation method in the behavior handler
class.
4. At the beginning of the method validatePrice, declare a structured data object that
you type with the line type of failed-flight (suggested name: failed_record).
Similarly, declare a structured data object that you type with the line type of reported-
flight (suggested name: reported_record).
Note:
These structures will be used to add rows to failed-flight and reported-
flight, in case the validation finds an error.
5. Use a READ ENTITIES statement to read the user input from the transactional buffer. Use
the statement IN LOCAL MODE and ensure that only the key fields and the field Price are
read. Use an inline declaration for the result set (suggested name: flights).
Note:
It is not necessary to list the key fields after the FIELDS addition. READ
ENTITIES always reads the key fields.
6. Implement a loop over the data that you just read. Use an inline declaration for the work
area (suggested name: flight).
7. Inside the loop, check if the component Price is greater than zero. If not, fill the structure
failed_record with the key of the current flight and add the new code row to failed-
flight. Similarly, fill structure reported_record with the key of the current flight and
add the new code row to reported-flight.
Hint:
In draft-enabled business objects, it is recommended that you use the
component %tky to assign the key.
8. Before the APPEND statement fill the component %msg of the structure
reported_record with a reference to a message object. To create the message object,
call the method me->new_message with the following input:
number '101'
severity if_abap_behv_message=>severity-error
Hint:
Use code-completion wherever possible to enter the code.
2. Activate the behavior definition and use a quick fix to create the validation
implementation.
4. For the flights that need to be validated, read the field CurrencyCode and the key fields
from the transactional buffer and implement a loop over the data.
5. Inside the loop, check if the value of the component CurrencyCode is valid.
Hint:
Implement a SELECT statement with CDS view entity I_Currency as data
source and Currency = flight-CurrencyCode as WHERE clause.
6. If the currency code is not valid, add a row to failed-flight and reported-flight.
Do not forget to fill reported_record-%msg with a reference to a suitable message
object. To create the message object, call the method me->new_message with the
following input:
Parameter name Value
id '/LRN/S4D400'
number '102'
severity if_abap_behv_message=>severity-error
v1 flight-currencycode
3. In the app, display a list of flights, open the details for one of the flights and switch to
change mode.
4. Make some changes to the price and currency code, and then choose Save. Analyze the
validations in the debugger.
Note:
Enter the currency code in the second currency code field.
In this exercise you define and implement validations for the price and currency code.
Template:
none
Solution:
You completed the previous exercises. You created and filled the database table Z##FLIGHT
(where ## is your group number) and generated the development objects for an OData UI
Service.
Hint:
Use code-completion wherever possible to enter the code.
create;
update;
delete;
3. Use a quick fix to create the validation implementation method in the behavior handler
class.
a) Position the cursor on the name of the validation (validatePrice) and choose Ctrl +
1.
4. At the beginning of the method validatePrice, declare a structured data object that
you type with the line type of failed-flight (suggested name: failed_record).
Similarly, declare a structured data object that you type with the line type of reported-
flight (suggested name: reported_record).
Note:
These structures will be used to add rows to failed-flight and reported-
flight, in case the validation finds an error.
5. Use a READ ENTITIES statement to read the user input from the transactional buffer. Use
the statement IN LOCAL MODE and ensure that only the key fields and the field Price are
read. Use an inline declaration for the result set (suggested name: flights).
Note:
It is not necessary to list the key fields after the FIELDS addition. READ
ENTITIES always reads the key fields.
a) After the declarations, add the following code, replacing ## with your group number:
6. Implement a loop over the data that you just read. Use an inline declaration for the work
area (suggested name: flight).
a) After the EML statement, add following code:
ENDLOOP.
7. Inside the loop, check if the component Price is greater than zero. If not, fill the structure
failed_record with the key of the current flight and add the new code row to failed-
flight. Similarly, fill structure reported_record with the key of the current flight and
add the new code row to reported-flight.
Hint:
In draft-enabled business objects, it is recommended that you use the
component %tky to assign the key.
IF flight-price <= 0.
failed_record-%tky = flight-%tky.
APPEND failed_record TO failed-flight.
reported_record-%tky = flight-%tky.
APPEND reported_record TO reported-flight.
ENDIF.
8. Before the APPEND statement fill the component %msg of the structure
reported_record with a reference to a message object. To create the message object,
call the method me->new_message with the following input:
number '101'
severity if_abap_behv_message=>severity-error
failed_record-%tky = flight-%tky.
APPEND failed_record TO failed-flight.
reported_record-%tky = flight-%tky.
reported_record-%msg =
new_message(
id = '/LRN/S4D400'
number = '101'
severity = if_abap_behv_message=>severity-error
).
ENDIF.
ENDLOOP.
Hint:
Use code-completion wherever possible to enter the code.
create;
update;
delete;
2. Activate the behavior definition and use a quick fix to create the validation
implementation.
a) Press Ctrl + F3 to activate the behavior definition.
4. For the flights that need to be validated, read the field CurrencyCode and the key fields
from the transactional buffer and implement a loop over the data.
a) After the declarations, add the following code, replacing ## with your group number:
ENDLOOP.
5. Inside the loop, check if the value of the component CurrencyCode is valid.
Hint:
Implement a SELECT statement with CDS view entity I_Currency as data
source and Currency = flight-CurrencyCode as WHERE clause.
exists = abap_false.
ENDIF.
Note:
There are different ways to implement such an existence check. This
example has the advantage that no data is actually retrieved from the
database. The FIELDS list contains only a constant. However, it is
technically not possible to entirely omit the FIELDS list and the INTO
clause .
6. If the currency code is not valid, add a row to failed-flight and reported-flight.
Do not forget to fill reported_record-%msg with a reference to a suitable message
object. To create the message object, call the method me->new_message with the
following input:
Parameter name Value
id '/LRN/S4D400'
number '102'
severity if_abap_behv_message=>severity-error
v1 flight-currencycode
failed_record-%tky = flight-%tky.
APPEND failed_record TO failed-flight.
reported_record-%tky = flight-%tky.
reported_record-%msg =
new_message(
id = '/LRN/S4D400'
number = '102'
severity = if_abap_behv_message=>severity-error
v1 = flight-currencycode
).
b) Open your service binding. In the Entity Set and Associations list on the right-hand
side, first choose entity Flight and then choose Preview....
3. In the app, display a list of flights, open the details for one of the flights and switch to
change mode.
a) Proceed as you have done in previous exercises.
4. Make some changes to the price and currency code, and then choose Save. Analyze the
validations in the debugger.
Note:
Enter the currency code in the second currency code field.
In this exercise, you adjust the user interface of your app; either directly by editing the UI-
metadata, or indirectly by adjusting the business object behavior and the data model
projection.
Template:
none
Solution:
You completed the previous exercises. You created and filled the database table Z##FLIGHT
(where ## is your group number) and generated the development objects for an OData UI
Service.
Note:
These changes should only apply to your OData UI Service. The business object
itself should still support the creation and deletion of flights, and the changing of
the airplane type.
1. In the behavior projection for your service, disable the standard operations create and
delete.
2. In the behavior projection of your business object, set the field PlaneTypeID to read-only.
1. Edit the Metadata Extension of the projection view (ZC_##Flight). Remove all UI
annotations for the fields LocalCreatedBy, LocalCreatedAt, LocalLastChangedBy,
LocalLastChangedAt, and LastChangedAt and replace them with @UI.hidden:
true.
2. Remove the @UI.selectionField annotation for all elements except for the elements
CarrierID and ConnectionID.
3. Change the position of the PlaneTypeID field on the object page. Place it between
FlightDate and Price.
Hint:
The position on the object page is specified with annotation
@UI.identification.
1. Edit the definition of the projection view ( ZC_##Flight). Annotate the view element
CurrencyCode with annotation @Consumption.valueHelpDefinition: [{ }]. Use
I_CurrencyStdVH as the value for the subannotation entity.name and Currency as
the value for the subannotation entity.element.
Note:
Currency is the name of the key element of CDS view I_CurrencyStdVH.
2. On the report list page, verify that the buttons Create and Delete have disappeared.
3. Verify that there are two selection fields at the top of the report list page. Test their
functionality.
Hint:
Be aware that the selection fields support the entry of multiple values and
ranges.
4. For any data set, navigate to the object page. Verify that the Delete button has
disappeared.
5. Verify that field Plane Type is displayed after field Flight Date and before field Flight Price.
In this exercise, you adjust the user interface of your app; either directly by editing the UI-
metadata, or indirectly by adjusting the business object behavior and the data model
projection.
Template:
none
Solution:
You completed the previous exercises. You created and filled the database table Z##FLIGHT
(where ## is your group number) and generated the development objects for an OData UI
Service.
Note:
These changes should only apply to your OData UI Service. The business object
itself should still support the creation and deletion of flights, and the changing of
the airplane type.
1. In the behavior projection for your service, disable the standard operations create and
delete.
a) Open the behavior projection ZC_##Flight (where ## is your group number).
b) Add comment markers in front of the statement use create; and use delete;.
To add the comment markers, proceed as usual: select the code rows you want to
comment and press Ctrl + <.
Your code should then look like this:
// use create;
use update;
// use delete;
2. In the behavior projection of your business object, set the field PlaneTypeID to read-only.
Note:
The precise position of the statement is not important. We suggest that
you place it before the use ... statements.
1. Edit the Metadata Extension of the projection view (ZC_##Flight). Remove all UI
annotations for the fields LocalCreatedBy, LocalCreatedAt, LocalLastChangedBy,
LocalLastChangedAt, and LastChangedAt and replace them with @UI.hidden:
true.
a) Open the metadata extension ZC_##FLIGHT where ## is your group number.
@UI.hidden: true
LocalCreatedBy;
@UI.hidden: true
LocalCreatedAt;
@UI.hidden: true
LocalLastChangedBy;
@UI.hidden: true
LocalLastChangedAt;
@UI.hidden: true
LastChangedAt;
2. Remove the @UI.selectionField annotation for all elements except for the elements
CarrierID and ConnectionID.
a) Adjust the code as follows:
@UI.identification: [ {
position: 30 ,
label: 'Flight Date'
} ]
@UI.lineItem: [ {
position: 30 ,
label: 'Flight Date'
} ]
FlightDate;
@UI.identification: [ {
position: 40 ,
label: 'Flight Price'
} ]
@UI.lineItem: [ {
position: 40 ,
label: 'Flight Price'
} ]
Price;
@UI.identification: [ {
position: 50 ,
label: 'Currency Code'
} ]
@UI.lineItem: [ {
position: 50 ,
label: 'Currency Code'
} ]
CurrencyCode;
@UI.identification: [ {
position: 60 ,
label: 'Plane Type'
} ]
@UI.lineItem: [ {
position: 60 ,
label: 'Plane Type'
} ]
PlaneTypeId;
3. Change the position of the PlaneTypeID field on the object page. Place it between
FlightDate and Price.
Hint:
The position on the object page is specified with annotation
@UI.identification.
@UI.identification: [ {
position: 35,
label: 'Plane Type'
} ]
@UI.lineItem: [ {
position: 60 ,
label: 'Plane Type'
} ]
PlaneTypeId;
1. Edit the definition of the projection view ( ZC_##Flight). Annotate the view element
CurrencyCode with annotation @Consumption.valueHelpDefinition: [{ }]. Use
I_CurrencyStdVH as the value for the subannotation entity.name and Currency as
the value for the subannotation entity.element.
Note:
Currency is the name of the key element of CDS view I_CurrencyStdVH.
a) Open the definition of CDS view entity ZC_##FLIGHT where ## is your group number.
@Consumption.valueHelpDefinition: [{ entity.name:
'I_CurrencyStdVH',
entity.element: 'Currency' }]
b) Open your service binding. In the Entity Set and Associations list on the right-hand
side, first choose entity Flight and then choose Preview....
2. On the report list page, verify that the buttons Create and Delete have disappeared.
a) Proceed as you have done in previous exercises.
3. Verify that there are two selection fields at the top of the report list page. Test their
functionality.
Hint:
Be aware that the selection fields support the entry of multiple values and
ranges.
a) Enter a value in the selection field Airline ID (for example: “LH”) and choose Go.
4. For any data set, navigate to the object page. Verify that the Delete button has
disappeared.
a) Proceed as you have done in previous exercises.
5. Verify that field Plane Type is displayed after field Flight Date and before field Flight Price.
a) Proceed as you have done in previous exercises.