You are on page 1of 12

NEW ABAP LANGUAGE FEATURES

CD263
Exercises / Solutions

Frank Bertelsmeier and Holger Janz / SAP AG


All exercises are done by a team of two. Since all teams work within the same SAP system, the names of global
objects like programs or classes must be unique for each team. Therefore global names used in this description end
with XX. When copying the template programs for the exercises please substitute the ending XX in all global names
with your team number (e.g. program ZTE10_PROGRAM_XX is copied to ZTE10_PROGRAM_01 for team number 1
and ZTE10_PROGRAM_99 for team number 99).

Since the workshop CD 263 will be held several times all template programs for the exercises additionally end with a
letter for the location and a number to indicate the occurrence for the current session. So, right before the XX for the
team number you find the mnemonic B1 for the workshop in Berlin, L1 for the first one in Las Vegas and L2 for the
second in Las Vegas:

Suffix Location Example


st
B1_XX Berlin, 1 hands-on workshop CD263 ZTE10_DYNW_EX_B1_XX
st
L1_XX Las Vegas, 1 hands-on workshop CD263 ZTE10_DYNW_EX_L1_XX
L2_XX Las Vegas, 2nd hands-on workshop CD263 ZTE10_DYNW_EX_L2_XX

Please save all objects you create as system local objects ($TMP) so no transport request is necessary.

Extended Expressions
Exercise 1 – String Templates and String Expressions
String Templates are especially well suited to create technical documents like HTML or XML documents. The objective
of this exercise is to add and extend the HTML output of a database selection from table SFLIGHT making use of the
new string expressions. The resulting HTML is then displayed in a browser popup window.

Problem Description
 First, please make your own copy of program ZTE10_STRING_EX_mn_xx (replacing mn_xx with the suffix from the
table above and your team number).
 The report already contains an implementation to create and display a HTML page, but the selected data from the
SFLIGHT database table is not yet filled in. Your task is to add this code taking advantage of the string expressions,
especially the string template formatting with | { } |. To let the string template spread over several lines you can use
“&” to concatenate the string template parts indicated by | |.
 Hint: In case you have to deal with arbitrary text the built-in function escape( ) might be helpful to provide a HTML
appropriate escaping for characters in the variable part of the output text which might have a special meaning in
HTML.
 Look at the coding in method create_flighttab_html ( ) which creates the resulting HTML string to be
displayed on the HTML page. Add the string expression within the LOOP AT flights … ENDLOOP to create the
table content using string templates and add the content of the SFLIGHT table fields “Airline”, “Flight No.”, “Date”,
“Airfare”, “Planetype” and “Free Seats” as given in the HTML table header line:

"COMPLETE THIS METHOD IMPLEMENTATION USING STRING TEMPLATES


METHOD create_flighttab_html.
[...]
LOOP AT flights ASSIGNING <flight>.
p_html = p_html &&
| Enhance this string templates | &
| to generate html ...|.
ENDLOOP.
ENDMETHOD.

 Hint: The HTML tags <tr> and </tr> are used to start and end a new table line. The content of one table cell is
specified between the HTML tags <td> and </td>. To add a “non-breaking” space at the end of each cell (to keep
the table formatting) you can use the HTML notation “&nbsp;”. The overall pattern is mentioned in the comment
block in the coding.

2
Solution 1 – String Templates and String Expressions
You just need one string expression to combine the HTML tags with the content of internal table flights to fill in the
data into the HTML table:

LOOP AT flights ASSIGNING <flight>.


p_html = p_html &&
|<tr>| &
|<td>{ <flight>-carrid }&nbsp;</td>| &
|<td>{ <flight>-connid }&nbsp;</td>| &
|<td>{ <flight>-fldate }&nbsp;</td>| &
|<td>{ <flight>-price } &nbsp;{ <flight>-currency }</td>| &
|<td>{ escape( val = <flight>-planetype format = e_html ) }&nbsp;</td>| &
|<td>{ <flight>-seatsmax - <flight>-seatsocc }&nbsp;</td>| &
|</tr>|.
ENDLOOP.

The class constant e_html (defined in class demo) serves as an abbreviation for the constant
cl_abap_format=>e_html_text used as format parameter of the built-in function escape.

Internal Tables
Exercise 2 – Secondary keys for internal tables
In this exercise you improve the performance of existing coding processing quite large internal tables by using
secondary keys.

Problem Description
In Report ZTE10_SCND_EX_mn_xx (replacing mn_xx with the suffix from the table in the introduction) there is a
method total_quantity_of_items to gather the following information for all orders of a customer (given by a
customer_id):
 Internal item ID (internal_item_id)
 Total number of ordered items (quantity)

