Quantcast
Channel: SCN : Blog List - Floorplan Manager for Web Dynpro ABAP
Viewing all 54 articles
Browse latest View live

Wiring based on Business Objects in Floorplan Manager

$
0
0

Introduction

In my previous blog post I compared the main data exchange possibilities to share data between UI Building Blocks (UIBBs) in the Floorplan Manager (FPM). The way of sharing data supported by the FPM Framework is called “Wiring”. There are a lot of good guides out there which show how wiring can be done. They usually utilize an example with a list which sends the selected column to another UIBB to show some detail data.

The problem with these examples is usually not the wiring mechanisms of the FPM or the way data is exchanged in general – moreover the way it is implemented.

Usually, the examples include a wire which goes via Lead selection from a certain List UIBB to a Form UIBB which shows the details of the record. The Wire connector contains an attribute of a single record described purely by an ABAP structure. This is misleading and is not the way large enterprise applications are implemented.

The problem with this approach is the fact that you are heading a dead end in most of the cases: What can the Form UIBB, which shows the detail data of the record do with the structure once there are some editable Input Fields showing the attributes of the structure?

Well, data can be written back to the structure and then what? How can the record be validated and saved on the database? If there is no function module to persist the data, you would need to use ABAP OO, and in the cases where we ourselves use the FPM in our own projects, there is always an ABAP OO Backend.

But you can’t call operations on structures. So either the Connector, to which the Form UIBB has access to, would have to persist the data afterwards or the Form UIBB would have to create its instance of the Business Object by itself in order to call something like a SAVE – Method.

Both solutions aren’t really a good idea in terms of maintainability and understandability. That’s why I wrote this blog post.

Demo

I set up a demo for this blog post in order to show the concepts which I used. The demo application comprises the following functionality:

  • Search flights (implemented by a Search UIBB)
  • Show number of results in the header area (OVP - Title)
  • Show a list of the results (implemented by a List UIBB)
  • Once the users selects an entry, a form UIBB shows the detail data

01 - Overview of the application.png

In order to make clear what the building blocks of the application are, I marked them for you. Of course, the OVP Floorplan title is not a Building block, rather a part of the header area of the OVP. For demo purposes, I also marked it since its information is also getting updated, hence, subject to the wiring mechanisms I will show you in detail.

 

02 - OVP-Floorplan, UIBBs and title of the application.png

Data sharing

Sharing selection criteria and the result list

There are two UIBBs involved in sharing the selection criteria and result list with each other. The header area of the OVP which shows the number of results is involved as well. All of them share one object with each other which has the responsibility of selecting all the data which fits to the selection criteria entered in the Search-Block.

The instance is typed as ZIF_FPM_DEMO_WIRE_FLIGHT_SEL. Please note that this is still an interface which describes only what an object needs to do – not how it is implemented.

The reason why this interface inherits ZIF_FPM_DEMO, which contains no methods and no attributes will be explained later on. There will be no further explanation here.

ZIF_FPM_DEMO_WIRE_FLIGHT_SEL.PNG

Wiring works based on this interface. Sharing the selection instance starts at the search UIBB. It fetches the selection criteria and pushes it to the data selection instance MO_CONTAINER of type ZIF_FPM_DEMO_WIRE.

 

METHOD if_fpm_guibb_search~process_event.  CLEAR: et_messages, ev_result.  DATA:
 lt_selopt            TYPE if_powl_easy_feeder=>typ_t_selection_parameter,
 ls_selopt            TYPE if_powl_easy_feeder=>typ_s_selection_parameter,     lt_sel               TYPE rsdsselopt_t.  FIELD-SYMBOLS:<ls_sel>         TYPE rsdsselopt,<ls_selcrit>     TYPE fpmgb_s_search_criteria.  DATA lo_cx_fpmgb TYPE REF TO cx_fpmgb.  DATA ls_message TYPE fpmgb_search_s_t100_message.  CASE io_event->mv_event_id.    WHEN if_fpm_guibb_search=>fpm_execute_search.      TRY.          LOOP AT it_fpm_search_criteria ASSIGNING <ls_selcrit>.
 CLEAR ls_selopt.
 APPEND INITIAL LINE TO lt_sel ASSIGNING <ls_sel>.<ls_sel> = cl_fpm_guibb_search_conversion=>to_abap_select_option( <ls_selcrit> ).
 ls_selopt-attribute = <ls_selcrit>-search_attribute.
 ls_selopt-sign      = <ls_sel>-sign.
 ls_selopt-option    = <ls_sel>-option.
 ls_selopt-low       = <ls_sel>-low.
 ls_selopt-high      = <ls_sel>-high.
 APPEND ls_selopt TO lt_selopt.
 ENDLOOP.        CATCH cx_fpmgb INTO lo_cx_fpmgb.
 ls_message-plaintext = lo_cx_fpmgb->get_text( ).
 ls_message-severity = if_fpm_message_manager=>gc_severity_error.          APPEND ls_message TO et_messages.      ENDTRY.
 mo_container->set_selection_criteria( lt_selopt ).  ENDCASE.
ENDMETHOD.


If the instance does not yet exist, it is created at runtime during the wiring setup.

 

METHOD if_fpm_feeder_model~get_outport_data.
 try_get_container( ).  CASE iv_port_identifier.    WHEN zif_fpm_demo_wire_flight_sel=>gc_name.      ro_data = mo_container.  ENDCASE.
ENDMETHOD. 


METHOD try_get_container.
  CHECK mo_container IS INITIAL.  IF mo_connector IS NOT INITIAL.    mo_container ?= mo_connector->get_output( ).  ELSE.    CREATE OBJECT mo_container TYPE zcl_fpm_demo_wire_flight_sel.  ENDIF.
ENDMETHOD.

 

Targets are both the List – UI Building Block as well as an OVP Exit (which implements IF_FPM_OVP_CONF_EXIT) which is also implementing the Application Controller Interface (IF_FPM_APP_CONTROLLER) and the UIBB feeder model interface (IF_FPM_UIBB_MODEL). This way it can also serve as a target for wiring. This OVP Exit updates the application header title.

The list UIBB accesses the instance via the connector which has been passed by the FPM framework during wiring setup.

 

  DATA lo_datacontainer TYPE REF TO zif_fpm_demo_wire_flight_sel.  CASE io_event->mv_event_id.    WHEN if_fpm_guibb_search=>fpm_execute_search.      lo_datacontainer ?= mo_connector->get_output( ).      lo_datacontainer->apply_selection( ).      mt_sflight = lo_datacontainer->get_list( ).
...
ENDCASE.


The OVP Exit receives the instance via its feeder model and hooks into the AFTER_PROCESS_EVENT-Method:

 

METHOD after_process_event .  DATA lo_ovp TYPE REF TO if_fpm_cnr_ovp.  lo_ovp ?= wd_this->mo_fpm->get_service( cl_fpm_service_manager=>gc_key_cnr_ovp ).  DATA lo_datacontainer TYPE REF TO zif_fpm_demo_wire_flight_sel.  DATA lv_port_identifier TYPE fpm_model_port_identifier.  DATA lv_title TYPE string.  DATA lv_num TYPE i.  DATA ls_content_area TYPE if_fpm_ovp=>ty_s_content_area.  CHECK wd_this->mo_feeder_model IS NOT INITIAL.

 lv_port_identifier = zif_fpm_demo_wire_flight_sel=>gc_name.
 lo_datacontainer ?= wd_this->mo_feeder_model->get_outport_data( iv_port_type = 'LS' iv_port_identifier = lv_port_identifier ).

 ls_content_area = lo_ovp->get_current_content_area( ).  CHECK: lo_datacontainer IS NOT INITIAL, lo_ovp IS NOT INITIAL.  lv_num = lo_datacontainer->get_number_of_results( ).  lv_title = lv_num.  CONCATENATE 'Flight Search -' lv_title 'results' INTO lv_title SEPARATED BY space.
 ls_content_area-title = lv_title.
 lo_ovp->change_content_area_restricted( iv_content_area_id = ls_content_area-id iv_title = lv_title ).
ENDMETHOD.

 

03 - Wires of the application I.png

 

The wiring setup finalizes the implementation and makes clear what the data exchange directions are. The connector class which is used for that is ZCL_FPM_DEMO_FL_SEARCH_CONN. There will be two wires as both the flights result list as well as the OVP title need to be updated based on the flight results.

It contains an instance of type ZIF_FPM_DEMO_WIRE, the parent interface of the current business object’s interface.

05 - Wiring 01.PNG

05 - Wiring 02.PNG

 

Sharing the selected entry as a business object

The List UIBB which shows the flight results needs to setup another business object which does not contain a list of flights, rather the exact record, which has been selected by the user. The flight record is represented by an instance of type ZIF_FPM_DEMO_WIRE_SFLIGHT. It inherits from ZIF_FPM_DEMO as well as the previously introduced business object of type ZIF_FPM_DEMO_WIRE_FLIGHT_SEL.

04 - Wires of the application II.png

The business object currently only provides a Setter and a getter method to read the data structure or write a modified data structure back to the instance.

ZIF_FPM_DEMO_WIRE_SFLIGHT.PNG

The wiring setup reuses the connector class ZCL_FPM_DEMO_FL_SEARCH_CONN as there is no special treatment needed for the exchange of the current business object.

As mentioned earlier, it contains an instance of type ZIF_FPM_DEMO_WIRE, the parent interface of both business object’s interfaces.

Now it is getting clear, what ZIF_FPM_DEMO_WIRE is used for. It is just a marker interface, which gives a hint, which business objects are shared across the application. As the connector references an instance of that type, it can be referencing both the selection as well as the flight record. There is no technical or functional requirement for that – the reason why I didn’t use a more generic REF TO OBJECT for the instance is the fact that I just wanted to make clear for someone who reads and needs to understand the code, what the intended context of the current connector is.

05 - Wiring 03.PNG

I didn’t implement any update operations for this demo, but it would be yet another method for the existing business object besides the SET_SFLIGHT( )-Method, for example SAVE( ).

Since the feeder has already access to the wired business object, it has also access to its public methods. The SAVE( )-method would implement the update operations and could be called directly from the form feeder which provides the UI operations for the flight details building block.

In contrast to a possible solution, where only a flat data structure was exchanged, this is a much more convenient way of accessing and modifying the data provided by the backend.

 

The nugget can be found here.


Perform Save-operations using a wire transaction handler in the FPM

$
0
0

Introduction

In the previous blog post I figured out how wiring based on business objects might work in the Floorplan manager. The example application provides a Search component to select records based on the table SFLIGHT. Once a result entry has been selected, the flight data record is shown in a detail view below the result list. While the result list is implemented by a List-UIBB, the detail view is implemented by a Form-UIBB.

Any follow-up steps have not been implemented then, this includes also the possibility to save the edited record back to the database.

The subject of this blog post is how a Save-operation could be implemented based on a wire transaction handler.

I decided to not use the interface IF_FPM_TRANSACTION which can be implemented by any UIBB in the application, rather, I decided to use a Transaction Handler for wire models.  The drawback of this approach is that a wire transaction handler cannot serve as a target for wires, hence, has usually no access to Business objects.

One opportunity to pass the business object to the handler might be to share it as a singleton instance. This requires the existence of a registry or any other singleton mechanism. Another possibility is the data exchange based on events.

In this very blog post, the business object is going to be shared as a parameter of the FPM_SAVE- event.

For now, let’s again recap the wires which are in use by the demo application. However besides this introduction it is strongly recommended to read the previous blog post if you did not yet read it.

 

The existing application

The selection criteria and the selection of the flight list is implemented by the list selection wire (ZCL_FPM_DEMO_WIRE_FLIGHT_SEL which implements ZIF_FPM_DEMOWIRE_SFLIGHT_SEL).

03 - Wires of the application I.png

The selected flight data record is represented by an instance of type ZIF_FPM_DEMO_WIRE_SFLIGHT.

04 - Wires of the application II.png

Both wires have specific operations offered to the UIBBs or OVP Exit which use these wires.

ZIF_FPM_DEMO_WIRE_FLIGHT_SEL.PNGZIF_FPM_DEMO_WIRE_SFLIGHT.PNG

In this blog post, the first wire is going to be extended to hold a lead selection instance of the second wire. The second wire which represents a single flight data record will be enhanced with a Save-operation. In combination with some other changes, this allows the user to edit the flight data and save it back to the database.

 

Sharing the business object

A new Save-Button will be added to the application’s OVP toolbar.

In order to allow the wire transaction handler to access the business object, the OVP exit will catch  the Save-Event which is triggered by the save- button and will enrich the event data with a new Name-Value Pair which represents an instance of a saveable business object, that is, the wire which represents a single entry of the flight data list (It would be a good idea to work with an abstraction to the specific flight data instance as well, so we can possibly reuse the wire transaction handler later on in another application)

Since the OVP exit has access to the list selection instance only we need to provide access to the selected business object through the list selection wire.

 

Enhancements to the current application

First of all, we include an OVP-toolbar button to allow the user to trigger the Save-operation.

Save button.PNG

The list selection wire will need to store the selected flight record to allow the OVP Exit to get access to the currently selected record. Therefore the methods GET_LEAD_SELECTION and SET_LEAD_SELECTION  are added to the interface ZIF_FPM_DEMO_WIRE_FLIGHT_SEL which describes, what operations have to be supported by this wire. In the implementing class, a new attribute MO_LEAD_SELECTION is included and the corresponding Getter- and Setter method are implemented.

ZIF_FPM_DEMO_WIRE_FLIGHT_SEL new.PNG

Now we need to call SET_LEAD_SELECTION in ZCL_FPM_DEMO_FLIGHT_LIST, method IF_FPM_GUIBB_LIST~PROCESS_EVENT, which handles the lead selection event in the list.

METHOD if_fpm_guibb_list~process_event.  DATA lo_datacontainer TYPE REF TO zif_fpm_demo_wire_flight_sel  …  lo_datacontainer ?= mo_connector->get_output( ).  CASE io_event->mv_event_id.  …    WHEN 'FPM_GUIBB_LIST_ON_LEAD_SELECTI'.      CHECK lo_datacontainer IS NOT INITIAL.      READ TABLE mt_sflight INTO ls_sflight INDEX iv_lead_index.      IF sy-subrc = 0.        CREATE OBJECT mo_sflight TYPE zcl_fpm_demo_wire_sflight.        mo_sflight->set_sflight( ls_sflight ).        lo_datacontainer->set_lead_selection( mo_sflight ).      ENDIF.  ENDCASE.
ENDMETHOD.

 

