Professional Documents
Culture Documents
TO APPLICATION
CD167
Exercises
Dirk Becker / SAP AG
Jens Bckenhauer / SAP AG
Christian Gnther / SAP AG
Simon Hoeg / SAP AG
In this exercise you will create an entire FPM application with feeder classes and configuration. In this
application, you will start with the search for flights and select a single flight for which you will show details
and bookings. The bookings are editable and introduce the transactional behaviour of the framework.
As a preparation, we have centrally provided a singleton class for data access which takes care of the
backend processes: CL_CD167_FLIGHT_ACCESS is available and referenced several times in the
exercises.
Furthermore, sample feeder classes are available for your reference; you can use them for review, copy or
even directly in configuration. You will notice that the comments therein reference to the steps in the
exercises. These are:
-
CL_CD167_FLIGHT_SEARCH (exercise 1)
CL_CD167_FLIGHT_LIST (exercise 3)
CL_CD167_FLIGHT_FORM (exercise 4)
CL_CD167_FORM_REP (exercise 5)
This exercise requires ABAP development skills. Depending on your degree of ABAP knowledge, there
are several levels of executing the exercises; you can also switch between these levels, e.g. if time runs out.
1.) Perform the entire exercise step by step and do the coding on your own.
2.) Perform the exercises step by step but leave out the steps marked with OPTIONAL.
3.) Perform the exercises step by step, but instead of writing the coding on your own, copy the coding
from the sample feeder classes listed above. In this case you should read the coding in order to
understand the business logic.
4.) For the virtual Hands-on we recommend dont code at all. Start directly
with exercise 2; leave out the coding parts in exercises 3, 4 and 5. In
configuration, enter the names of the sample feeder classes listed above.
LOGON INFORMATION
System / client: M24 / 800
Your user name: CD167-A-<group>
A = your session
<group> = your group number
Search GUIBB
Z<Yxx>_CD167_FLIGHTS_SEARCH
Form GUIBB
Z<Yxx>_CD167_FLIGHTS_FORM
Feeder class:
ZCL_<Yxx>_CD167_FLIGHTS_SEARCH
Feeder class:
ZCL_<Yxx>_CD167_FLIGHTS_FORM
The singleton class CL_CD167_FLIGHTS_ACCESS is centrally available and can be used by you as it is.
For your reference, the corresponding Solutions document contains the entire coding which has to be
written during this exercise plus the entire central singleton class.
In this exercise, you will create your first feeder. This feeder is intended to search for flights. You will get to learn basis
functionalities of feeder interfaces and feeder classes with FPM and in detail you will implement the methods
GET_DEFINITION and PROCESS_EVENT.
1.1. Start the class builder transaction code SE24 and create your own feeder class
ZCL_<Yxx>_CD167_FLIGHT_SEARCH as local object. Take care for the naming conventions: Y
denominates the session and xx your group; therefore if you are in session A and your group number is 01,
your feeder class will be called ZCL_A01_CD167_FLIGHT_SEARCH.
1.2. Implement the feeder interface IF_FPM_GUIBB_SEARCH. You will notice that IF_FPM_GUIBB is
implemented automatically.
1.3. Implement all interface methods: In the class builder, switch to edit mode, enter void method code for each
method and after you have gone through all methods, finally save. There must not occur any warning when
you process a syntax check.
1.4. Now you define the field description: Therefore you have to implement code for method
IF_FPM_GUIBB_SEARCH~GET_DEFINITION as follows: Create a runtime type descriptor for DDIC structure
CD167_SEARCH_ATTRIBUTE by calling CL_ABAP_TYPEDESCR=>DESCRIBE_BY_NAME and cast the
result to the exporting parameter EO_FIELD_CATALOG_ATTR.
1.5. Implement IF_FPM_GUIBB_SEARCH~PROCESS_EVENT.
1.5.1.Implement the following only if the event ID is FPM_EXECUTE_SEARCH (IO_EVENT->MV_EVENT_ID
equals constant IF_FPM_GUIBB_SEARCH=>FPM_EXECUTE_SEARCH).
1.5.2.In this case use method FPM_ATTRIBUTE_INTO_ABAP_RANGE of the search conversion passed as
parameter IO_SEARCH_CONVERSION to convert the input into an ABAP range table for each search
attribute (i.e. you have to call the method 5 times) Take care: you will receive data references, so you
will need to use field symbols for assigning the content.
1.5.3.Pass the range tables to method SELECT of the single instance of class CL_CD167_FLIGHT_ACCESS
which you can always retrieve by calling CL_CD167_FLIGHT_ACCESS=>GET_INSTANCE.
1.6. Save and dont forget to activate feeder class.
2.1.1.On the first page of the tool, enter Web Dynpro Application name CD167_FLIGHTS. It is important
that you assign your local name space Z<Yxx>_: Therefore use the button Apply Namespace in the
toolbar of the initial screen. The rule is as before: Y is for virtual Hands-on A and xx your group
number; if your group number is 01, your namespace reads ZA01.
2.1.2.Select Floorplan Overview Page. You might want to add descriptions, but those are not needed
throughout this exercise.
Attention: Leave the confirmation page open for the rest of the exercise. In case you lose it due to a timeout, you can find the generated objects in your local objects (SE80). (see 3.7.1 page 14)
2.2. Launch the Configuration Editor (FLUID) by pressing the link Launch Configuration Editor on the
confirmation screen.
2.2.1.Open the Navigation Panel by clicking on the corresponding button choices (see illustration below):
There you create a new page type Initial Screen and rename Page Id to INIT and Title to Search
Flights (or any other name you prefer).
2.2.2.Go to the Overview Page Schema: Select the UIBB line (1) and delete (2) the dummy UIBB which was
rendered automatically by the system.
2
1
2.2.3.Then
add
a
UIBB
for
the
Search
Component
and
set
Configuration
ID
Z<Yxx>_CD167_FLIGHT_SEARCH (Y = A and xx = group number). You will receive an error that this
configuration does not yet exist; you can ignore the error and save the configuration.
10
2.3. Now you configure the Search UIBB: Press button Configure UIBB in the schema toolbar (see below; the
new Search UIBB must be selected). (save component = Yes)
2.3.1.On the appearing initial screen, press New; add a description if you like and choose Local object on
the TADIR popup.
11
2.3.2.On the feeder class popup, enter the sample feeder class CL_CD167_FLIGHT_SEARCH.
If you created your own feeder class in exercise 1, you can also use your own newly created feeder class
ZCL_<Yxx>_CD167_FLIGHT_SEARCH (Y = A and xx = group number). The feeder class has no
parameters; therefore you have to confirm the next popup with Ok.
).
Mark all Search Criteria (use button shift and click on rows)
12
Move all search attributes from the Repository via drag and drop into Preview or Search UIBB
Schema. Save and close the browser window.
2.4. Execute the application. You can either do it from the Confirmation Page of the Application Creation Tool (see
above)
Or especially if this page is no longer open or if you experienced a time out you will find your application in
your local objects in SE80 and can start it from there.
13
You will notice that you can fill the Search, but that nothing happens when you click on Search. This is
because we have not yet passed the data to a Result List. This will be part of Exercise 3.
14
Alternatively you can press the button Show Configurable Areas of the running application and click in
15
Or you can find your search configuration in your local objects in SE80.
Double click on the Component Configuration
Select the UIBB element and click on Configure UIBB.
16
17
Open the Attributes panel (if needed); enter configuration name Z<Yxx>_CD167_FLIGHT_LIST (Y = A
and xx = group number). Again, you can ignore the errors and save the configuration.
Then click on Configure UIBB in the schema toolbar to enter the List UIBB configuration.
18
Add a description if you like and create the configuration as Local Object. In the feeder class dialog,
enter your feeder class ZCL_<Yxx>_CD167_FLIGHT_LIST (Y = session and xx = group number) and
continue (This feeder class has no parameters).
19
3.8.2.Bring all fields from the Repository to the List UIBB Schema (e.g. by drag and drop).
Open the Repositories
3.8.3.In the General Settings panels: Set Search Results Objects Name to Flights and Selection mode No
selection (see below).
20
3.8.4.Change the Display Type (if not already done in optional step 3.4.2 before) of CONNID to Link To
Action (either in the List UIBB Schema or in the Attributes panel).
21
You will notice that you get a list of flights out of your search. But it is still not possible to select a flight and
continue to a details page. This will be done in exercise 4.
22
23
4.7.2.There rename Page ID to MAIN and Title to Flight Detail and Bookings.
4.7.3.In the Overview Page Schema: Add a form component by pressing Add UIBB and select Form
Component from the list.
24
On the upcoming initial screen, press New; on the following popups, enter a description text (if you like to),
then assign Local Object;
25
4.8.1.In the form configuration on the panel General Settings: Set the Layout Type to 16/2 (see below).
4.8.2.In the Preview panel, you will find a form layout with two layout columns divided by a red line and 16
configuration columns (8 for each layout column). In order to populate the form, you can use drag and
drop to move elements from the Repository to the Preview.
26
4.8.3.Multi-select all form fields (either in the Preview or in Form UIBB Schema), open the Attributes panel
and set the Display Type to Text View (this automatically applies to all selected fields). If you have
forgotten one or more fields in your selection you can convert the Display Type individually still for each
field.
4.9. In this step, you realize the connection from the Result List to the newly created form on the Main Page. In the
List UIBB configuration: select Connection Number (CONNID) either in the List UIBB Schema or in the
Preview; open the Attributes panel (if needed); therein assign action FPM_NAVIGATE to FPM Event ID.
27
Additional fields appear in the Attributes panel which are relevant for the navigation event: Set Processing
Mode to Execute Search and Leave; set Edit Mode to Read-Only. Assign CARRID and FLDATE as
Additional Source Attributes (take two of the five available input fields for Additonal Src Attr). This is
necessary since the flight key consists of CARRID and FLDATE in addition to CONNID which already acts as
a key field for navigation.
28
Step 5.1 to 5.13 is optional! You may copy the class CL_CD167_BOOK_FORM_REP
to ZCL_<Yxx>_CD167_BOOK_FORM_REP or you use CL_CD167_BOOK_FORM_REP in the exercise.
5.1. In the class builder, create the form repeater feeder class ZCL_<Yxx>_CD167_BOOK_FORM_REP (Y =
session and xx = group number) as local object.
5.2. Implement the form repeater feeder interface IF_FPM_GUIBB_FORM_REPEATER and extended feeder
interface IF_FPM_GUIBB_FORM_REPEATER_EXT which is required later for the data loss popup.
5.3. Implement all methods (as in exercise 1.3)
5.4. Implement the method IF_FPM_GUIBB_FORM_REPEATER~GET_DEFINITION:
5.4.1.Create the field catalog from SBOOK remember that we are dealing with a data collection which is
represented by an ABAP table and need to undergo the same steps as in Exercise 3.4.1.
5.4.2. Set the key fields of the booking to read only (these must not be changed in the booking form repeater)
therefore use the read_only attribute of the field description for the elements CARRID, CONNID, FLDATE
and BOOKID.
5.4.3.OPTIONAL: Mark field MANDT a technical field (TECHNICAL_FIELD is a Boolean attribute of the field
description); this removes the field MANDT from the Repository so that it cannot appear on the UI.
5.5. Define a private class type TT_BOOK as standard table of SBOOK.
5.6. Declare a private instance attribute MT_BOOK type TT_BOOK and a private instance attribute
MV_READ_FROM_DB (type ABAP_BOOL initial value ABAP_TRUE)
5.7. Implement IF_FPM_GUIBB_FORM_REPEATER~GET_DATA:
5.7.1.Get the selected flight from
the singleton (method CL_CD167_FLIGHT_ACCESS=>
GET_SELECTED_FLIGHT) and select the bookings from the data base table SBOOK into the instance
attribute MT_BOOK for the selected flight key (CARRID, CONNID and FLDATE).
5.7.2. Execute the selection (i.e. the above code) only if we have to read the data from the DB, i.e.
MV_READ_FROM_DB is true. You also have to reset the indicator MV_READ_FROM_DB. This will
ensure that we reconcile our internal bookings buffer MT_BOOK with the database only at the beginning
and after the transactional events for save and cancel.
5.7.3. Move the booking data into CT_DATA and set the change indicator EV_DATA_CHANGED. For
performance reasons, you should execute this step only if MT_BOOK and CT_DATA differ.
5.8. EASY WAY: Implement IF_FPM_GUIBB_FORM_REPEATER~FLUSH and move the entire IT_DATA to
MT_BOOK. This will dump the entire table to the data base even if only one field was changed. Alternatively,
the advanced (OPTIONAL) solution below (5.9, 5.10 and 5.11.2) describes a much better and performant
way:
5.9. OPTIONAL PERFORMANCE (1): Create a private instance attribute MT_CHANGED_LINES as sorted table
of I (integer) with unique default key.
5.10. OPTIONAL PERFORMANCE (2): IF_FPM_GUIBB_FORM_REPEATER~FLUSH: All the changes are
tracked in parameter IT_CHANGE_LOG; you have to apply these changes to the booking table. Therefore
29
you will need to declare field-symbols for the change log, for the booking table and for the old and the new
value. While looping over the change log table access the relevant booking by the given line_index in table
MT_BOOK, take over the new_value and insert the index into the MT_CHANGED_LINES buffer table; this
table is needed in IF_FPM_GUIBB_FORM_REPEATER~PROCESS_EVENT.
5.11. Implement IF_FPM_GUIBB_FORM_REPEATER~PROCESS_EVENT
5.11.1. Create a case distinction for the event ID: For the save event (FPM_SAVE IF_FPM_CONSTANTS
=>GC_EVENT-SAVE) you will update the SBOOK from table MT_BOOK (only in case of the EASY
WAY)
5.11.2. OPTIONAL PERFORMANCE (3): If you did the optional performance steps above, in case of SAVE,
you will update only the changed lines which you have saved before in the buffer table
MT_CHANGED_LINES. Dont forget to reset the buffer table.
5.11.3. After the data base update you have to perform a COMMIT_WORK and request the new data selection
by setting MV_READ_FROM_DB to ABAP_TRUE.
5.11.4. For the cancel event (FPM_CANCEL IF_FPM_CONSTANTS =>GC_EVENT -CANCEL) request the
new data selection by setting MV_READ_FROM_DB to ABAP_TRUE and just reset the buffer table.
5.11.5. For the local edit event (FPM_LOCAL_EDIT IF_FPM_CONSTANTS =>GC_EVENT LOCAL_EDIT)
first check whether the event was raised by the own UIBB (cf. parameter IV_RAISED_BY_OWN_UI) to
ensure that the local edit was not requested by any other UIBB. Then request the new data selection by
setting MV_READ_FROM_DB to ABAP_TRUE.
5.11.6. OPTIONAL: This optional step takes care of locking the selected flight: Also in the local event event,
you have to try to lock the selected flight. The locking is only needed if there are bookings available
(check MT_BOOK). Take any line of the table MT_BOOK and call the Function Module
ENQUEUE_ESFLIGHT with the flight key CARRID, CONNID and FLDATE. If messages occur, append
them to the message table ET_MESSAGE and set the event result EV_RESULT to failed (FAILED
IF_FPM_CONSTANTS => GC_EVENT_RESULT-FAILED). Remark 1: If you like you can encapsulate
the coding in a separate method. Remark 2: You can easily check the locking mechanism by selecting
the same flight twice and try to enter the edit mode in both windows.
5.11.7. OPTIONAL: If you have implemented the locking mechanism in the previous step, you need to unlock
your locked records in case of CANCEL. Therefore go back to the Cancel part of the coding and call
function module DEQUEUE_ESFLIGHT with the flight key.
5.12. OPTIONAL: Implement IF_FPM_GUIBB_FORM_REPEATER_EXT~NEEDS_CONFIRMATION: For the
data loss popup, check for the cancel event and in case the buffer MT_CHANGED_LINES is not empty, set
EO_CONFIRMATION_REQUEST to CL_FPM_CONFIRMATION_REQUEST=> GO_DATA_LOSS.
5.13. Save and activate feeder class.
5.14. Go to the configuration (FLUID, e.g. out of the running application) and navigate to the OVP Main Page
(MAIN).
5.14.1. In the Overview Page Schema add an Form Repeater Component directly underneath the existing
Form Component and enter the Configuration ID Z<Yxx>_CD167_BOOK_FORM_REP (Y = A and xx
= group number) with Title Bookings. You can as usual ignore the errors and save the
configuration.
30
Drag
and
drop
various
fields
from
the
Repository
to
the
Form
Repeater
Preview.
On the left side of the form, start with the Booking Number (BOOKID), add the Travel Agency Number
(AGENCYNUM), Class (CLASS) and the Invoice Flag (INVOICE).
You will notice that the Booking Number will be rendered as non-enterable because we have set this to
read-only programmatically before (compare with 5.4.2).
31
5.15.3. In the Attributes panel set for the element Class (CLASS) the Display Type to Drop Down.
And the Display Type of the element Invoice Flag (INVOICE) to Check Box.
5.15.4. Drag and drop (Part 2): Drag and drop the Customer Number (CUSTOMID), Passenger Name
(PASSNAME) and DOB of Passenger (PASSBIRTH) to the right part of the form.
5.15.5. Save your configuration
5.16. Use
the
breadcrumb
to
navigate
back
to
the
OVP
floorplan
configuration.
5.16.1. In the Form Repeater you will have to enter the Edit button: In the OVP configuration go to the
Toolbar Schema (you will find it as a stacked panel behind the Overview Page Schema) and select the
Toolbar of UIBB: Bookings and press Add Toolbar Element (see below).
32
In the Attributes Panel set the Text of the button to Edit, for the Image Source chose the Edit Icon
(~Icon/Edit) by pressing the Value Help.
5.16.2. In the OVP Global Toolbar you will create a Save and a Cancel button: In the toolbar schema select
the Global Toolbar,
choose Add Toolbar Element and select the Save button, choose again Add Toolbar Element and
select the Cancel button.
33
5.17. Restart your application and test the transactional behavior: Click on edit and check whether the form
repeater switches to local edit mode, change the data: Check whether the data loss popup appears in case of
Cancel and check whether the data is saved successfully in case of Save.
34
"if_fpm_guibb_search~get_definition
35
iv_search_attribute = 'FLDATE'
IMPORTING
et_range_tab_ref
= lr_fldate.
ASSIGN lr_fldate->* TO <lrg_fldate>.
*----- range for maximum capacity
CALL METHOD io_search_conversion->fpm_attribute_into_abap_range
EXPORTING
iv_search_attribute = 'SEATSMAX'
IMPORTING
et_range_tab_ref
= lr_seatsmax.
ASSIGN lr_seatsmax->* TO <lrg_seatsmax>.
*----- range for occcupied
CALL METHOD io_search_conversion->fpm_attribute_into_abap_range
EXPORTING
iv_search_attribute = 'SEATSOCC'
IMPORTING
et_range_tab_ref
= lr_seatsocc.
ASSIGN lr_seatsocc->* TO <lrg_seatsocc>.
*+++++++++++++++++ 1. Excercise: 1.5.3 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*
*----- let the singleton select from database
cl_cd167_flight_access=>get_instance( )->select(
irg_carrid = <lrg_carrid>
irg_connid = <lrg_connid>
irg_fldate = <lrg_fldate>
irg_seatsmax = <lrg_seatsmax>
irg_seatsocc = <lrg_seatsocc>
iv_max_num = iv_max_num_results ).
ENDCASE.
ENDMETHOD.
"if_fpm_guibb_search~process_event
36
"if_fpm_guibb_list~get_definition
"if_fpm_guibb_list~get_data
37
"if_fpm_guibb_form~get_definition
"if_fpm_guibb_form~get_data
38
ASSIGNING <ls_field_descr>.
ASSIGNING <ls_field_descr>.
ASSIGNING <ls_field_descr>.
ASSIGNING <ls_field_descr>.
"if_fpm_guibb_form_repeater~get_definition
39
"if_fpm_guibb_form_repeater~get_data
"if_fpm_guibb_form_repeater~flush
40
"if_fpm_guibb_form_repeater~process_event
41
"if_fpm_guibb_form_repeater_ext~needs_confirmation
42
PART II APPENDIX
The Appendix is intended for reconstructing the exercise in any system which contains SAP Net Weaver
7.03/7.31.
Application Creation Tool
The Application Creation Tool is available as Web Dynpro application FPM_CFG_BO_MODEL_ACT with Web
Dynpro application configuration FPM_CFG_BO_MODEL_ACT.
43
<SIGNATURE>---------------------------------------------------------------------------------------+
| Instance Public Method CL_CD167_FLIGHT_ACCESS->GET_FLIGHTS
+-------------------------------------------------------------------------------------------------+
| [<---] ET_FLIGHT
TYPE
T_FLIGHT
+--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_flights.
"get_flights
<SIGNATURE>---------------------------------------------------------------------------------------+
| Static Public Method CL_CD167_FLIGHT_ACCESS=>GET_INSTANCE
+-------------------------------------------------------------------------------------------------+
| [<-()] RO_INSTANCE
TYPE REF TO CL_CD167_FLIGHT_ACCESS
+--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_instance.
"get_instance
<SIGNATURE>---------------------------------------------------------------------------------------+
| Instance Public Method CL_CD167_FLIGHT_ACCESS->GET_SELECTED_FLIGHT
+-------------------------------------------------------------------------------------------------+
| [<-()] RS_FLIGHT
TYPE
SFLIGHT
+--------------------------------------------------------------------------------------</SIGNATURE>
METHOD get_selected_flight.
"GET_SELECTED_FLIGHT
<SIGNATURE>---------------------------------------------------------------------------------------+
| Instance Public Method CL_CD167_FLIGHT_ACCESS->HAS_NEW_DATA
+-------------------------------------------------------------------------------------------------+
| [<-()] RV_NEW_DATA
TYPE
ABAP_BOOL
+--------------------------------------------------------------------------------------</SIGNATURE>
METHOD has_new_data.
rv_new_data = mv_new_data.
mv_new_data = abap_false.
44
ENDMETHOD.
*
*
*
*
*
*
*
*
*
*
"has_new_data
<SIGNATURE>---------------------------------------------------------------------------------------+
| Instance Public Method CL_CD167_FLIGHT_ACCESS->SELECT
+-------------------------------------------------------------------------------------------------+
| [--->] IRG_CARRID
TYPE
TRG_CARRID
| [--->] IRG_CONNID
TYPE
TRG_CONNID
| [--->] IRG_FLDATE
TYPE
TRG_FLDATE
| [--->] IRG_SEATSMAX
TYPE
TRG_SEATSMAX
| [--->] IRG_SEATSOCC
TYPE
TRG_SEATSOCC
| [--->] IV_MAX_NUM
TYPE
I (default =0)
+--------------------------------------------------------------------------------------</SIGNATURE>
METHOD select.
"select
<SIGNATURE>---------------------------------------------------------------------------------------+
| Instance Public Method CL_CD167_FLIGHT_ACCESS->SET_INDEX
+-------------------------------------------------------------------------------------------------+
| [--->] IV_INDEX
TYPE
I
+--------------------------------------------------------------------------------------</SIGNATURE>
METHOD set_index.
"set_index
45