This is done by looping over the order item table to find all orders belonging to a given customer and then to read the
internal item ID from another table with the supplier ID and the item ID of the supplier, which identify any item uniquely
(provided by the order table).

The performance of this method is not very good. Your goal is to improve the performance using secondary keys.
 Again, please make your own copy of program ZTE10_SCND_EX_mn_xx (replacing mn_xx with the suffix from the
table in the introduction and your team number) and activate it.
 Execute the program by pressing F8. As you can see, the performance of the existing code is not very good.
 Define an appropriate secondary key for the internal table it_order_item according to the where condition of the
outer loop in method total_quantity_of_items. What happens if you call the syntax check right after adding
the secondary key definition?
 What about the LOOP statement? How to make use of the new secondary key in the LOOP statement?
 Repeat the same steps for the second internal table ts_item_mapping. Which type of secondary key would be
appropriate here? Adapt the READ statement accordingly.
 Debug the coding, display it_order_item in the debugger’s table tool. Observe the status of the secondary key
(which should be out-dated) right before the loop is entered.
 Surprisingly, the performance improvement is only moderate since for non-unique secondary keys the key
information is built-up lazy when first using the key. The runtime needed to built-up the keys is also measured with
the call of res_handle->total_quantity_of_items( customer_id = customer ).
 Use the method cl_abap_itab_utilities=>flush_itab_keys to update the non-unique secondary key for
table it_order_item before the measurement, e.g. in method init_order_item_table.
 Advanced/optional: Remove the comments for method adapt_item( ) and debug it (with the given values).
Observe the status of the secondary key during the changes, try to update the key in the debugger.

3
Solution 2 – Secondary keys for internal tables
The solution is implemented in ABAP program ZTE10_SCND_SOL. The relevant definition of the secondary keys might
look like this:

DATA:
it_order_item TYPE SORTED TABLE OF ts_order_item
WITH UNIQUE KEY order_id
WITH NON-UNIQUE SORTED KEY key_cust
COMPONENTS customer_id,

it_item_mapping TYPE SORTED TABLE OF ts_item_mapping


WITH UNIQUE KEY internal_item_id
WITH UNIQUE SORTED KEY key_supplier
COMPONENTS supplier_id supplier_item_id.

The adapted coding of method total_quantity_of_items might look like this:

" If the non-unique secondary key hasn't been used beforehand,


" it is outdated up to now (-> key_status, debugger flush)
LOOP AT it_order_item USING KEY key_cust ASSIGNING <fs1>
WHERE customer_id = customer_id.

" Get the internal_item_id


READ TABLE it_item_mapping ASSIGNING <fs2>
WITH KEY key_supplier
COMPONENTS supplier_id = <fs1>-supplier_id
supplier_item_id = <fs1>-supplier_item_id .

wa-internal_item_id = <fs2>-internal_item_id.
wa-quantity = <fs1>-quantity.
APPEND wa TO it_res.
ENDLOOP.

Exceptions
Exercise 3 – Resumable Exceptions
In this exercise you extend a generic storage service to store the content of an arbitrary internal table in a file on the
application server and retrieve the content again later on.

Problem Description
 Again, please make your own copy of the storage service class ZCL_TABLE_STORAGE_EX_mn_xx (replacing mn_xx
with the suffix from the table in the introduction and your team number) and activate it.
 Copy the small test program ZTE10_RESEXCP_EX_mn_xx that uses the service (replacing mn_xx with the suffix
from the table in the introduction and your team number) and activate it.
 If you execute the test program an exception message occurs (“Disk is full, clear space”) and the displayed result list
only shows 5 entries instead of 11 original entries that should be stored to file.

4
 Internally, the method STORE_LINE of class ZCL_TABLE_STORAGE_EX_mn_xx throws the exception object of class
ZCX_DISK_FULL whenever the number of stored table lines (=LINES) exceeds a certain limit MAX_LINES = 5, a
constant defined in the service class. This exception is used to simulate a resource limitation (“disk full”).

 The thrown exception object is caught in the test program ZTE10_RESEXCP_EX_mn_xx (statement CATCH
ZCX_DISK_FULL). The exception handler just writes the message and calls the method CLEAR_SPACE of class
ZTE10_RESEXCP_EX_mn_xx to reset the counter for the stored lines.

Although the CLEAR_SPACE method solves the resource limitation the processing to store the table content in a file
terminates when the exception is raised.

Your task is to modify your storage service so it is able to continue even if a resource limitation is reached.

 Make the exception ZCX_DISK_FULL a resumable exception in your copy of class