The selected flight record is show in the detail section of the screen. Its feeder does not yet have a FLUSH-implementation which needs to be implemented. Its purpose would be to transfer the entered values back to the flight record instance.
Therefore the form feeder class ZCL_FPM_DEMO_FORM_SFLIGHT_DET receives a FLUSH-method implementation:

METHOD if_fpm_guibb_form~flush.  CHECK mo_connector IS NOT INITIAL.  mo_sflight ?= mo_connector->get_output( ).  CHECK mo_sflight IS NOT INITIAL.  FIELD-SYMBOLS <ls_data> TYPE any.  ASSIGN is_data->* TO <ls_data>.  DATA ls_sflight_key LIKE ms_sflight.  MOVE-CORRESPONDING <ls_data> TO ms_sflight.  MOVE-CORRESPONDING <ls_data> TO ls_sflight_key.  ms_sflight-carrid = ls_sflight_key-carrid.  ms_sflight-connid = ls_sflight_key-connid.  ms_sflight-fldate = ls_sflight_key-fldate.  mo_sflight->set_sflight( ms_sflight ).
ENDMETHOD.

Now, the OVP exit has also access to the currently selected flight record instance through its configured list selection wire. The OVP exit is implemented by the webdynpro component ZWDYN_FPM_FLIGHT_OVP_EXIT. The implementation of method OVERRIDE_EVENT_OVP now needs to try to read the flight record instance from the wire model and enrich the Save-Event with the flight record data object. Please note that we pass an instance of type ZIF_FPM_DEMO_SAVEABLE rather than ZIF_FPM_DEMO_WIRE_SFLIGHT.

 

METHOD override_event_ovp.
 wd_this->mo_ovp = io_ovp.  DATA lo_event TYPE REF TO cl_fpm_event.  DATA: lo_datacontainer TYPE REF TO zif_fpm_demo_wire_flight_sel,        lo_saveable TYPE REF TO zif_fpm_demo_saveable.  DATA lv_port_identifier TYPE fpm_model_port_identifier.
 lv_port_identifier = zif_fpm_demo_wire_flight_sel=>gc_name.  lo_event = io_ovp->get_event( ).  CASE lo_event->mv_event_id.    WHEN if_fpm_constants=>gc_event-save OR if_fpm_constants=>gc_event-save_and_back_to_main.      TRY.
 lo_datacontainer ?= wd_this->mo_feeder_model->get_outport_data( iv_port_type = 'LS' iv_port_identifier = lv_port_identifier ).          CHECK lo_datacontainer IS BOUND.          lo_saveable ?= lo_datacontainer->get_lead_selection( ).
 lo_event->mo_event_data->set_value( iv_key = zif_fpm_demo_saveable=>gc_event_parameter_id iv_value = lo_saveable ).        CATCH cx_sy_move_cast_error.      ENDTRY.  ENDCASE.
ENDMETHOD.

ZIF_FPM_DEMO_SAVEABLE serves as a generic interface for a save operation. It is implemented by the wire which represents the flight record (ZCL_FPM_DEMO_WIRE_SFLIGHT)

Interface ZIF_FPM_DEMO_SAVEABLE.PNG

The class ZCL_FPM_DEMO_WIRE_MODEL_TRANS serves as the application wire transaction handler. It implements the standard FPM interface IF_FPM_WIRE_MODEL_TRANSACTION and therefore takes part in the event loop. The method AFTER_PROCESS_EVENT is implemented and handles the SAVE-Event which will later on be triggered once the Save-Button has been pressed. The method implementation tries to read an instance of type ZIF_FPM_DEMO_SAVEABLE from the event data and eventually call the SAVE-Method.

 

METHOD if_fpm_wire_model_transaction~after_process_event.  DATA: lo_savable TYPE REF TO zif_fpm_demo_saveable.  CASE io_event->mv_event_id.    WHEN if_fpm_constants=>gc_event-save OR if_fpm_constants=>gc_event-save_and_back_to_main.      TRY.
 io_event->mo_event_data->get_value(
 EXPORTING iv_key = zif_fpm_demo_saveable=>gc_event_parameter_id
 IMPORTING ev_value = lo_savable ).          CHECK lo_savable IS NOT INITIAL.
 lo_savable->save( ).        CATCH cx_sy_move_cast_error.      ENDTRY.  ENDCASE.
ENDMETHOD.

Once the transaction handler class has been implemented, we register the transaction handler in the OVP-Component FPM_OVP_COMPONENT, Configuration ZFPM_DEMO_OVP_FLIGHT_SEARCH

Register wire transaction model.PNG

Why should we not simply enhance the OVP-Exit?

The reason why I didn’t just implement the Save-operation directly in the OVP-Exit is the Separation of concerns design principle.

In the case of having an exit only and no transaction handler, the OVP Exit would have to evaluate the save event and trigger the SAVE-Method, besides its task of updating the OVP floorplan title with the number of results. Also, an OVP Exit is not reusable in OIF or GAF floorplans, and this would also apply to its transaction logic, if coupled too strongly.

Right now, with the current implementation, it only does, what an exit is intended to do: It catches certain events like the Save-event and enriches it with some data, if necessary. The actual SAVE-Method call is triggered by another component which actually does not care about how or by whom the  event has been enriched – it just expects the business object along with the event data. This decouples the execution of the SAVE-Command from other aspects of the application and eventually leads to a better design and maintainability. There is no real benefit yet, but in case a more complex transaction logic would be needed, we could easily provide the implementation of these aspects, like commits or rollbacks, in a specific transaction handler, not within the OVP Exit.

 

Download the nugget file here


Perform Save-operations using a wire transaction handler in the FPM - Refactoring

$
0
0

Introduction

In the previous blog post, I introduced the Save-operation by using a wire transaction handler. The main statement below this blog post was, that an event can be enriched by an OVP-exit before it is getting processed by a wire transaction handler. The event receives a new parameter value, which is an instance of a saveable business object, that is, an ABAP Object implementing ZIF_FPM_DEMO_SAVEABLE.

There is a small issue with the way the wire transaction handler handles the event. In this short blog post I would like you to show what the problem is and how it can be fixed.

 

The existing wire transaction handler implementation

Right now, the wire transaction handler implementation reads the business object by a hard coded key-value:

 

METHOD if_fpm_wire_model_transaction~after_process_event.  DATA: lo_savable TYPE REF TO zif_fpm_demo_saveable.  CASE io_event->mv_event_id.    WHEN if_fpm_constants=>gc_event-save OR if_fpm_constants=>gc_event-save_and_back_to_main.      TRY.          io_event->mo_event_data->get_value(            EXPORTING iv_key = zif_fpm_demo_saveable=>gc_event_parameter_id            IMPORTING ev_value = lo_savable ).          CHECK lo_savable IS NOT INITIAL.          lo_savable->save( ).        CATCH cx_sy_move_cast_error.      ENDTRY.  ENDCASE.
ENDMETHOD.

 

The value represented by constant zif_fpm_demo_saveable=>gc_event_parameter_id serves as a key to retrieve the business object that has been hooked previously to the event by the OVP-exit.

 

This coding violates the Open-Closed-Principle which says "software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification" (Meyer, Bertrand (1988). Object-Oriented Software Construction. Prentice Hall. ISBN 0-13-629049-3)

Why is this transaction handler affected by this principle?

The answer is quite easy: Every time we reuse the wire transaction handler in another application, we would also need to read business objects which have been hooked into the event by other exits, possibly with other key values. If this was the case, every reuse would cause the coding shown above to be changed in order to support other key values:

 

METHOD if_fpm_wire_model_transaction~after_process_event.  DATA: lo_savable TYPE REF TO zif_fpm_demo_saveable.  CASE io_event->mv_event_id.    WHEN if_fpm_constants=>gc_event-save OR if_fpm_constants=>gc_event-save_and_back_to_main.      TRY.          io_event->mo_event_data->get_value(            EXPORTING iv_key = zif_fpm_demo_saveable=>gc_event_parameter_id            IMPORTING ev_value = lo_savable ).          CHECK lo_savable IS NOT INITIAL.          lo_savable->save( ).        CATCH cx_sy_move_cast_error.      ENDTRY.                TRY.          io_event->mo_event_data->get_value(            EXPORTING iv_key = zif_fpm_demo_saveable=>gc_event_parameter_id2            IMPORTING ev_value = lo_savable ).          CHECK lo_savable IS NOT INITIAL.          lo_savable->save( ).        CATCH cx_sy_move_cast_error.      ENDTRY.  ENDCASE.
ENDMETHOD.

 

You recognized the changed coding already: another business object is read from the event with the key zif_fpm_demo_saveable=>gc_event_parameter_id2.

The way we deal with changes here is not a good practice.

 

Changes to the existing logic

Instead of supporting every thinkable FPM parameter key in the wire transaction handler, we improve the logic a little bit and make it more smart: The event parameters are now iteratively read and the handler tries to down-cast it to an instance of type ZIF_FPM_DEMO_SAVEABLE. If the down-cast fails, nothing happens (no SAVE-method is invoked) and the logic continues with the next event parameter until no more parameters are left.

 

METHOD if_fpm_wire_model_transaction~after_process_event.   DATA: lo_saveable TYPE REF TO zif_fpm_demo_saveable.   DATA lt_keys TYPE if_fpm_parameter=>t_keys.   FIELD-SYMBOLS <lv_key> LIKE LINE OF lt_keys.   CASE io_event->mv_event_id.     WHEN if_fpm_constants=>gc_event-save OR if_fpm_constants=>gc_event-save_and_back_to_main.       lt_keys = io_event->mo_event_data->get_keys( ).       LOOP AT lt_keys ASSIGNING <lv_key>.         io_event->mo_event_data->get_value(           EXPORTING iv_key = <lv_key>           IMPORTING ev_value = lo_saveable ).         CHECK lo_saveable IS NOT INITIAL.         lo_saveable->save( ).       ENDLOOP.   ENDCASE.
ENDMETHOD.

 

Now the wire transaction handler does not need any further update for any new use case any longer. It works, no matter if you pass zero, one or multiple different instances of type ZIF_FPM_DEMO_SAVEABLE to it.

In order to avoid parameter key collisions, the OVP exit is also updated a little bit. Instead of setting the business object with the hard coded key value represented by ZIF_FPM_DEMO_SAVEABLE=>GC_EVENT_PARAMETER_ID, let's create a guid as a key value by using the CL_UUID_FACTORY.

Since the wire transaction handler does not rely on any specific key values any longer, it is going to work even after this change:

 

 METHOD override_event_ovp.  wd_this->mo_ovp = io_ovp.  DATA lo_event TYPE REF TO cl_fpm_event.  DATA: lo_datacontainer TYPE REF TO zif_fpm_demo_wire_flight_sel,        lo_savable TYPE REF TO zif_fpm_demo_saveable.  DATA lv_port_identifier TYPE fpm_model_port_identifier.  DATA lv_key TYPE string.  DATA lo_generator TYPE REF TO if_system_uuid.  CALL METHOD cl_uuid_factory=>create_system_uuid    RECEIVING      generator = lo_generator.  lv_key = lo_generator->create_uuid_c22( ).  lv_port_identifier = zif_fpm_demo_wire_flight_sel=>gc_name.  lo_event = io_ovp->get_event( ).  CASE lo_event->mv_event_id.    WHEN if_fpm_constants=>gc_event-save OR if_fpm_constants=>gc_event-save_and_back_to_main.      TRY.          lo_datacontainer ?= wd_this->mo_feeder_model->get_outport_data( iv_port_type = 'LS' iv_port_identifier = lv_port_identifier ).          CHECK lo_datacontainer IS BOUND.          lo_savable ?= lo_datacontainer->get_lead_selection( ).          lo_event->mo_event_data->set_value( iv_key = lv_key iv_value = lo_savable ).        CATCH cx_sy_move_cast_error.      ENDTRY.  ENDCASE.
ENDMETHOD.

 

Benefits

The wire transaction handler is now much more robust against changes in any exit which enriches the save-event with a saveable business object. This increases reusability without cutting functionality.

The usage of the handler has been made easier dramatically since it tries to extract instances of type ZIF_FPM_DEMO_SAVEABLE from any event parameter instead of event parameters with a specific key. Any application that reuses this handler does not need to be aware of the parameter key value of that object, it just needs to make sure, that an instance of a saveable business object has been hooked into the event data with a freely defineable key value before the handler is getting executed - and that's it.

Wiring heterogeneous feeder models together - or the fairytale of Hänsel and Gretel

$
0
0

Introduction

Recently I was asked as a reply to one of my previous blog posts, wether it is possible to wire multiple UI building blocks to one target. The target could be a transaction component in order to save all of these models when the users presses the "Save" button in the UI.

The exact question was:

 

"If we have a GAF with several steps and at the last step we want to save all the GUIBB's. Some GUIBB's have there own model.We have created a WD component with interface IF_FPM_TRANSACTION. We want to transfer all the GUIBB models to the transaction component.Wiring would be nice, but we have more sources to the transaction component. That is the reason why I would like to have more sources to a target. What would you do? We can always use a factory singleton, but if we do that then the wiring would not be needed anymore."

 

Unfortunately, SAP says clearly, that every UIBB may serve as a source for wiring multiple times, while it may serve as a target only once.

To answer the question, having a FPM transaction component as a target for multiple UIBBs is not possible. But there is a workaround, which could help solving this issue.

 

The fairytale of Hänsel and Gretel

The basic question is, how heterogeneous feeder models can be connected to a single UIBB feeder model which eventually performs a Save-operation on all the received feeder models.

This is where a commonly known fairytale comes into the scene.

Imagine, we had a Guided Activity FPM application. The first steps shows the "Hänsel" UI-Building Block which has its own feeder model to read the data and save it afterwards. The second step is the "Gretel" UI Building Block which has a totally different feeder model with its own data. The main question is: What happens to these feeder models and what are the further operations invoked?

Everyone who knows the fairytale already has the answer: Both are held captive by a witch. But what does that have to do with our FPM application?

 

Technically spoken, we need to transfer both feeder models to a composite feeder model. This is, where the composite pattern is used.

Both feeder models need to implement the same interface ZIF_FPM_SAVEABLE_FEEDER_MODEL which forces its implementers to implement a SAVE( )-Method.

ZIF_FPM_COMPOSITE_MODEL inherits from ZIF_FPM_SAVEABLE_FEEDER_MODEL and describes what a composite feeder model should be able to do. Despite the SAVE( )-method, it requires another method +ADD_MODEL(IO_MODEL : ZIF_FPM_SAVEABLE_FEEDER_MODEL). The composite feeder model is implemented by ZCL_WITCH_MODEL.

This means, the witch model may include other feeder models and subjects them to a common treatment, which is, in this very example, the Save-operation.