ZCL_TABLE_STORAGE_EX_mn_xx. Change the coding in method STORE_LINE in a way that the thrown exception
is resumable, i.e. a handler of the exception may decide to continue the execution.
 Extend the signature definition of method STORE_LINE as well as method STORE_TABLE which calls STORE_LINE
and inform the client of your service that the exception ZCX_DISK_FULL is thrown as a resumable exception.
 Modify your program ZTE10_RESEXCP_EX_mn_xx so that the exception handler may decide to continue, i.e. the
exception is caught before unwinding the call stack.
 Don’t call RESUME yet, just establish the prerequisites. Run the program under the control of the debugger and
observe the different behavior.
 Get rid of the resource limit and continue. Inside of the handler get rid of the resource limitation. Just call method
CLEAR_SPACE inside of the storage service class that resets the LINES attribute of the storage object. Call this
method inside of the handler, then use RESUME. Examine the program under debugger control.

5
Solution 3 – Resumable Exceptions
The first part of the solution is implemented in method STORE_LINE of ABAP class ZCL_TABLE_STORAGE_EX_SOL.
The exception of type ZCX_DISK_FULL is to be raised as a resumable exception:
METHOD STORE_LINE.
DATA str TYPE string.
FIELD-SYMBOLS <field> TYPE any.

WHILE lines >= max_lines.


RAISE RESUMABLE EXCEPTION type zcx_disk_full
EXPORTING
limit = max_lines.
ENDWHILE.
DO.
ASSIGN COMPONENT sy-index OF STRUCTURE line TO <field>.
IF sy-subrc <> 0. EXIT. ENDIF.
str = <field>.
TRANSFER str TO name.
ENDDO.
TRANSFER sy-uline(50) TO name.
ADD 1 TO lines.
ENDMETHOD.

Besides rasing an exception as resumable exception it is necessary to preserve this property during propagation of the
exception object. To achieve this the signature of methods STORE_LINE and STORE_TABLE (defined in class
ZCL_TABLE_STORAGE_EX_SOL) must be extended to indicate that the exception is propagated as a resumable
exception:
class ZCL_TABLE_STORAGE_EX_SOL definition.
public section.
methods STORE_TABLE
importing
!ITAB type ANY TABLE
raising
resumable(ZCX_DISK_FULL) .
[…]
private section.
methods STORE_LINE
importing
!LINE type ANY
raising
resumable(ZCX_DISK_FULL) .
[…]
endclass.

The second part of the solution is implemented in ABAP program ZTE10_RESEXCP_EX_SOL. The exception handler
might look like this:
TRY.
tabstore->store_table( emp_tab ).
CATCH BEFORE UNWIND zcx_disk_full INTO excp.
IF excp->is_resumable = abap_true.
WRITE / 'Disk is full, clear space'.
tabstore->clear_space( ).
RESUME.
ELSE.
WRITE / 'Disk is full!'.
ENDIF.
ENDTRY.
The attribute IS_RESUMABLE can be used to ensure that the exception is thrown and propagated as a resumable
exception. Only then the RESUME statement is allowed to be executed.

6
Decimals Floating Point
Exercise 4 – Difference between binary and decimals floating point
In this exercise you analyze the different behavior of binary and decimals floating point numbers. You will get to know
what errors can be expected from the different floating point types. The example of converting the unit of measurement
Barrel to the metric unit Liter will be used (1bbl = 158.987295l).

 Create the test program ZTE10_DECFLOAT1_EX_mn_xx.


 In this program define a calculation type (set to binary floating point F for the first test), define a binary floating point
constants with the conversion factor for Liters (158.987295) and an input parameter of type string for the numbers of
Barrels (note: ABAP Dynpros do not support the binary floating point).
 Take the input parameter and convert it to floating point variable using the MOVE statement.
 Calculate the number of Liters for the input of Barrels (make sure that only binary floating point numbers are used
within this expression).
 Write the result to the ABAP list.

Now use your program to convert 3bbl to Liters. What is the result? What was your expectation?

Solution 4a – Converting Barrels to Liters using binary floating point numbers

PROGRAM ZTE10_DECFLOAT1_EX_mn_xx.

TYPES:
calc_type TYPE f.

PARAMETERS:
bbl_str TYPE string.

CONSTANTS:
l_per_bbl TYPE calc_type VALUE '158.987295'.

DATA:
bbl TYPE calc_type,
l TYPE calc_type.

bbl = bbl_str.

l = bbl * l_per_bbl.

WRITE: / bbl, 'bbl =', l, 'l'.

For the second test make the following changes to your program:

 Copy the test program ZTE10_DECFLOAT1_EX_mn_xx to ZTE10_DECFLOAT2_EX_mn_xx.


 Change the calculation type to decimal floating point DECFLOAT34.
 Use the utility method cl_abap_decfloat=>read_decfloat34 to convert the input string to a decimal floating point
number.
 Use COMPUTE EXACT to detect overflows.
 Catch all possible exceptions that can be thrown by cl_abap_decfloat=>read_decfloat34 and COMPUTE EXACT.
Use the MESSAGE excp_obj TYPE ‘I’ statement to create an info message in case of an exception.

Now use your program again to convert 3bbl to Liters. What is the result? What was your expectation?

7
Solution 4b – Converting Barrels to Liters using decimal floating point numbers

PROGRAM ZTE10_DECFLOAT2_EX_mn_xx.

TYPES:
calc_type TYPE decfloat34.

PARAMETERS:
bbl_str TYPE string.

CONSTANTS:
l_per_bbl TYPE calc_type VALUE '158.987295'.

DATA:
bbl TYPE calc_type,
l TYPE calc_type,
excp TYPE REF TO cx_root.

TRY.
cl_abap_decfloat=>read_decfloat34( EXPORTING string = bbl_str IMPORTING value = bb
l ).
COMPUTE EXACT l = bbl * l_per_bbl.
CATCH cx_abap_decfloat_parse_err
cx_sy_conversion_error
cx_sy_arithmetic_error INTO excp.
MESSAGE excp TYPE 'I'.
EXIT.
ENDTRY.

WRITE: / bbl, 'bbl =', l, 'l'.

Note: The method cl_abap_decfloat=>read_decfloat34 uses the user setting to validate the input format.

Streams and Locators


Exercise 5 – Using streams and locators to save memory and performance
In this exercise streams and locators are use to read and copy documents stored in the database. The first part is to
read a document and write it to the ABAP list (database table ZCD263 with components NAME (SSTRING) and
DOCUMENT (STRING)).

 Create the test program ZTE10_STREAMS1_EX_mn_xx.


 Define your own work area type using the statement TYPE … TYPES with the addition READER FOR COLUMNS. The
reader should be defined for the column DOCUMENT.
 Define a parameter for the document name to be read.
 Use a SELECT SINGLE statement to select the document “IEEE 754 INTRODUCTION” (a stream is automatically
created for column DOCUMENT).
 Use the methods data_available and read to read from the stream (read the document in blocks of 80
characters) and write every block (line) of 80 characters to the ABAP list.
 Check the ABAP list.

Solution 5a – Read document from database via a stream

PROGRAM ZTE10_STREAMS1_EX_mn_xx.

TYPES:
read_cd263 TYPE zcd263 READER FOR COLUMNS document.

8
PARAMETERS:
name TYPE string.

DATA:
buffer TYPE string,
wa TYPE read_cd263.

SET BLANK LINES ON.

SELECT SINGLE * FROM zcd263 INTO wa WHERE name = name.

WHILE wa-document->data_available( ) = abap_true.


buffer = wa-document->read( 80 ).
WRITE / buffer.
ENDWHILE.

wa-document->close( ).

Extended exercise: Now write a new program displaying the document “IEEE 754 INTRODUCTION” not using a
database stream but common ABAP character strings, reading the document completely in one string (Note: To
determine the used memory use the debugger tool “Tools  Memory Management Memory Analysis”).

For the second exercise a new program is written to copy the document “IEEE 754 INTRODUCTION” to the group’s
name (“CD263 mn xx”) using a locator.

 Create the test program ZTE10_STREAMS2_EX_mn_xx.


 Define your own work area type using the statement TYPE … TYPES with the addition LOCATOR FOR COLUMNS.
The locator should be defined for the column DOCUMENT.
 Define two parameters for the source and destination document name.
 Use a SELECT SINGLE statement to select the document with the source name (a locator is automatically created
for column DOCUMENT).
 Use the MODIFY statement to copy (rewrite) the document to the destination name.
 Execute the program with source name “IEEE 754 INTRODUCTION” and destination name “CD263 mn xx”.
 Use the program from exercise 5a to check the copied document.

Solution 5a – Read document from database via a stream

PROGRAM ZTE10_STREAMS2_EX_mn_xx.

TYPES:
loc_cd263 TYPE zcd263 LOCATOR FOR COLUMNS document.

PARAMETERS:
cpy_from TYPE string,
cpy_to TYPE string.

DATA:
wa TYPE loc_cd263.

SELECT SINGLE * FROM zcd263 INTO wa WHERE name = cpy_from.