Wiring Model.png

The wiring behaviour of the UIBBs now needs to work like this:

1. If the input which comes from a wire, is not initial, the UIBB checks if the input is a composite feeder model of type ZIF_FPM_COMPOSITE_MODEL (to do so, simply down-cast the connector's output to an instance of type ZIF_FPM_COMPOSITE_MODEL and catch the CX_SY_MOVE_CAST_ERROR exception, if raised)

2. If no input was provided, or the input had the wrong data type, a new composite model of type ZIF_FPM_COMPOSITE_MODEL is created by the UIBB

3. A new outport of the UIBB is created which outputs a composite model of type ZIF_FPM_COMPOSITE_MODEL

4. The UIBB's feeder model is added to the output using the ADD_MODEL-Method of the composite model

 

This approach allows you to wire multiple UIBBs, who have a completely different feeder model, together. The output of every feeder model will be an instance of type ZIF_FPM_COMPOSITE_MODEL. Now we've got several wiring possibilities to wire the UIBBs and the FPM transaction component together.

 

Option 1 - The FPM transaction component pushes ZIF_FPM_COMPOSITE_MODEL to the feeders

Both feeders receive the witch, which is an instance of type ZIF_FPM_COMPOSITE_MODEL. Every UIBB adds its own model by calling the ADD_MODEL method. In the end, the witch holds captive all the feeder models.

Option 1 - FPM transaction handler pushes ZIF_FPM_COMPOSITE_MODEL to the feeders.png

Option 2 - The FPM transaction component receives  ZIF_FPM_COMPOSITE_MODEL

The UIBBs are connected in series. The last chain link is the transaction component. In contrast to the fairytale, the witch is created by Hänsel and is handed over to Gretel. The transaction component receives the witch in the end. Again, the witch holds captive the two other feeder models.

Option 2- The FPM ransaction handler is the last chain link.png

 

Conclusion

If feeder models need to be transferred using wires, a common interface and the use of the composite pattern may be an option, if the implementations of the feeder models differ. This is often the case, if the UIBBs in the application were initially build up for another use case, but now need to be combined for a new application.

However, the interface which needs to be implemented yby the feeder models depends on the type of common treatment you want to apply to the feeder models. So there is still the effort of applying the above shown changes to existing feeders.

SRM7 - Include Custom logic inside standard FPM Action in PO

$
0
0

In this Blog I am going to talk to about, how to interrupt the standard FPM actions and induce our custom logic and then continue with the execution of standard code. Instead of just explaining the methodology, I would like to state an imaginary requirement and explain the methodology as we fulfill the requirement. Here is the most amazing requirement you have ever heard

 

When we click on EDIT button on PO screen, user should get a pop-up which will have some check boxes, each referring to a particular field of PO. Once the user selects some check box and clicks on OK button, corresponding field and label should be removed from the screen. Below is screen shot of how it should look

 

edit button.JPG

 

Now on a high level, we should know which code gets triggered when we click on EDIT button, enhance it and include the code to generate a pop-up screen. Also when we click on OK button execute whatever logic we want to execute and then let the standard code get execute.

 

How to figure out the code that gets executed when we click on EDIT button:

 

The header buttons in PO screen are not part of any particular webdynpro component. This makes it difficult to debug these actions. We have to go to the corresponding AppCC component ( refer to my blog to know more about AppCC ( Dynamically Modifying Purchase order FPM in SRM7 using custom AppCC) and debug the component controller method OVERRIDE_EVENT_OIF to figure out what code gets executed when we click on EDIT button. Below are the details

 

- control first goes to the statement  wd_this->mo_oif_helper->override_event_oif( ). Here mo_oif_helper refers to class /SAPSRM/CL_FPM_OVRIDE_OIF.

 

- once inside the method OVERRIDE_EVENT_OIF of class /SAPSRM/CL_FPM_OVRIDE_OIF, control goes to the statement

 

mo_ident_mapper->handle_event(

            EXPORTING io_event = mo_fpm_oif->mo_event ).

 

Here mo_ident_mapper refers to class /SAPSRM/CL_CH_WD_IDEN_MAP_PO. Inside the method handle_event is the code related to respective action.

 

How to generate a pop-up dialog box:

 

To do this, first we enhance the AppCC component and create a View ( POP_VIEW), a  window (POP_WIN) and embed the view inside the window. Also, add two check box with descriptions as shown in the above screen shot ( I assume reader knows how create view, window and check boxes, so i am not going to explain that in detail here ).

 

enhwdconf.JPG

Layout of the view

layout.JPG

 

Create two context attributes and bind them to 'Checked' property of the check-box

 

context.JPG

 

Once we have everything ready, we go to the method  HANDLE_EVENT method of class  /SAPSRM/CL_CH_WD_IDEN_MAP_PO, create an implicit enhancement and insert the below code.

 

DATA lo_window_manager TYPE REF TO if_wd_window_manager.

  DATA lo_api_component  TYPE REF TO if_wd_component.

  DATA lo_api_controller TYPE REF TO if_wd_controller.

  DATA lo_window         TYPE REF TO if_wd_window.

  *check if the event is EDIT

  IF  io_event->mv_event_id = 'FPM_EDIT'.

*check if pop up is required

    IF zcl_popup=>popup_req EQ 'X'.

 

 

      lo_api_controller  =  mo_wd_component_controller->wd_get_api( ).

 

 

      CALL METHOD lo_api_controller->get_component

        RECEIVING

          component = lo_api_component.

 

*get access to window manager

      lo_window_manager = lo_api_component->get_window_manager( ).

 

*create window

      lo_window         = lo_window_manager->create_window(

      window_name            = 'POP_WIN'

      title                  = 'Please selct...'

      message_display_mode   = if_wd_window=>co_msg_display_mode_selected

      close_button           = abap_false

      button_kind            = if_wd_window=>co_buttons_ok

      message_type           = if_wd_window=>co_msg_type_none

      default_button         = if_wd_window=>co_button_ok

      ).

 

 

* Set the height and width here

      lo_window->set_window_size( width = '20%' height = '15%' ).

      lo_window->open( ).

      EXIT.

    ENDIF.

  ENDIF.

To your surprise, most important piece of code in the above code is 'EXIT' statement. If we don't exit from the method after raising the pop up, what happens is, we get the pop-up BUT system continues with the afterwards code and removes the pop-up from the screen. So, we will not be able to select any check box on the pop-up. In order for pop-up to stay on the screen, till we select something on the screen and click on OK button, we have to exit the method. But there is a catch here... If we exit the method,  we are skipping the actual code related to EDIT action. So, we have to somehow re trigger the action EDIT, once we are done with check box selection on pop-up ( Just to keep the suspense alive, I will come back to this later )

 

I have created a class with name ZCL_POPUP and added three static attributes as shown below

 

staticclass.JPG

Here POPUP_REQ attribute is used to check, if pop-up needs to be created or not ( by default it is set to 'X'). Attributes CHECK1 and CHECK2 are used to capture the selection made by the user on pop-up screen.

 

Let's look at what happens in the view POP_VIEW...

 

In WDDOMODIFYVIEW method,  we use the below code to assign an action to button OK on pop-up

 

  DATA:l_api TYPE REF TO if_wd_view_controller,

       l_window_ctlr TYPE REF TO if_wd_window_controller,

       l_popup TYPE REF TO if_wd_window.

 

 

  l_api = wd_this->wd_get_api( ).

  l_window_ctlr = l_api->get_embedding_window_ctlr( ).

 

 

  IF l_window_ctlr IS BOUND.

    l_popup = l_window_ctlr->get_window( ).

 

 

    l_popup->subscribe_to_button_event(

       button = if_wd_window=>co_button_ok

       action_name = 'OK'

       action_view = l_api

       is_default_button = abap_true ).

 

 

  ENDIF.

 

we also add an event with name OK, this creates an event handler with name ONACTIONOK in methods tab of the view POP_VIEW. In the action handler we write the below code

 

DATA: lo_fpm TYPE REF TO if_fpm.

  DATA lo_el_context TYPE REF TO if_wd_context_element.

  DATA ls_context TYPE wd_this->element_context.

  DATA lv_check1 TYPE wd_this->element_context-check1.

  DATA lv_check2 TYPE wd_this->element_context-check2.

 

 

*clear static attribute popup_req

 

  CLEAR zcl_popup=>popup_req.

 

* get element via lead selection

  lo_el_context = wd_context->get_element( ).

 

 

* read context attributes check1 and check2

  lo_el_context->get_attribute(

    EXPORTING

      name =  `CHECK1`

    IMPORTING

      value = lv_check1 ).

 

 

  lo_el_context->get_attribute(

     EXPORTING

       name =  `CHECK2`

     IMPORTING

       value = lv_check2 ).

 

*set the static variables 

  zcl_popup=>check1 = lv_check1.

  zcl_popup=>check2 = lv_check2.

 

*Get rererence to current FPM instance

  lo_fpm = cl_fpm_factory=>get_instance( ).

 

*Trigger the EDIT action again 

  CALL METHOD lo_fpm->raise_event_by_id

    EXPORTING

      iv_event_id = 'FPM_EDIT'.

 

Here we are reading the context attributes CHECK1 and CHECK2 and store the values in static attributes of the class ZCL_POPUP. Then using raise_event_by_id method we are re triggering event FPM_EDIT ( suspense is over now..   )

 

Now to Hide the PO number and PO name fields from the overview, we can use the BADI WD_BADI_DOMODIFYVIEW. Create an implementation with below filter

 

badifilter.JPG

 

Inside the method IF_WD_BADI_DOMODIFYVIEW~WDDOMODIFYVIEW, write below code

 

DATA : lo_ref TYPE REF TO cl_wd_transparent_container.

 

  lo_ref ?= view->get_element( 'LEFT_CONTAINER' ).

 

  IF zcl_popup=>check1 EQ 'X'.

 

    IF lo_ref IS NOT INITIAL.

      lo_ref->remove_child( id = 'PO_NUMBER_LABEL' ).

      lo_ref->remove_child( id = 'PO_NUMBER' ).

    ENDIF.

 

  ENDIF.

 

 

  IF zcl_popup=>check2 EQ'X'.

 

    IF lo_ref IS NOT INITIAL.

      lo_ref->remove_child( id = 'PO_NAME_LABEL' ).

      lo_ref->remove_child( id = 'PO_NAME' ).

    ENDIF.

 

  ENDIF.

 

 

Here based on values of static attributes CHECK1 and CHECK2 of class ZCL_POPUP, we conditionally remove PO number / PO name fields from the PO screen

 

DEMO:

 

User clicks on EDIT button on PO screen, which triggers a pop-up that has two check boxes on it. User selects both the check boxes and clicks on OK button.

clickok.JPG

After OK button is clicked, PO number and PO name fields are removed from the overview screen.

 

pofinal.JPG

 

I am sure that there might be a better solution for this and  I sincerely welcome all the suggestions from readers.

 

Finally, I would like to thank Matteo Montalto  for his invaluable contribution towards this blog.

How to enable IGS (Internet Graphics) services and crystal report option in SAP analytics ALV list in FPM

$
0
0

This blog is useful for enabling internet graphics and crystal report option for your SAP Analytical List Viewer (ALV). So that you
will be able to see graphics view in your FPM application.

 

Maintain some necessary R/3 system SPRO customizing as per below steps.

 

Step 1. Open
transaction code SPRO.

 

Step2. To activateIGS Services follow the below snap shot.

Execute the Maintain Webdynpro ABAP-Specific Settings and check the option Java Server Available save the settings

as per the below snap shot.

 

1.png

 

2.png

 

 

 

Step 3. To activateCrystal Report follow the below snap shot.

 

Execute the Maintain SAP GUI-Specific Settings and check the option Allow Crystal Reports  and save
the settings as per the below snap shot.

 

3.png

 

4.png

 

 

 

Result : Now you will see all the display as option in drop down in the toolbar of Analytical ALV list.

 

result_alv.png

** TEAM FPM ** - Model-Driven UI Development with FPM

$
0
0

To derive user interfaces directly from business logic relations is a hot, lengthily-discussed topic and an old dream of Software Architects and User Interface Designers over the last decade. Many frameworks were built to reach this goal, but most of them failed due to the complexity of the business logic which needed to be implemented. Until now! With the Floorplan Manager (FPM), this dream became reality: generation and configuration of user interfaces has never been as easy as it is today with FPM.

 

FPM started from the opposite point. Established as a UI framework based on Web Dynpro ABAP, FPM streamlined the appearances of applications in the classic ERP by providing central components for the assembly of the UI parts. These central components served as the skeleton of the applications and were consequently called ‘floorplans’. What FPM had to offer was spiced up ever more with additional components for common UI patterns such as forms, lists, hierarchies, searches and so on. Business logic was encapsulated in feeder classes and thus the idea was somehow obvious to provide generic feeders to consume business object models. The image below is a screenshot of an FPM application generated purely on OData information retrieved from the World Wide Web (WWW) – without any line of UI coding to be written.

 

FPM_MDD_1.png

 

But stop! We should go back three steps …

 

Where do we come from? What are the stages of UI development? A short subjective historical overview is needed:

 

As I struggle to decide whether I have just started the second half of my life or have already finished the first half, I came into contact with computers and programming with the legendary TI99 – and I am still missing the GOSUB-statement. Later, with Fortran or the much cooler Pascal, we coded everything into one stream of code. Statements as writeln() and readln() were spread all over the code; UI and business logic were completely mixed up together.

 

When I started at SAP some time ago, we studied ABAP and wrote reports and GUI screens. The Screen Painter was already a step forward; the first time that I came into contact with a graphical design tool where user interfaces were not coded! But the Screen Painter only provided the UI layout; UI logic and business logic were still mixed inside the coding (LEAVE TO SCREEN 100).

 

Later, Web Dynpro ABAP came into the game with the MVC (model-view controller) architecture and the separation of components and their configuration. It became possible to define components and allow for code-free configuration on top. Actually, it was the SAP HCM development area who delivered the first pre-configured components. And this is the point where FPM enters the game; and now we can continue with what was said before.

 

FPM exploited the possibilities of UI components and their configurations to a maximum extent. By means of the UI components, common parts of typical applications were defined and feeder interfaces were introduced as communication interfaces between these UIcomponents and the application logic. Application developers implement the feeder interfaces within the feeder classes in which they define the data structures, the data itself, the actions and the event processing. The entire UI definition is separated from the business logic; the UI is defined entirely in configuration, based on the feeder classes which define what can be configured on the UI (fields defined in data structures convert into form elements or table columns, actions convert into buttons or links). This procedure provides a lot of freedom for UI composition. All good and desirable, but what about a generic approach? What if you knew already about the data definition and their relations? What if you could generically access the data without writing feeder classes? What if you could already propose the structure of the application and a first UI? Unrealistic?  Hmm, let’s see…

 

Business object models allow the description of objects and their relations in a well-defined way. Some of them – like BOPF – model the business logic directly on the database tables. Others – like BOL – allow the consumption of legacy business logic which has already been encapsulated in APIs. For completeness, one should mention SPI (Service Provider Infrastructure) which provides an external facing on the UI so that it can be used in the Demilitarized Zone and, last but not least, OData, the Open Data protocol which serves as a web standard to expose any data in the WWW for any consumption based on industry standards like REST, XML, HTTP, Atom and JSON.  There are many differences between these object models, but all of them define objects, relations, actions and queries. All of them provide a full and comprehensive encapsulation which serves as a uniform facade for further consumption. So they are generically accessible by a UI framework.

 

Generic feeders are provided by FPM and by other frameworks to access the data, their relations and their actions. Depending on the relations, the cardinality can be derived and this decides whether a form or a list should be used to display the data (or better still, a form-repeater with a separate details block?). Queries are transformed into a search screen to access the root object. Using the FPM wiring concept, even the dependencies between UIBBs (e.g. adapting content of a details view when changing the selection in a master table) can be pushed to the UI configuration whereas the business logic part of the dependencies (e.g. an association between the nodes) is encapsulated in generic connector classes.

 

This all works perfectly for BOL (Business Object Layer) and has proven its value in the renovation projects within HCM and FIN development. FPM provides a creation wizard, the ‘Application Creation Tool’ which accesses a certain BOL component and transforms all available nodes into UI Building Blocks (UIBBs) – well, you have a chance to de-select those nodes you do not want to see on your UI and which have no relevance to the application you are going to construct (see image below). These UIBBs are put together into an Overview Page Floorplan (OVP) and are wired according to their relation defined in BOL – and your application can be generated out of the box. You are totally free to adapt this application in FLUID (Flexible UI Designer – the FPM configuration editor). There, you can refine the UI, eliminate unwanted table columns and form elements, add and rearrange fields, columns and buttons or simply change display types if needed, and you can revise the wiring between the UIBBs. So you gain both: an application generated based on the definitions defined in the object modeling layer, and a UI with highly-flexible configurability options. Talk about easy UI creation!

 

FPM_MDD_2.png

 

What works for BOL also works for BOPF (Business Object Processing Framework). Since the FPM does not provide generic feeders for BOPF, an intermediate layer has to be used, the so-called BOL-BOPF adapter. This adapter provides a seamless transfer of BOPF model definition to the BOL-based FPM feeders. This allows for a revolutionary end-to-end process. In the Business Object Builder (formerly known as BOPF Enhancement Workbench (see sample image below)) you can define your business logic with all the objects, their relations and their actions. In the next step, you can start the ‘Application Creation Tool’ (mentioned previously) and construct your application with BOL feeders but based on your underlying BOPF scenario.


FPM_MDD_3.png

 

This approach helps application developers to first invest into the clear analysis of the business process and to separate business logic from the UI entirely. Additionally, with this approach it is possible to start IT projects in complete reverse, compared to how they were started one decade ago. Instead of letting hundreds of UI developers swarm around and build their individual ‘perfect’ islands (which fit together so badly inhomogenously), the first move is with the architects who know and understand the business processes; so they can build and refine the underlying business model. Then, finally, based on this business model, the UI can be created and tailored exactly to the process that customers want to install. These UIs can then be adapted flexibly and enhanced easily by pure UI configuration – but without altering the business model underneath. This will definitely lead to a so-far-unknown and much higher level of business process integrity in modern UIs.

 

You want more information? See Floorplan
Manager on SCN, e.g. the Administrator’s Guide, the Developer’s Handbook (http://scn.sap.com/docs/DOC-30668 ), the Adaptation Guide (http://scn.sap.com/docs/DOC-28799 ) and many others. – For BOPF, here is the documentation on the Business Object Builder (BOB).

SRM7- Create new variant for FPM component configuration for PO

$
0
0

In this blog I will explain how to create new variant for PO FPM component configuration. Also, will show you how to call this new variant based on custom logic. This can be used, if we need to display different buttons/tabs in PO screen when accessed from different places.

 

  1. Go to SE80, go to component FPM_OIF_COMPONENT and expand component configuration node and select configuration ZENH_SAPSRM_WDCC_PO_PURCH ( In my case I already had created a custom variant with delegation to standard configutaion)

img1.jpg

2. Click on ‘Start Configurator’. This will open up configuration screen in a browser

2.png

 

3. Click on ‘Change’ button. You will see a pop-up asking for transport request. Select the existing request or create a new one.

4. Click on ‘Copy’ button and select ‘Variant’

4.png

5. A new pop-up window asking for new variant name will appear on the screen

5.png

6. Click on ‘Copy’.

7. All mainview and subview IDs have ‘_1’ appended at the end

 

Mainview ‘Header’

6.png

 

Subview ‘Notes and Attachments’

7.png

 

8. In general we don’t have to change these IDs, but in case of PO, we faced an issue with PO item details button. Below error appears when we click on ‘Details’ button at item level.

8.png

Because of this reason, we had to change the mainview ID from PO_ITM_1 to PO_ITM

 

9.png

 

9. To hide a button from the screen, select the button and choose ‘Is not visible’ option from ‘Visibility’ dropdown.

10.png

10. Finally click on ‘Save’.

 

How to call the new variant from ABAP code:

Create an implicit enhancement in method HANDLE_VIEW_SWITCH_VISIBILITY of class /SAPSRM/CL_FPM_OVRIDE_OIF and call method SET_VARIANT’ of interface IF_FPM_OIF ( mo_fpm_oif variable in the method ).

 

 

Thanks for taking time and reading the blog.


** TEAM FPM ** - Switching from the Old List UIBB to the New List UIBB (aka List ATS UIBB)

$
0
0

This blog post describes how to replace the old List UIBB with the new one.

 

The new List UIBB is known as the List ATS UIBB (ATS stands for ABAP Table Services).
To find out which List component your FPM application uses, look at the name of the WD ABAP

component of the List component; FPM_LIST_UIBB is the old List component, FPM_LIST_UIBB_ATS

is the new List component. (Use FLUID, the FPM configuration editor, at floorplan level to find out the
WD ABAP component name).

 

The List ATS UIBB is available from SAP NetWeaver 7.31 onwards (software component SAP_BASIS).

 

 

Why Switch to the List ATS UIBB?

 

 

The List ATS UIBB has several advantages over the old List UIBB, with the most important being:

 

  • smooth vertical and horizontal scrolling
  • an integrated personalization dialog box
  • advanced filter, sorting, and grouping capabilities
  • different aggregation possibilities
  • the ability to create different views
  • mass edit mode (meaning the List component creates dummy rows at the bottom of the
    list, enabling the user to enter new data quickly and easily)
  • copying data to and from a Microsoft Excel spreadsheet

             

How is the transition done? Like all FPM generic UIBBs (GUIBBs), the List ATS UIBB
consists of a WD component (FPM_LIST_UIBB_ATS), a feeder class and a
configuration. The interface for the feeder class is actually the same for both
the old and new List components; this makes life easier because it means you
can just reuse the current feeder class without needing to change anything (you
could make changes though, and I will point that out at a later point in this
blog). So, all that's needed is to exchange the old List UIBB with the List ATS
UIBB in the floorplan configuration, and to create a new configuration for the
newly-added List ATS UIBB. And here's how to do that, in detail:

 

  1. Start FLUID and open the floorplan configuration (that is, an OVP, GAF or OIF
    configuration) of your application and switch to edit mode.
  2. In the floorplan schema, locate and remove the old List UIBB.
  3. Press the Add UIBB button and choose List UIBB. This will automatically add the
    List ATS UIBB.
  4. In the floorplan schema, locate the row that contains the new List ATS UIBB.
    You will see that a configuration is missing for the new UIBB. Enter a configuration
    name into the corresponding input field and press the Save button - and don't worry
    if your configuration doesn't actually exist yet - you can create it in the next step.
  5. Make sure the List ATS UIBB is selected and press the Configure UIBB button
    in the panel's toolbar.
  6. In the window that is opened, press the Create Configuration button. The
    editor asks for the name of the feeder class. As pointed out earlier, you can
    use the same feeder class for the old and new List components.
  7. After you have entered the name of the feeder class, add all the columns and toolbar
    elements that were there for the old List UIBB. You might also want to have a look at the
    General Settings panel as it contains some additional settings for the List ATS UIBB.
  8. Save your changes and restart your application. You should now see the
    List ATS UIBB in action.

 

These instructions are mainly intended for applications that were developed customer-side.
In this case, the instructions above will lead to a modification of the floorplan configuration.

However, if you want to avoid modifications (for example, if the configuration is provided by

SAP), you have the possibility to enhance it or to create a customizing for it (SAP Note
1619534 provides documentation on how to do that).

 

 

Important Remarks &
Restrictions:

 

 

The old List UIBB had the WD ABAP implicit personalization enabled; the end user could
access the WD ABAP implicit personalization at runtime using the context menu (for example,
they could set columns to invisible or change the amount of visible rows). After the transition
to the List ATS UIBB, the implicit personalization of WD ABAP is switched off; the end user
will not be able to access the WD ABAP implicit personalization using the context menu. Instead,
there is now a new explicit Personalization dialog box available (it can be accessed via a button
on the toolbar). The implicit WD ABAP personalization of the old List UIBB is lost and there is no
possibility for converting it.

 

 

Additionally, the old List UIBB supported three different rendering modes: Standard Rendering,
ALV Rendering and Row Repeater Rendering (see the General Settings panel in the configuration

of the old List UIBB). The List ATS UIBB does not support these rendering modes.
ALV Rendering is not necessary anymore; all its features are available in the List ATS UIBB (personalizations
made in this rendering mode will not be available in the List ATS UIBB). Row Repeater Rendering is also not
supported in the List ATS UIBB; a much better way for that is the FPM Form Repeater UIBB (WD component

FPM_FORM_REPEATER_UIBB).

 

Remarks regarding the Feeder Class:

 

As I've already mentioned, feeder classes of the old List UIBB and the List ATS UIBB use the same feeder

class interface (IF_FPM_GUIBB_LIST). That means feeder classes of the old List UIBB can be reused without

the need for changing them. However, there are a few parameters that are intended for the List ATS UIBB only,

and which can be used optionally:

 

  • Method
    PROCESS_EVENT, parameter IO_UI_INFO

 

You can use this parameter in order to retrieve information about the current UI status (for example, the current sort

order, or the position of certain rows). Please refer to the FPM Developer's Guide for more detailed info).

 

  • Method
    GET_DATA, parameter IO_EXTENDED_CTRL

 

You can use this parameter for extended features like controlling the mass edit mode or setting the focus (again,

please refer to the FPM Developer's Guide for more detailed info).

 

  • Method
    GET_DATA, parameter EO_ITAB_CHANGE_LOG

 

This is the so called data change log. You can use it for a detailed data exchange. The old List UIBB had a

very simple method for exchanging data; you could only exchange the whole data. This parameter provides

a little more flexibility, in that you can exchange single rows of data. When this data changelog is used the

List UIBB ATS will automatically behave in a way that the SAP UI guideline recommends: This is relevant

when a sorting rule or a filter rule is active (that means when the user chose to sort or filter the data).

In such a case when a row (or more than row) is inserted, the current active sort and filter rules shall not be

applied to it.

That means if a filter rule is active that would cause the new row to be hidden it will appear on the UI anyway.

Also the current sort rule will not influence the position where it appears. The position where it appears is

determined if currently a row is selected. If so, the new row will appear beneath that selected row.

If there is no row selected it will appear at the bottom. Only when the user sorts or filters the dataagain the

sort and filter rule shall be applied to those new rows.

There are mainly two different types data change logs: The key change log (it means rows are identified by

their unique key) and the stable line change log (it means rows are identified by their position). If possible it

is recommended to use the key data change log. All the details  regarding this, is documented in the

FPM Developer's Guide. Please refer to the chapter about the List UIBB ATS, there see data exchange

(the data change log is described in detail in the appendix).

 

References:

 

  • Note
    1619534: How to Adapt, Customize and Enhance FPM Applications.
  • FPM Developer's Guide (available on SCN; go to the Floorplan Manager page and choose the link
    Get started with Floorplan Manager)

Demystifying FPM for Travel & Expense (FITV_FPM)

$
0
0
          View Sundeep Sethi's profile on LinkedIn   

 

This blog is to share my experience and learning's on migrating to WD ABAP based Travel and Expense. We had quite a lot of custom developments done in WD Java version of Travel and Expense and the challenge was to incorporate the changes in the migrated version. I assume most of the ESS projects have the strategy to maintain proper documentation of the custom changes made in WD Java which serve as the guide on custom changes to be made during upgrade or migration.

 

You can choose one of the following ways of applying changes to a FPM based application depending on complexity of the requirement

- Personalization: Can be done by end users. Used for simple changes like controlling visibility, label texts etc. The changes are applicable only for the user doing the personalization

- Customization:  Can be done by administrator. The changes made are applicable for all the users.

- Configuration:    Using the Application Configuration and Component Configuration we can modify the UI Building Blocks of the floor plan. The FLUID tool can be used to assemble the FPM application. However this tool is not applicable for Floorplan Manager of new Travel and Expense application.

- Enhancement:   If we need to introduce custom code and layout changes it can be done through Enhancements.

 

Now coming to the learning's on implementing some custom changes to FPM for T&E:

 

  1. First things first, all the UI content (Web Dynpro, Dictionary Objects, Programs etc.) related to Travel management can be found in the package PTRM_WEB_UI. The Travel Management Components start with FIT*. The POWL objects related to Travel management are in the package PTRM_WEB_POWL.
  2. The FPM component for Travel Management is FITV_FPM. It is important to note that the floorplan framework for Travel Management is not based on the standard floorplans that we are aware of. Even though the applications (Expenses, Requests etc.) have a Guided Activity (Roadmap UI) structure they are not based on FPM_GAF_COMPONENT. Interestingly Travel Management has its own FPM framework defined in the component FITV_FPM.
  3. When the application configuration is launched in a browser window for any of the Travel Management applications (e.g. FITE_EXPENSES), the Component Configuration (e.g. FITV_FPM_EXPENSES) launched do not have the standard structure of GAF or OIF floorplans that we are aware of.

 

                    

 

   4.  One common requirement which many clients can have is to disable the navigation using the Roadmap UI steps. In the standard component it is possible to directly jump to Step 3 from Step 1 by clicking the roadmap step. Clients may require that the user should go to each step before finally confirming and saving.

 

                   

 

Option 1: Through Configuration i.e. by creating a copy of Application and Component Configuration and changing the property “Activated ” of the UI element Roadmap. Doing this greys out the road map but does not indicate on which Road Map Step the user might be on

 

Figure showing how to change Activated property of Roadmap UI for application FITE_EXPENSES

                 

 

Figure showing the end result after doing the above change, even though the user is in step Enter Receipts it is not highlighted

               

 

Option2: Though Enhancement- The Roadmap UI is part of the view  "LAYOUT_VIEW" of the component "FITV_FPM". In order to disable the navigation through roadmap steps the "onSelect" property of the Roadmap UI element on the view should be reset.

This can be done in the Post Exit method of the "WDDOMODIFYVIEW" method dynamically resetting the value of "onSelect" property of the UI element.

 

DATA: lo_ui_elem  TYPE REF TO CL_WD_ROAD_MAP.

*ROADMAP is the id of the Roadmap UI element in the LAYOUT_VIEW

lo_ui_elem ?= view->get_element( 'ROADMAP' ).

CALL METHOD LO_UI_ELEM->SET_ON_SELECT

  EXPORTING

    VALUE  = ''.

 

Figure showing the end result after doing the above code change, when the user is in step Enter Receipts, it is highlighted.

              

 

  5.  Understanding FPM for Travel Management: It took me some time to realize that the FPM for Travel Management is different from the standard FPM (e.g. GAF, OIF etc.). Travel management applications use their own FPM framework. There are three FPM components in the package PTRM_WEB_UI which contain the logic to build the floorplan. The component FITV_FPM is the main FPM component here. The Web Dynpro applications are contained in the component FITV_FPM_START.

 

              

 

In standard FPM (GAF, OIF etc.) we have the interface IF_FPM_UI_BUILDING_BLOCK which contains methods for the FPM navigation loop. In Travel management applications FITV_FPM_VC is the interface of Visual Component for floorplan manager. This interface is implemented by the components which contains the visual components (e.g. FITE_VC_GENERAL_DATA).

When working with FPM it is important to understand the concept of Eventing. For each action raised on the screen there is a corresponding event id associated and the behavior of the application depends on the way that event is handled.

Just like the interface IF_FPM_UI_BUILDING_BLOCK contains the method PROCESS_EVENTS the interface FITV_FPM_VC contains a corresponding method ON_NAVIGATE.

 

I will try to explain a scenario which would be helpful while working with FPM in Travel management applications.

Scenario: Imagine that you have to put a custom validation in place when the button Enter Receipts is clicked on the General Data view of the Create Expense Report application.

 

         

 

Step 1- Identify the web dynpro component to which the view belongs by right clicking on any field on the screen and choosing "More Field Help" and switching to the technical help of the field. You will find the WD Component as shown in this case to be FITE_VC_GENERAL_DATA.

 

         

 

Step 2- Go to the Component Controller of the web dynpro component and you will find the ON_NAVIGATE method. This method comes as a result of implementing the interface FITV_FPM_VC by this component.

 

Step 3- You can find the corresponding event id raised by any button on the screen by placing a break point in the ON_NAVIGATE method and checking the value of importing parameter IV_TYPE of this method.

 

Step 4- Once you have the event id you can put custom logic in the post-exit of this method by checking the parameter IV_TYPE.

e.g. if you have to put custom validation on click of "Enter Receipts" button following code will help

          IF IV_TYPE EQ WD_THIS->FPM_API->GC_NAVIGATE_FORWARD.

               ***put your custom validation here****

          ENDIF.

 

Similarly you can apply custom logic for any button on the screen by finding their component and the event id raised.

 

I hope this blog helps beginners working on Travel management applications in WD ABAP.

I will continue to update this blog with more learning's as and when I acquire them .

New Book on Floorplan Manager

$
0
0

If you're an ABAP developer looking for a comprehensive resource to help you learn how to develop web applications using FPM technology,  then perhaps you'll indulge me as I offer a shameless plug for my new book: Floorplan Manager: The Comprehensive Guide.

Cover.jpg

Who Should Read this Book?

This book is geared towards seasoned ABAP developers who have at least some experience working with Web Dynpro ABAP (WDA) technology and are looking to transition their skills into the world of FPM development. Aside from the core WDA requirement, there is a general assumption that readers have a basic understanding of object-oriented programming (OOP) concepts. Other than that, we start from scratch with the basics of the FPM framework and work our way up from there.

 

Tour of the Book

Organizationally, this book is broken up into three parts as outlined below. The basic idea here is to break the content up such that novice developers can start from the beginning, more experienced FPM developers can pick up in Part 2, and so forth. We also think this approach lends itself well to coming back and using this book as a reference once you get on your feet.

 

Part 1: Getting Started

In this first part of the book, we'll introduce the FPM framework and its core concepts. This foundation sets the stage for more advanced concepts    introduced later on in the book.

 

  • Chapter 1, Introduction   
    • In this chapter, we introduce the FPM framework and identify some of the features that set it apart from other web development frameworks you      might have come into contact with outside of the SAP landscape (e.g. Jakarta Struts, Tiles, and so forth).
  • Chapter2, Tutorial: Creating an FPM Application
    • Since the FPM is all about developing UIs, many of its core concepts are best explained by example. With that in mind, this chapter walks you through the development of a working FPM application so that you can see how the various framework elements come together in a real and tangible way. At this stage in the book, the goal is to simply see the big picture; we'll fill in the details in the chapters to follow.
  • Chapter 3, Floorplan Overview
    • In this chapter, we'll take an in-depth look at the various floorplan types provided by the FPM framework. Here, we'll observe the various floorplan page types, custom features, and so forth.
  • Chapter 4, Working with the FPM Development Tools
    • This chapter concludes our introduction by showing you how to work with the editor tools used to develop FPM applications. Here, we'll highlight differences between tool functionality in various SAP NetWeaver releases.

 

Part 2: Developing Application Content

In part two of the book, we'll dig deeper into FPM application development concepts by looking at different ways to develop application content.

 

  • Chapter 5, Freestyle UIBBs and the FPM Event Loop
    • This chapter introduces the UIBB concept and shows you how to create freestyle UIBBs using custom WDA components. During the course of this introduction, we'll also introduce the FPM event loop which provides the necessary hooks for a given UIBB to be able to communicate with other UIBBs.
  • Chapter 6, Generic and Reuse UIBBs
    • Having looked at the makeup of UIBBs in the previous chapter, this chapter picks up with the concept of Generic UIBBs (GUIBBs) and Reuse UIBBs (RUIBBs). Here, we'll discover that SAP has provided some highly configurable UI components which can really speed up the UI development process.
  • Chapter 7, Working with the Wire Model
    • In this chapter, we put the finishing touches on our UIBB discussion by showing you how to supply UIBB components with data using the wire model.

 

Part 3: Putting it all Together

In the final part of the book, we'll look at FPM application development at the macro level, focusing on framework elements which influence behaviors at    the application level. Once these concepts are generally understood, we close by showing you how to enhance pre-existing FPM applications.

 

  • Chapter 8, Influencing Application Behavior
    • In this chapter, we turn our attention towards those elements of the FPM framework which affect the overall application behavior. Specifically, we look at the notion of application controllers. We also look at a handful of APIs used to apply changes to floorplan layouts, etc.
  • Chapter 9, Interactive Elements of the FPM
    • This chapter explores some of the various elements of the FPM framework which make FPM applications more interactive. Here we look at toolbars, dialog boxes, messaging, quick helps, and so forth.
  • Chapter 10, Enhancement Concepts
    • In this final chapter, we look at some of the various options we have for enhancing pre-delivered FPM applications (such as the ones delivered by SAP). Here, we'll learn how to enhance both the UI and the backend application logic.

Where Can I Find Out More About the Book?

If you are interested in learning more about the book and what it has to offer, you can check out the book's companion site at http://www.bowdark.com/books.html. The book is available in print format and as an eBook. The eBook version is based on Amazon Kindle technology, but you don't have to have a Kindle device to read it. Amazon provides a number of apps which allow you to read Kindle books on iPads, Android tablets, PCs, and so on. You can download the applications for free from your device's app store or here. If you run into problems or have any further questions, please feel free to contact me directly. Enjoy.

An Opinion Blog: Floorplan Manager - A Compromised UI Solution from SAP?

$
0
0

 

I’ve been reviewing a lot of code lately; much of this based on changes to Floorplan Manager (FPM) applications or development of new Floorplan Manager apps. And do you know what I have not come across yet? I have not come across a Floorplan Manager app that I think is a good clean, simple design. Don’t get me wrong. Some of what I see is very good based on what is available, but when you think about software concepts like separation of concerns and variations of UI patterns like Model-View-Controller (MVC) - there seems to be one or two things that always stick out as limitations. It’s like your elegant design having a party and this small piece of bad design shows up uninvited...Awkward!


So there’s a lot of good in FPM, so let me highlight my theory about what was architected to be great:

  • The ability to get a consistent style of interface, especially with Global User Interface Building Blocks (GUIBB’s).
  • GUIBB’s providing the ability to create UI’s with small amount of code in a feeder class (which is mostly very similar each time); and some configuration.
  • The whole FLUID editor (and the improved workbench in the latest releases)
  • Reuse of UIBBs within a UI in different applications
  • Plus lots more


The biggest feature though is the ability to provide configuration based enhancements/adaptions or personalisation capabilities for SAP developed content without modification and in many cases without even coding. And this is what I feel is the main point of FPM. To benefit customers, and not necessarily make life as easy as possible for developers (though it doesn't go out of it's way to not do this either).

 


Note - At my current customer, we saw the benefits and committed to FPM rather than straight Web Dynpro because we know it’s the future of Web Dynpro development (note I didn’t say future of UI development). After spending more time with it, and realising the above, we're less certain this was the right approach for custom developments.


So where it becomes tainted is when you need to develop one of these from scratch. In essence, my concern is for all of SAP’s developers who are developing non-Fiori/BO/Mobile business suite applications with FPM and customers wanting to develop their own apps.


My issues are:

  • Poor examples of enterprise design being trained/highlighted.

  • Lack of consistency by SAP themselves in using it.

  • Reliance on singletons, highly structured wires, or events containing data that don’t provide any real controller to your application.

  • Lack of realisation within many consulting companies that FPM is not just Web Dynpro and that training is required.

  • The Fear Uncertainty Doubt (FUD) that goes with UI development and FPM causing simple UI’s to become very expensive.


Let me explain further below but first may I also say one thing that is really great is the FPM Developers Guidelines/Cookbook. It truly is a cookbook in terms of size. e.g. Imagine you have a large recipe book and you go and try eat all the recipes in one go - Futile right? I think I’ve gone back to the FPM Cookbook hundreds of times to get more recipes out of it. It is a great reference, but be warned, it will overwhelm most people if they try to learn FPM from the developer guidelines (which I tried to do initially).


Anyway, let me explain the issues and being a helpful consultant I’ll provide a recommendation to SAP/yourselves to get around this issue.

 

Please note: This all assumes you don’t want to move to HTML5/Gateway development for business applications just yet

 

Issue #1: Poor examples of enterprise design being trained/highlighted.

 

A common bugbear I have with many training courses is when training goes as far as showing you how to do simple examples, but provides no information to you to do something in an enterprise way. Imagine learning all the HTML/JavaScript/CSS language and then being given a job at Google to build their next gmail web app. Realistically, there is a lot of work still required to get that job at Google, but at the very least if you did get that job somehow, there are some good enterprise like patterns out there to learn from and lots of example that put you in a good position to at least not get fired on the first day.


With FPM, the training appears to cover the basics from what I can tell but doesn’t get into design patterns per se. I didn’t get any response to my question specifically asking about this so can't be certain:

http://scn.sap.com/people/peter.walters/blog/2013/08/10/new-features-for-floor-plan-manager-for-web-dynpro-abap

 

The cookbook covers off aspects but no holistic view of how it should all hang together. So many options but “WHAT SHOULD I DO!?”!

Many examples on SCN look at single UIBB’s, or a screen with multiple UIBB’s talking to each other without application context. e.g. Very few examples of real applications.

Now I just noticed this book which has one section of the book which looks hopeful - Definitely something I’ll check out at TechEd next month:

http://scn.sap.com/community/web-dynpro-abap/floorplan-manager/blog/2013/08/22/new-book-on-floorplan-manager

 

Issue #1 Solution: TEAM FPM are doing a good job of trying to resolve this; and I think it’s the “recommended” end to end examples that are probably missing to really solve this issue. Ideally the end to end design should show a low-fi mockup of what is required and the thinking required to design the solution. Not an easy blog to write but would be very valuable to the SAP community. Note - There are a number of frameworks in place each requiring different thinking, but let's just go for the simple scenarios first.

Another option is to buy that book and see if there are any answers there. If you've read it, would love to get your feedback, otherwise I’ll get back to you on that one.

 

Anyway, for now, checkout TEAM FPM blogs, and also look at the following wiki page (slightly dated now days but still has good info):

http://wiki.sdn.sap.com/wiki/display/WDABAP/eLearning+Tutorials+-+Floorplan+Manager+for+Web+Dynpro+ABAP

 

Note - Part of the issue is also to reinforce the underlying UX patterns that are required within the GAF/OIF/OVP’s since you’d be very surprised what some developers think is normal within a GAF going from Initial screen all the way through to Confirmation screen as an example. At the end of this blog you’ll see what I’m going to do in the end for simple apps which will probably become an anti-pattern but at least it will be easy to create and maintain the FPM app IMO.

 

Issue #2 Lack of consistency by SAP themselves in using it.

Have you ever worked on HR FPM apps? What about GRC apps? What about the EPM Model examples considered to be a good example of design. HR uses Singletons most the time (arghh!); I believe GRC uses a monster framework which makes FPM development very easy but makes understanding it all a nightmare. EPM is almost nice with it’s use of shared data but lack of application controller was my problem I saw with many examples there.

 

For reference, here's where Sandra Thimme referenced the EPM models within the Netweaver stack as a good starting point for enterprise examples:

http://scn.sap.com/community/netweaver-business-client/blog/2013/02/13/floorplan-manager-fpm-and-nwbc

Plus link to EPM Model information she references:

http://www.sdn.sap.com/irj/scn/go/portal/prtroot/docs/library/uuid/d0a7f673-59da-2f10-6e8b-bc7fe5dd4d0f?QuickLink=index&overridelayout=true&58600533829162

 

Issue #2 Solution: Partly same as issue #1; though we do need to grasp all the different frameworks out there and preferably get them under control. GRC is becoming another HR or CRM with how much unique behaviour is being built into these frameworks.

 

Issue #3 Reliance on singletons, highly structured wires, or events containing data that don’t provide any real controller to your application.

All I want in a simple application pattern is a controller, a model and set of views. The views should be able to map to the required model/data via the controller. The view can fire events that reach the controller, but the controller effectively controls the overall behaviour beyond a view.

 

Now use of Singletons is reasonable within the controller (using the app controller within FPM), but do I then create Singletons for every View? Do I reuse singletons across different views even though they may not relate? How do I know what visibility the Singleton's have. In essence, singletons are not the answer here unless we’re talking about one-off UI’s that are not reused. Yuck…


Wires seem to do the trick, but locks you into this list<->object style of interaction with specific coding also required. It’s also very behind the scenes to the application and a little out of control IMO which personally I don’t really like. Good thing about wires is the visibility given though directly in the FLUID editor. Note of warning - I’m very green when it comes to the usage of wires so probably have a lot to learn and maybe the above can all be solved easily.


Shared data - Well - This is probably my recommendation for larger apps and something worth exploring further as a good standard - though still a little hidden in terms of context unless you go searching the code.

 

Issue #3 Solution: Now this one requires development effort to the whole FPM framework. Extending the Application concept to similar to the context mapping in Web Dynpro would be fantastic so that visibility is easy. I'm guessing we're not going to see a change here and have to live with one of the approaches above with hopefully at least some improvement in visibility within FLUID. Awkward!

 

Issue #4 Lack of realisation within many consulting companies that FPM is not just Web Dynpro and that training is required.

So as the System Integrator, you win a brand new greenfield implementation or upgrade project. Fantastic. Maybe it’s just ERP - Okay - We have ERP trained consultants - all good. Now unless you have a very strong technical director in your company - will they really know that things have ever so slightly(!) changed since Web Dynpro was introduced; and even if they do realise, do they have the power (& budget) to ensure that developers working within the UI space need training? My guess is rarely this is the case (at least in Australia where SAP training seems to cost more than in some other countries and developers typically need to know everything and cannot get all the training they need).

e.g. I remember early on my current project, people were looking at modifying the solution quite often not realising that configuration or enhancements in FPM were possible. Luckily we had a process to require approval to be given for modifications and implicit enhancements the current development lead and I had gone to the enhancing FPM apps session at TechEd last year to understand what was possible.

 

Issue #4 Solution: This is a common issue for SAP consultants across many areas, and realistically, it will come down (again) to the solution to the first issue since budgets for training are difficult to come by. Having one person officially trained, then doing internal training can be quite cost effective. At the very least, you can afford to buy the book I mentioned above!

The other point is for customers to check the credentials of customers, and ensure appropriately trained consultants are used. e.g. Asking for certification, while I personally don’t feel is that important, is one way of ensuring that a level of recent training has been undertaken. It also means that customers need to have the ability to review resumes and potentially interview their key developers.

 

Issue #5 The Fear Uncertainty Doubt (FUD) that goes with UI development and FPM causing simple UI’s to become very expensive.

There’s a theme going on with these issues. Lack of training and enterprise design examples are causing this. Simple Applications should take only a couple of days to build including documentation (but excluding stakeholder UI design/requirement sessions, reviews and approvals) for a experienced FPM developer who has a few Enterprise patterns up their sleeve already.

 

To bring home my point, get a developer to quote doing a simple ABAP report; then get them to quote on the same report in FPM. They should take around the same amount of time if they use the right GUIBB's, and alternatively format the ABAP report nicely.

 

Issue #5 Solution: See above!  In addition, to get things moving, see the end of this blog for my first step to resolve at least this aspect for simple applications.

 

Off-topic issue: One last issue slightly unrelated to FPM:

SAP: Please add the ability to save default variants to the search UIBB - It’s such a glaring omission from the UIBB and I get people incorrectly implementing POWL’s for reporting purposes just to provide this functionality!

 

What’s my next step for all of this?

Well, I’m obviously going to be asking a lot of questions and requesting a lot favours at TechEd next month in Vegas (Mentioned a few times now - Can you tell I’m excited?), but also, I’m challenging myself now to post within the next week or so, the first end to end design approach and pattern that is reasonably easy to build and maintain with limited bad code (FYI - The awkward part of my design includes statics). The development lead at my customer has implemented this pattern to help him (and myself) better learn FPM and it’s quite effective and reusable for the very simple requirements we had. I’ll post it as a document in order to get improvements made over time since I know there will be better ways to doing this.

 

What’s your next step for all of this?

If you're SAP Product management for FPM - Please control the other developers outside your space in SAP by listening to their concerns and providing guidelines to them on how to do this consistently in order to get maximum benefits. No more rogue framewoks please. And how about publishing these guidelines on SCN so everyone can benefit?

 

If you're a developer - push for training, buy the book (letting me know if it's any good), keep reading SCN, record the FPM cookbook and play it over and over while you sleep. And let SAP know what needs improving and any ideas on idea place to improve the tools.

 

If you're a customer - Ask your SI what they are doing to get on top of the new tools (not just FPM)?  Review CV's, especially when doing custom development. Build your own list of approved UI patterns based on the SAP patterns, and get user experience owned internally.

 

If you're an SI - Train your people on the skills they need to do their job before they need it, or at least just in time - noting that they will need play time to come up with enterprise designs. At the very least, have a good development architect who you invest in who can train/mentor the team when required. Preferably make that person a director/senior manager/partner, and give them budget to train people on projects properly!

 

And for everyone - provide your feedback on your experiences below, whether you disagree on the above, what you love, what you hate, or what you plan to do in Vegas at TechEd outside of the conference (I'm always up for new ideas on what to do before TechEd too)! Have fun all and thanks for reading.

 


** TEAM FPM ** - Work Protection

$
0
0

In this blog I want to give an overview about how FPM supports work protection.

The basic requirement for work protection is very simple: Whenever the application contains unsaved data ('is dirty') and the user is about to leave the application present him a data-loss popup.

So although this seems to be a rather easy requirement, there is some complexity involved. This is due to the fact that 3 parties have to interact: The shell (portal or NWBC), FPM and the business logic.

Basically there are 2 reasons why an application might be dirty:

  1. The user entered some data on the screen but did not trigger a roundtrip. This data is then only available on the client but not in the backend.
  2. The user is leaving the application after having maintained a lot of data, but did not save it. In this case the backend knows all the data, because there have been several round-trips before. Nevertheless if the application is left then the data is lost as it is not getting persisted.

Now in the FPM world there is a complete separation between the frontend-side rendering (which is done using HTML and javascript) and the backend logic (implemented in ABAP). As a consequence the backend logic isn't capable of detecting the client-side dirty state and can only deal with the 2nd point. Therefore we have 2 different work protect mechanisms in FPM: the client-side and the backend work protect mode.

Client-Side Work Protect Mode

The client side work protect mode is a feature of the shell. This means it only works when the application is running in the SAP Portal or in Netweaver Business Client (NWBC). It's quite simple: With any user interaction the dirty state is set to true and stays at this value until the next roundtrip is started. Then the control is passed to the backend and the dirty state is cleared again.

The problem here is, that there is no generic way to decide whether or not a user considers his interaction to be worth to be protected. As a consequence this type of work protection might result in unnecessary data-loss popups (one example: The user changes an entry in a drop-down list box - now it depends completely on the scenario whether this change should be work-protected or not).

In FPM the client-side work protect mode is active by default. Note 1801019 explains how to switch it off.

 

Backend Work Protect Mode

On the backend side the business logic has to decide whether or not the application is dirty. Normally the application's state is set to dirty whenever the first changed data is flushed to the backend. And it is getting cleared only after the user is pressing the "Save" button (or any other interaction triggering a save).

To achieve this FPM is offering the interfaces IF_FPM_WORK_PROTECTION. There is a Web Dynpro Interface as well as an ABAP OO interface. The Web Dynpro Interface is meant to be implemented by freestyle UIBBs, Transaction  Handlers or Application-specific Configuration Controller (AppCCs). The ABAP OO interface should be implemented by all relevant feeder classes.

The main method of these interfaces is called IS_DIRTY. Now during the FPM event loop on every involved component implementing IF_FPM_WORK_PROTECTION this method is called. And if at least one of them is returning true, the application's state is set to dirty. This results in a data-loss popup when the user tries to leave the application.

Now there is one important thing: This dirty state get's automatically cleared with the next roundtrip. So if during the next roundtrip all involved IF_FPM_WORK_PROTECTION entities are returning IS_DIRTY to be false, then there will be no data-loss popup. This implies that the involved components have to keep track of their dirty state by themselves. If they received changed data in a first roundtrip they have to return IS_DIRTY = X as long as the data isn't persisted.

 

Summary

If you want your application to support work protection you have to

  • do nothing for client-side work protect mode
  • for backend work protection: implement IF_FPM_WORK_PROTECTION in those of your application's components or feeder classes, which are responsible for the changed data

** TEAM FPM ** - Using FPM Applications on an iPad

$
0
0

WebDynpro and FPM are designed for the creation of desktop applications. Nevertheless it was always technically possible to run FPM based applications on a tablet or even on a smartphone. But as there are a lot of limitations this wasn't supported by SAP. This has changed now. With note 1853087 SAP offers "conditional" support for running WebDynpro/FPM in Safari on iPad.

In this blog I want to explain a new feature of FPM which might help you in running existing applications on a mobile device. It is available with Netweaver 7.03/7.31 SP9 (+ note 1893651) and with Netweaver 7.40 SP4.
Besides the usage of "touch" instead of keyboard and mouse, the main difference between a mobile device and a desktop is the much smaller screen space. Therefore normally you want to have simpler screens on the device - there should be only the fields available which are really needed, it might be better to split the content of one crowded screen into several screens which much less content, ...
This is all possible, because in FPM the UI is mainly defined by configuration. Such adjustments to the UI can be done easily via configuration. In the document How to Create, Enhance, and Adapt Floorplan Manager Applications on SAP NetWeaver 7.31 we give an introduction to the multiple methods available for adaptation of applications.
But with all these options one issue remains:
If you adapt your application to the needs of an iPad user the desktop user has to live with the reduced functional scope configured for the tablet as well. Or you create a copy of your application and adapt the copy to the iPad's needs. Then you have to maintain 2 applications and the user has to launch separate applications on the iPad and on his desktop, ...
Luckily there is a solution for this: Using Context-Based Adaptations (CBA) combined with device detection. This means that you only have to maintain a separate delta configuration for the tablet where only the differences are stored compared to the desktop configuration. FPM automatically detects the device type the application is running on and automatically applies the delta or not. This way you have to maintain only one application. The user always uses the same application but on the mobile device he sees the leaner UI.
As this technique is modification-free there is no problem to adapt SAP delivered applications as well.

Step-by-Step Description

In the rest of this blog I will show you with a small example how this works. We will use an existing SAP delivered application and simplify it, so that it can be used on a mobile device. The application we are using is FPM_DEMO_PLAYER. This is a quite stupid application as it only shows 2 lists, one with famous football players and one with famous tennis players. On selecting an entry in the list a form with details of the selected player is displayed.
FPM_DEMO_PLAYER.png

0. Creating an Adaptation Schema

This preparatory step is only necessary if you are on Netweaver 7.03/7.31 SP9 - else you can skip it and use the SAP delivered scheme FPM_DEVICE.
Context Based Adaptations need an adaptation scheme, which defines based on which dimensions (characteristics) the application shall be adapted. For our purpose we only need one dimension - the device type (Desktop, Tablet or Phone).
The adaptation scheme is defined via view cluster maintenance:
  1. Call Transaction SM34
  2. Enter FPM_VC_ADAPT_SCHEMA as View Cluster and press 'Maintain'
  3. Add a new Schemata entry (name is arbitrary e.g. ZDEVICE)
  4. Mark the new entry and select in and then select Dimensions in the left-Hand tree
  5. Add 1 Dimension (Name DEVICE, Index 1 and Data element FPM_DEVICE_TYPE)
  6. Don't forget to save everything

1. Enable CBA

The first thing to do is to convert the original desktop application in to an adaptable one, where we can create separate flavors for the different device types.
  1. Call up the FPM Workbench via Transaction FPM_WB. When launched from SAPGui the FPM Workbench will open up in a stand-alone browser  window.
  2. Click on the Link Enable FPM Applications for Context-Based Adaptations in the section Context Based Adaptations. FPM_WB.png
  3. This will bring up the CBA Enabler. On the first step you have to enter the application configuration name of the application you want to convert (FPM_DEMO_PLAYER), the adaptation schema you want to use (use the one created in Step 0 or if skipped use FPM_DEVICE) and 2 names for 2 to be created objects (the adapted application and the adapted application configuration) . These names are arbitrary, however I recommend to use the same for both objects e.g. ZDEMO_PLAYER. Then press Next.CBA Enabler Step 1.png
  4. On the 2nd step of the CBA Enabler you have the option to assign a package or a transport request. You can simply press Save without changing any data here. Now the application is prepared for being adapted and you see a very simple screen with 2 links. CBA Enabler Step 3.png

Before adapting our application let me explain what has happened after pressing Save:

We didn't really convert the existing application FPM_DEMO_PLAYER. Instead we wrapped the existing application into a new one (ZDEMO_PLAYER). This new one embeds the original functionality (this is no copy it's still the original application) and adds the necessary adaptation capabilities. So if you would start now the new application (via the link Execute Application) it would still look the same as before.

Now let's start the Configuration Editor (by pressing the link Launch Configuration Editor) to make the adaptations for the iPad.

 

2. Adapting the UI

After pressing Launch Configuration Editor you will be directly brought to the FPM configuration editor ("FLUID"). In case you closed the CBA enabler you can launch it via SE80. Go to your local objects and select the new FPM application configuration ZDEMO_PLAYER there and then press Start Configurator or F7. The Configurator will start in the browser. Enter in display mode and navigate to the floorplan configuration by pressing the Link FPM_DEMO_PLAYER_OIF.

In the toolbar you see 3 icon buttons allowing to show additional editor views.

icon_buttons.png

Press the left one to open up the adaptation panel. The Configuration Editor should look now more or less like this:

FLUID.png

To create a new adaptation for the iPad press the Add Button in the header of the adaptation panel. You will get now a popup. There you should uncheck the Checkbox Applies to all values, enter TABLET as Device Type and Z as Namespace.adatation popup.png

After pressing OK the system creates an adaptation specific for tablets for you. You can now adjust the configuration using the whole set of functionality the FPM configuration editor offers. Feel free to do any changes you think suitable.

In the end the application might look like this on the tablet:

app on tablet.png

What did I do to get this result:

I removed the tennis player mainview completely, then I created a new mainview for the Detail UIBB and moved the form UIBB there.

I removed the Edit and Check button from the toolbar.

To remove the list  and form title I created additional adaptations for the list configuration FPM_DEMO_PLAYER_LIST_FOOTBALL and the form configuration FPM_DEMO_PLAYER_FORM_FOOTBALL. This works the same way as for the floorplan configuration.

All these changes were done completely within the FPM configuration editor, without the need to modify any SAP delivered object. And you will only see these changes when running the application on a tablet. If you launch it from your desktop PC you will still get the unchanged application.

 

Summary

WebDynpro and FPM weren't designed for use on mobile devices and if you want to have apps with optimal mobile user experience you should not use FPM to create them. Nevertheless for existing applications this approach offers a way to use them  on a mobile device as well. There are several advantages:

  • The desktop application isn't touched at all
  • The adaptation for mobile only consists of the changes to the original application. So bug-fixes or functional enhancements will still be applied to the "mobile application" as well
  • Although you have a rather different UI the application is still the same and the business logic isn't changed at all
  • The effort for such adaptations is low

 

 

 

 

 

 

 

** TEAM FPM ** - A new Chart UIBB

$
0
0
In my last blog I described how a Java Script chart library can beintegrated on basis of a Freestyle UIBB approach by using the new HTML5 Island of Web Dynpro ABAP. This kind of procedure offers unlimited possibilities to ABAP developers who are familiar with JSON and Java Script, or at least have the time (hours and days) to invest into this topic. However, what about developers who have to stay focused on the application logic in the backend system? This often requires a full time investment and an affinity to ABAP - for very good reasons ...
During the "HTML5 Island Hype" times we stumbled over a very elegant and nice chart library, named CVOM (Common Visual Object Model) HTML5 Visualization Library. It belongs to the SAP portfolio and was already under investigation by SAPUI5. Soon there was an agreement on having a new FPM Chart UIBB with the complete infrastructure that FPM application developers like and appreciate, and in the meantime we can offer a quite good result to our customers with SAP Netweaver 740 SP4.
Before I go into further detail, just one basic remark on CVOM. This library is built on top of D3 (Data Driven Documents), it renders so-called vector-based graphics via SVG (Scalable Vector Graphics). As a result there is not loss of quality if a graphic is zoomed or resized. Web Dynpro ABAP has provided a corresponding Chart UI Element that renders CVOM charts. You will need a browser that is able to handle HTML5, which is not a problem at all if you take one of the most recent versions.

A Data Driven Approach

There are two different basic use cases to generate charts:
  1. Data driven approach
  2. Type driven approach
When following the data driven approach the application developer provides first the data on which a chart is going to be generated. At a later point in time (at the latest during runtime) a chart type is selected that fits to the data provided. In contrast, for the type driven approach the application developer decides first for a chart type and then prepares a data set that fits to the selected type.
 
The new FPM Chart UIBB (WD component FPM_CHART_UIBB) can be consumed via the data driven approach. This covers the first basic use case and it fits well into the FPM architecture, in which the Feeder Class (the data supplier) means a leading component.
 
The application developer is never forced to invest into techniques close to the rendering (JSON, Java Script). Instead he/she stays focused on the backend application logic and the corresponding data retrieval from arbitrary data sources (classic DDIC, In-Memory, Cloud, SOA, ODATA etc.), see Figure 1 below.
 
Basically the data driven approach allows for generating several chart types on one data set. For instance a data set that is being visualized via a Bar Chart can be also rendered as an Area or Line Chart. With restriction to one measure the same data set can be rendered as a Pie Chart or Donut Chart, and so forth.
ChartUIBBModelDrivenApproach.png
Figure 1: A data driven approach for the FPM Chart UIBB

The Table Model

Once you start to describe the term data, you will end soon in a discussion on data models. In a first version we offer a simple Table Model that can be addressed by e.g. DDIC table types and that can be efficiently consumed by the SAP Business Suite. We found the table model to be an excellent candidate that should be exposed by the FPM APIs, since it can be easily prepared from most of the DDIC table types. E.g. simply via
    DATA:    lt_table TYPE << DDIC_TABLE_TYPE >>,
           lo_table_descr TYPE REF TO cl_abap_tabledescr.
  lo_table_descr ?= cl_abap_tabledescr=>describe_by_data( lt_table ).
The Table Model is provided by the application developer in the Feeder Class (method GET_DEFINITION). Then on configuration level (dynamic or static) Dimensions and Measures are defined on basis of the given columns, i.e. the the single columns (resp. table fields) can be defined either as dimension or measure.
A Dimension is regarded in this context as a range (e.g. City, Country, Month, Year and Currency Code) whereas a Measure is understood as something that can be quantified via numbers only. A Measure can be always used as a Dimension; but a Dimension cannot be converted always in to a Measure.
CountryYearProductProfitRevenue
China2001Car2566
China2001Truck159100
USA2001Car5812
USA2001Truck14934
Canada2001Car5835
Canada2001Truck38232
Table 1Example for the FPM Table Model. Each column is defined either as Dimension or Measure
The Table Model can be accessed via Feeder Interface IF_FPM_GUIBB_CHART. There are three Table Model interfaces:
  1. IF_FPM_CHART_TABLE_MODEL
  2. IF_FPM_CHART_TABLE_DATA
  3. IF_FPM_CHART_TABLE_SELECTION
The first is being exposed via Model Factory interface IF_FPM_CHART_MODEL_FACTORY, method GET_TABLE_MODEL. The second is being exposed via Model Factory interface IF_FPM_CHART_DATA_FACTORY, method GET_TABLE_MODEL. The application developer can access these interfaces within Feeder methods GET_DEFINITION and GET_DATA.
In contrast, the third interface IF_FPM_CHART_TABLE_SELECTION is being exposed via event parameter FPM_CHART_SELECTION of FPM event FPM_CHART_SELECT, and is typically accessed in the Feeder methods PROCESS_EVENT and GET_DATA.
Via Interface IF_FPM_CHART_TABLE_DATA the application developer sets the current chart data set (method SET_DATA). Method GET_DIMENSIONS and GET_MEASURES may be used to enable (resp. optimize) the selection of data in the Feeder Class.

Configuration Environment

On configuration level, creating a new chart the application developer decides first for the Feeder Class. Then an assignment of Measures and Dimensions to the Chart UIBB Schema (see Figure 2) can be done. In a next step the application developer may choose a chart type (different from the default one) and make further changes with regard to size, title, legend, colors etc.by using the General Settings panel (see Figure 3). The General Settings are grouped into Basic Settings, Plot Area, X-Axis, and Y-Axis. The settings displayed for each are dependent on the chart type.
There are also settings (e.g. axis, legend or chart title) that can be changed later during the runtime in the Feeder Class, see the interface IF_FPM_CHART_SETTINGS in method GET_DATA of interface IF_FPM_GUIBB_CHART.
Besides the graphical rendering also a Chart Toolbar can be configured on basis of actions that are defined in the Feeder Class. This approach is well known in FPM, see e.g. the List and Tree UIBB.
FLUIDChart1.PNG
Figure 2: Chart UIBB Design Time - Adding Measure and Dimensions to the Object Schema
FLUIDChart2.PNG
Figure 3: Chart UIBB Design Time - Changing the chart settings

Personalization Dialog

By definition the data driven approach allows for rendering the data model via different chart types. It is obvious that the end user should also have the possibility to decide for a favorite chart type during the runtime, after the application developer has selected a default chart type during the design time.
The new FPM Chart UIBB provides a personalization dialog on which the end user can make some favorite settings with regard to the chart type, drawing finish, legend visibility etc. (see Figure 4). Before, the personalization dialog has to be enabled on configuration level (see Figure 3).
RuntimeChart1.PNG
Figure 4: Chart UIBB Runtime - Personalization Dialog

Accessibility Mode

There is also a corresponding tabular rendering of the chart data with regard to the SAP product standard Accessibility (see Figure 5). The new FPM Chart UIBB will switch to the accessibility mode, if you provide e.g. the URL parameter sap-accessibility=X.
RuntimeChart2.PNG

Figure 5: Chart UIBB Runtime - Accessibility Mode

Test and Demo Applications

There are a couple of test (resp. demo) applications that are delivered with SAP Netweaver 740 SP4. Please check out the following application configurations:
  • FPM_TEST_CHART_PERS: Chart types, chart events and personlization dialog
  • FPM_TEST_CHART: Different chart examples on basis of a dynamic Feeder Class
  • FPM_TEST_CHART_SADL_SBOOK: Analyze table SBOOK by using the Service Adaptation Definition Language(SADL) on a HANA database
  • WDR_TEST_CHART: Basic features of the Web Dynpro ABAP chart UI element

Additional Concepts

The new FPM Chart UIBB is already productively used by the current SAP Business Suite 7 Innovations 2013. In addition FPM has delivered some additional concepts on top of the new FPM Chart UIBB: You will be amazed what kind of cool stuff is related to this! Maybe a couple of additional blogs will be supported via SCN in the near future.

Popups in Floorplan Manager

$
0
0

Confirmation boxes vs. Dialog boxes

In FPM, there is a concept called "Dialog Boxes" which allows you to embed any FPM component configuration in popups. Usually, this is overkill for simple confirmation boxes as you usually want to display a warning message there. Depending on the user decision "Yes" or "No" there is be some further backend logic to be invoked. This blog post deals with the question how showing these confirmation boxes can be achieved with quite few effort in a clear, transparent way.

 

Standard approach (FPM)

Use the FPM Interfaces for GUIBBs whenever possible. These interfaces are called IF_FPM_*_EXT*. These interfaces each provide a method called NEEDS_CONFIRMATION which allows you to intercept and defer event processing.

GUIBB Interfaces.PNG

For freestyle UIBBs, there is also a method IF_FPM_UI_BUILDING_BLOCK~NEEDS_CONFIRMATION.

You can specify a warning message by using the exporting parameter EO_CONFIRMATION_REQUEST. It allows you to specify title, message and which button texts should be displayed. In case the user confirmed the warning message, the PROCESS_EVENT is called.

Whenever possible, use this standard approach.

 

Individual approach (custom developed)

However, this approach has its drawbacks. One of the drawbacks is that multiple message lines do not look that good as you need to concatenate the texts. Also, mixing success and warning or even error messages (which is not recommended to use in confirmations) is not possible. Last but not least, the width of the popup cannot be changed.

So this chapter is about how you can define your own popup windows in FPM.

 

The first step starts with raising an FPM event in the GUIBB feeder class / freestyle UIBB and attaching a message table like BAPIRET2_TAB and a self-defined callback object. I do not further describe how the callback object could work. Please see this blog post for further details to get an idea how such a callback could work.

There will be another UIBB to handle this event and show the popup with the messages that are defined in the message table attached to the event.

 


DATA lo_event TYPE REF TO cl_fpm_event.
lo_event = cl_fpm_event=>create_by_id( iv_event_id = ‘OPEN_CONFIRMATION_POPUP’ ). 
lo_event->mo_event_data->set_value( iv_key = ‘MESSAGES’iv_value = lt_bapiret2 ).
lo_event->mo_event_data->set_value( iv_key = ‘CALLBACK’ iv_value = lo_callback_activity_complete ).
mo_fpm->raise_event( lo_event ).


Create a webdynpro component with an empty main window and empty view V_POPUP_EMBEDDER which implements IF_FPM_UI_BUILDING_BLOCK. This allows you to embed this webdynpro component into your FPM application. As this component only needs to be visible, when a popup needs to be shown, you can embed an empty window with an empty view V_POPUP_EMBEDDER to your FPM application. It is crucial that the component takes part in every event loop so the empty view should not be in a tab, rather at a position which is always displayed.

Create an event POPUP_WITH_CALLBACK with the IMPORTING parameters to cover both the callback object type and BAPIRET2-table type.

 

Create a webdynpro component with an empty main window and empty view V_POPUP_EMBEDDER which implements IF_FPM_UI_BUILDING_BLOCK. This allows you to embed this webdynpro component into your FPM application. As this component only needs to be visible, when a popup needs to be shown, you can embed an empty window with an empty view V_POPUP_EMBEDDER to your FPM application. It is crucial that the component takes part in every event loop so the empty view should not be in a tab, rather at a position which is always displayed.

Create an event POPUP_WITH_CALLBACK with the IMPORTING parameters to cover both the callback object type and BAPIRET2-table type.

 

Component controller event to raise the popup window.png

The process event method retrieves the attached event parameters and raises the internally used webdynpro event:

 

METHOD process_event.
 DATA lv_title TYPE string.
 DATA lt_message TYPE string_table.
 DATA lr_event TYPE REF TO data.
 FIELD-SYMBOLS <lo_event> TYPE REF TO cl_fpm_event.
 FIELD-SYMBOLS <lv_key> LIKE LINE OF lt_keys.
 FIELD-SYMBOLS <lv_any> TYPE any.
 DATA lr_data TYPE REF TO data.
 DATA lo_object TYPE REF TO object.
 CASE io_event->mv_event_id.
 WHEN ‘OPEN_CONFIRMATION_POPUP’. 
 io_event->mo_event_data->get_value(
 EXPORTING
 iv_key =  ‘MESSAGES’
 IMPORTING
 ev_value = lt_bapiret2 ). 
 io_event->mo_event_data->get_value(
 EXPORTING
 iv_key =  ‘CALLBACK’ 
 IMPORTING
 ev_value = lo_callback ).      wd_this->fire_popup_with_callback_evt(
 io_callback = lo_callback
 it_bapiret2 = lt_bapiret2 
 ).
ENDCASE.

ENDMETHOD.

Create the component controller’s event handler in the empty view.

Popup handler view methods.png

METHOD open_popup_with_callback.”store callback object in view’s attributes
 wd_this->mo_callback = io_callback.

 DATA lo_comp_api TYPE REF TO if_wd_component.
 DATA lo_controller_api TYPE REF TO if_wd_controller.
 DATA ls_config TYPE wdr_popup_to_confirm.
 DATA: lt_text_table TYPE string_table,
 lv_text_table TYPE string,
 lv_title TYPE string.
 
 ls_config-button_cancel-enabled = abap_false.
 
 lo_controller_api = wd_this->wd_get_api( ).
 lo_comp_api = wd_comp_controller->wd_get_api( ).
 lv_title = ‘Sure?’ 
 DATA: l_api_component  TYPE REF TO if_wd_component,
 l_window_manager TYPE REF TO if_wd_window_manager,
 l_api_view       TYPE REF TO if_wd_view_controller.
 l_api_component = wd_comp_controller->wd_get_api( ).
 l_window_manager = l_api_component->get_window_manager( ).
 wd_this->mo_window = l_window_manager->create_window(
 window_name = 'W_POPUP'
 title = iv_title
 button_kind = if_wd_window=>co_buttons_yesno ).
 wd_this->mo_window->open( ).
 l_api_view = wd_this->wd_get_api( ).
 wd_this->mo_window->set_on_close_action(
 view        = l_api_view
 action_name = 'CLOSE_POPUP' ).
 wd_this->mo_window->subscribe_to_button_event(
 button      = if_wd_window=>co_button_yes
 action_name = 'CONFIRM_POPUP'
 action_view = l_api_view ).
 wd_this->mo_window->subscribe_to_button_event(
 button      = if_wd_window=>co_button_no
 action_name = 'CLOSE_POPUP'
 action_view = l_api_view ).

 ENDMETHOD.


Create the actions CLOSE_POPUP and CONFIRM_POPUP in the view. CONFIRM_POPUP should execute the callback object’s callback method, like


 IF wd_this->mo_callback IS NOT INITIAL.
 wd_this->mo_callback->callback( ).
 CLEAR: wd_this->mo_callback.
 ENDIF.

 

Create the window W_POPUP with its own view V_POPUP. Show the content of the message table that came with the FPM event e.g. in a message area.

Sample Popup view in the generic webdynpro component.png

The popup will look like this. The screenshot shows only one warning message, so there is no benefit yet compared to the standard approach provided by the FPM runtime. But it is capable of showing multiple warnings and even different message types.

Popup.png

New book: "100 Tips and Tricks for Web Dynpro ABAP"

$
0
0

Two weeks ago SAP Press published the following book in German:

 

 

"Web Dynpro ABAP - 100 Tipps und Tricks"

 

 

 

9783836222747.jpg

 

 

 

More about the content:

 

Wenn es darum geht, komplexe Benutzeroberflächen mit Web Dynpro ABAP effizient zu gestalten, kann Ihnen kaum einer etwas vormachen. Doch trotz Ihrer Erfahrung fragen Sie sich ab und zu, ob sich manche Aufgaben nicht noch besser lösen lassen? Die 100 Expertentipps in diesem Buch zeigen Ihnen, wie’s geht! Blättern Sie ein wenig und lesen Sie zum Beispiel, wie Sie Swap Root Element richtig einsetzen, neue Layout-Typen verwenden oder die Performance Ihrer Anwendungen optimieren. Darüber hinaus finden Sie Tipps zum Floorplan Manager. Mit diesem Buch haben Sie stets noch ein *** im Ärmel!


Aus dem Inhalt:

• Architektur und Komponenten von Web-Dynpro-Anwendungen

• Web-Dynpro-Context verwenden

• User-Interface-Elemente einbauen

• Mit Tabellen arbeiten

• Im Editor arbeiten

• Fehler beheben

• Web-Dynpro-Anwendungen analysieren

• Anwendungen mit Web Dynpro anpassen, konfigurieren und erweitern

• Administration

• Mit dem Floorplan Manager arbeiten

 

You can order the book and find out more information at

http://www.sap-press.de/3334

I'm looking forward for your Feedback.

 

Best regards

Dominik Ofenloch

** TEAM FPM ** - How to integrate longer texts into your FPM application?

$
0
0

Hello everybody,

 

the possibility how to integrate documentation objects from SE61 into an FPM application via the explanation control is well-known.

 

Within transaction SE61 you create a document object and refer later to it within your OVP floorplan configuration (see below screenshots, click on them to enlarge).

 

Explanation.png

 

SE61.png

 


However  the explanation is only visible if the quick help is being activated via right-mouse click:

 

Quick_Help.PNG


Having a longer text within your FPM application which should be there from quite the beginning of the application runtime, can be achieved by the following way:

 

The idea is to use the text maintained via SE61 within other parts of your FPM application, e.g. within the Form UIBB. It would be a good idea doing this e.g. via the Formatted Text View.

 

Within this UI element of the form configuration you just can edit a normal text, but not a document object from SE61. Furthermore within the configuration layer you are limited to 255 characters due to translation reasons.

 

This is why there is a possibility to programmatically give the information via feeder class which document object from SE61 should be taken – either for the Formatted Text View or Formatted Text Edit.

 

Therefore you need the following coding snippet:

 
DATA docu_utility TYPE REF TO cl_wdr_docu_utility.
 
DATA lv_text_xml  TYPE string.

  docu_utility
= cl_wdr_docu_utility=>get_instance( ).
  lv_text_xml
= docu_utility->get_general_docu_as_fmt_text(
                     

                    object = `FPM_CBA_FR` " your document object from se61
                    langu 
= sy-langu ).

 

This coding converts the document object to a SAP Script Text.

 

GET_DATA.png

 

This text now you just have to assign to the correct field component of CS_DATA within GET_DATA of your feeder class and the documentation should be now displayed properly on the FPM application. For beautification reasons you can also remove the label from the Formatted Text View via the form configuration.

** Team FPM ** - Asynchronous Events

$
0
0

If you have to start a backend process from your FPM application, which takes longer than one second you have two options:

  1. Block the UI and show a waiting cursor as long as the backend needs to fulfill the task
  2. Start the process in a seperate asynchronous task, allowing the user to continue to work with the application

The first option causes a bad user experience, the 2nd a usability issue: When the task is completed, how do you inform the user? You could add a 'refresh' button to your application allowing the user to request the current status of the background task. Or you could simply check the status with every subsequent roundtrip. Or you can trigger recurring roundtrips simply for status checking by using a timed trigger.

Of course the appropriate option depends on the use-case.

Since Netweaver 7.31 SP07 FPM now offers asynchronous events, which offers a better solution for this issue. You can simply trigger an FPM event when the task is done.


To do this you have to do the following steps:

  • Register the FPM event with IF_FPM. It will return a notification ID

data: lv_id type wdr_notification_id.
      lv_id = mo_fpm->register_asynchronous_event( lo_event ).

  • Start your asynchronous task and pass it the notification ID

       call function 'MY_ASYNCHRONOUS_TASK' starting new task mytask
        exporting
          iv_notification_id = lv_id
          ...

  • When the asynchronous task completes trigger the FPM event by calling

  cl_wd_notification_service=>update_event_status(
    exporting
      event_id     =     iv_notification_id
      event_status =     cl_wd_notification_service=>c_status_done ).

 

That's it.

If the functionality is available in your system you can also have a look at the test application FPM_TEST_ASYNCHRONOUS_EVENT which shows this feature in a very simple application.

 

    

** Team FPM ** - Maximize Mode in the OVP floorplan

$
0
0

Maximize Mode in the OVP floorplan

 

Introduction

 

This blog describes the maximize and minimize functionality for UIBBs in the OVP floorplan, a pretty cool feature which is available as full-fledged version as of NW 7.40, SAP_UI SP08. With this functionality the end user is enabled to enlarge the display of a UIBB so that only this UIBB is visualized on the page and all other UIBBs are no longer displayed. The maximized UIBB may display its content in an enlarged manner. The end user can switch back to the standard display. For UIBBs which are based on a fixed height the maximize function may not make sense.

The main purpose of the maximize function is to let the user focus on a single UIBB if the available space on the page is not sufficient for proper visualization.

OVP1 - marked.png

   Figure 1: OVP in standard display mode

 

OVP2 - marked.png

   Figure 2: OVP in maximized mode

 

Please note that maximizing Tabbed and Composite UIBBs itself is not be supported as those 'layouting' UIBBs cannot properly enlarge their content. Of course, it is possible to enlarge UIBBs that are inside of a Tabbed or Composite UIBB.

 

Enabling the maximize/ minimize functionality in the configuration

In order to make use of the maximize mode there are just a few clicks required in the corresponding OVP component configuration. We will explain the required steps in the following by means of a local test application that does not use the maximized mode at all so far, as shown in the following screenshot.

 

Step 1:

Press the button 'Configure Page' in the page toolbar of the OVP.

Hint: If you don't have this button, you can promote yourself to an 'FPM Configuration Expert' by setting the user parameter FPM_CONFIG_EXPERT = X. The, you can find nice technical buttons in any FPM UI. With the first one, you can directly navigate to the floorplan configuration. With the second one, you get all configurable areas (FPM UIBBs) overlaid. By clicking in such an overlay area you can directly navigate to the respective UIBB configuration. With the third button you can navigate to the Application Hierarchy Browser.

Step 1 - marked.png

Step 2:

In the configuration editor, open the panel 'Toolbar Schema' and select the UIBB toolbar to which you want to add the 'Maximize' button. In our case, this is the toolbar of the UIBB 'Map'. Press the button 'Toolbar Element'.

Step 2 - marked.png

 

Step 3:

A dialog box will open. Just click on the icon for the 'Maximize' button.

Step 3 - marked.png

Step 4:

Press the 'Save' button in order to save the configuration. That's it!Step 4 - marked.png

 

Step 5:

Restart the application. You will see a 'Maximize' button in the toolbar of UIBB 'Map'.

Step 5 - marked.png

Step 6:

Now, click on the 'Maximize' button... and you will see a maximized map. Wow, that was easy!

Just note that the 'Maximize' button has now turned automatically into a 'Minimize' button. Moreover, the 'Page Master' toggle button as well as the 'Personalize' button have been disabled in order to avoid inconsistent UI states.

Step 6 - marked.png

 

Step 7:

In the configuration editor, you can now add 'Maximize' buttons to all other UIBBs on the screen. We will not describe it here in detail again.

However, for stacked panels there is an additional special feature in the OVP regarding the maximized mode. In our test application, we have several Chart UIBBs within a stacked panel. These are the UIBBs 'Combination', 'Column', 'Pie', 'Boxplot',... and so on. It would be cool if it was possible to maximize the expanded UIBB of a stacked panel not as single UIBB but together with its stacked panel, keeping the full functionality of the stacked panel. And here is how you can do it...

Open the configuration editor again, go to the UIBB toolbars of all those UIBBs that should be maximized together with their stacked panel, add the 'Maximize' buttons as already described above, but add an additional event parameter FPM_MAXIMIZE_STACK = ‘X’ in the button attributes as shown exemplary for the toolbar of UIBB 'Combination' below. Save the configuration.

Step 7 - marked.png

 

Step 8:

Restart the application again. You will see the new 'Maxmize' buttons that you have configured. Press the 'Maximize' button of the UIBB 'Combination'.

Step 8 - marked.png

 

Step 9:

The UIBB 'Combination' has been maximized together with its stacked panel.

Just note that you can open any other UIBB of the stacked panel, still staying in maximized mode. When minimizing again, the currently opened UIBB of the stacked panel will be kept open.

Step 9 - marked.png


Maximizing UIBBs without panel and UIBBs inside Tabbed or Composite UIBBs

In the case that there is no panel around a UIBB (typically the UIBBs on Initial Pages or Edit Pages of the OVP do not have panels) the 'Maximize' button for such a UIBB cannot be placed into a panel header within the OVP. Therefore, it is also possible to add a 'Maximize' button to the UIBB's internal toolbar. For this, you just have to mark the checkbox 'Maximize Button' in the General Settings of the respective UIBB configuration, as shown for a Visual Business UIBB in the following screenshot.

Maximize Button in UIBB General Settings.png

This functionality is available for the FPM UIBBs List ATS, Tree, Chart, and Visual Business. The 'Maximize' button in the UIBB toolbar will automatically be fully controlled by the UIBB logic. The application feeder class does not have to take care about it at all. By enabling the 'Maximize' button in the UIBB toolbar it is also possible to maximize UIBBs that are positioned inside a 'layout' UIBB, such as the Tabbed or the Composite UIBB.

It should be clear, of course, that it doesn't make sense to have both, a 'Maximize' button in the UIBB panel header (if there is one) and another 'Maximize' button in the internal UIBB toolbar.


Technical Concept

General Principles

Maximizing and minimizing a UIBB is triggered by a corresponding ‘Maximize’ and ‘Minimize’ button in the panel toolbar. A dedicated FPM event is assigned to the respective button. The FPM event for the ‘Maximize’ button has the ID ‘FPM_MAXIMIZE_UIBB’; that for the ‘Minimize’ button has the ID ‘FPM_MINIMIZE_UIBB’.

By default, only the single UIBB for which the ‘Maximize’ button is pressed is maximized. However, if the corresponding FPM event is furnished with the event parameter FPM_MAXIMIZE_STACK = ‘X’, then the entire stacked panel of the UIBB is maximized.

Integration into the FPM event loop

After the maximize event has been successfully processed only the maximized UIBB is visible. The event loop switches logically to the single maximized UIBB. The currently maximized UIBB can be retrieved via interface method IF_FPM->GET_MAXIMIZED_UIBB.

In case a stacked panel is maximized, the currently expanded UIBB of the stacked panel stays expanded and is exposed via interface method IF_FPM->GET_MAXIMIZED_UIBB. However, the event loop switches logically to the set of UIBBs contained in the maximized stacked panel.

In maximized mode, the FPM framework replaces the ‘Maximize’ button automatically with a ‘Minimize’ button, triggering the minimize event which switches back to the original display and the original set of UIBBs participating in the event loop (unless there are manipulations done by an Application Configuration Controller).

 

Behavior of UIBBs in maximized mode

In maximized mode the UIBBs may either display more or enlarged content. This is meaningful in the case of "expandable" UIBBs, such as the List UIBB, Tree UIBB, Chart UIBB, Visual Business UIBB, and so on. But it wouldn't make sense for UIBBs such as the Form UIBB. In maximized mode, the FPM Chart and Visual Business UIBB enlarge their height from the configured height to a 100% display; the FPM List and Tree UIBB switch from the configured height mode to the variable height mode (“Fit to Height of Surrounding Container”).

If freestyle UIBBs shall be maximized they have to take care of appropriate behavior themselves. There will be no interface pattern which allows exposing whether a UIBB can be appropriately maximized or not, i.e. there will be no check in the configuration editor.

Behavior of the OVP in maximized mode

The OVP runtime stores the maximized UIBB by page. As a consequence, navigation from a maximized UIBB to a different page keeps the UIBB maximized when returning to the original page.

If the ‘Maximize’ button belongs to an OVP panel toolbar, the OVP runtime automatically replaces the ‘Maximize’ button with a ‘Minimize’ button and the corresponding minimize event.

If the ‘Maximize’ button belongs to a GUIBB internal toolbar, the respective GUIBB runtime replaces the ‘Maximize’ button with a ‘Minimize’ button and the corresponding minimize event.

The OVP runtime disables the personalization and the page master toggle button in maximized mode in order to prevent an inconsistent UI state.

Viewing all 54 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>