wa-name = cpy_to.
MODIFY zcd263 FROM wa.

wa-document->close( ).

COMMIT WORK.

9
Extended exercise: Now write a new program copying the document “IEEE 754 INTRODUCTION” not using a
database locator but common ABAP character strings, reading the document completely in one string (Note: To
determine the used memory use the debugger tool “Tools  Memory Management Memory Analysis”).

Boxed Components
Exercise 4 – Using boxed components to save memory and performance
In the last exercise for boxed components the example of Security Officer Paul Safe from the presentation is revived. A
program for a security protocol is written and the memory consumption with and without boxed components is
analyzed.

 Create the test program ZTE10_BOXED1_EX_mn_xx.


 Define the line type for the table of the security protocol:

TYPES:
BEGIN OF detail_struc,
room TYPE c LENGTH 10,
time TYPE t,
descr TYPE c LENGTH 200,
END OF detail_struc.

TYPES:
BEGIN OF security_struc,
officer TYPE c LENGTH 30,
date TYPE d,
incident TYPE abap_bool,
details TYPE detail_struc BOXED,
END OF security_struc.

 Define input parameter for all components of the security structure.


 Write the input parameter to a work area of the security structure and append the work area to an internal table with
the line type of the security structure. Important is that only in the case of incident is true, the components of the
detail structure are written!
 To get more than one entry, repeat this with a while-loop (e.g. WHILE officer is not initial.) and call the
selection screen again with every loop (CALL SELECTION-SCREEN 1000., the screen number 1000 is the number
for the default selection screen).
 At the end write the protocol to the ABAP list.
 Use the debugger tool “Tools  Memory Management Memory Object Explorer”.
 Now remove the addition BOXED from component details of the security structure and repeat the memory analysis of
the security protocol program.

Solution 5a – Program for a security protocol using boxed components


PROGRAM ZTE10_BOXED1_EX_mn_xx.

TYPES:
BEGIN OF detail_struc,
room TYPE c LENGTH 10,
time TYPE t,
descr TYPE c LENGTH 200,
END OF detail_struc.

TYPES:
BEGIN OF security_struc,
officer TYPE c LENGTH 30,
date TYPE d,
incident TYPE abap_bool,
details TYPE detail_struc BOXED,

10
END OF security_struc.

PARAMETERS:
officer TYPE security_struc-officer,
date TYPE security_struc-date DEFAULT sy-datum,
incident TYPE abap_bool AS CHECKBOX DEFAULT abap_false,
room TYPE security_struc-details-room,
time TYPE security_struc-details-time DEFAULT sy-uzeit,
descr TYPE security_struc-details-descr.

DATA:
protocol TYPE TABLE OF security_struc.

FIELD-SYMBOLS:
<protocol_entry> LIKE LINE OF protocol.

WHILE officer IS NOT INITIAL.

INSERT INITIAL LINE INTO TABLE protocol ASSIGNING <protocol_entry>.


<protocol_entry>-officer = officer.
<protocol_entry>-date = date.
<protocol_entry>-incident = incident.
IF incident = abap_true.
<protocol_entry>-details-room = room.
<protocol_entry>-details-time = time.
<protocol_entry>-details-descr = descr.
ENDIF.

CALL SELECTION-SCREEN 1000.


ENDWHILE.

BREAK-POINT.

LOOP AT protocol ASSIGNING <protocol_entry>.


WRITE: / <protocol_entry>-officer,
<protocol_entry>-date,
<protocol_entry>-incident,
<protocol_entry>-details-room,
<protocol_entry>-details-time,
<protocol_entry>-details-descr.
ENDLOOP.

11
© 2010 SAP AG. All rights reserved.
SAP, R/3, SAP NetWeaver, Duet, PartnerEdge, ByDesign, SAP BusinessObjects Explorer, and other SAP products and services
mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP AG in Germany and other
countries.

Business Objects and the Business Objects logo, BusinessObjects, Crystal Reports, Crystal Decisions, Web Intelligence, Xc elsius,
and other Business Objects products and services mentioned herein as well as their respective logos are trademarks or registe red
trademarks of Business Objects Software Ltd. in the United States and in other countries.

All other product and service names mentioned are the trademarks of their respective companies. Data contained in this document
serves informational purposes only. National product specifications may vary.

These materials are subject to change without notice. These materials are provided by SAP AG and its affiliated companies ("SAP
Group") for informational purposes only, without representation or warranty of any kind, and SAP Group shall not be liable fo r errors
or omissions with respect to the materials. The only warranties for SAP Group 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.

You might also like