Professional Documents
Culture Documents
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 downcast the connectors 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 UIBBs 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 weve got several wiring possibilities to wire the
UIBBs and the FPM transaction component together.
ADD_MODEL method. In the end, the witch holds captive all the feeder models.
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.
Standard | Posted in Floorplan Manager | Tagged FPM, Wiring | 0 comments
12.28.12
by Uwe Kunath
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, lets 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.
ZIF_FPM_DEMOWIRE_SFLIGHT_SEL).
Both wires have specific operations offered to the UIBBs or OVP Exit which use these
wires.
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.
First of all, we include an OVP-toolbar button to allow the user to trigger the Saveoperation.
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.
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 FLUSHmethod 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.
(ZCL_FPM_DEMO_WIRE_SFLIGHT)
ZFPM_DEMO_OVP_FLIGHT_SEARCH
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 cant 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 arent really a good idea in terms of maintainability and
understandability. Thats 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:
Once the users selects an entry, a form UIBB shows the detail data
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.
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.
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.
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.
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 objects interface.
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.
I didnt 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
Singleton
Events
Wiring
Freestyle UIBB. Since context mapping is not possible for the Generic UIBBs, I do not
further investigate this possibility.
Advantages
Easy to implement
Sharing of a single Instance which offers both data and operations to its
clients is quite easy, there is no need to share only internal tables or
structures which offer no follow-up operations for the UIBBs dealing with
these data structures / instead, UIBBs can get an object, retrieve data and
also write some data back based on what the UIBBs was intended to do
Drawbacks
All UIBBs which rely on the application model class will work only with this
class, hence, show a strong association with that class. This threats the
reusability of that components in scenarios which usually do not deal with
this very application model class
io_tabbed->mo_event->mo_event_data->get_value(
EXPORTING iv_key = 'SEARCH_CRITERIA_FLIGHTS'
IMPORTING er_value = lr_data ).
ASSIGN lr_data->* TO <lt_selopts>.
...
ENDCASE.
Advantages
Easy to implement
Easy to implement also in dynamic scenarios, where UIBBs are registered at
runtime
No extra class for the backend object needed
Drawbacks
only visible UIBB take part in the event loop, invisible UIBBS (e.g. in other
tabs than the currently selected tab) do not receive the data
You cannot address specific UIBBs this way, instead all visible UIBBS take
part in the event loop and will handle this event or ignore it
Advantages
Since the connector classes and the data which they provide are defined at
design time and used both on sender and receiver side, surprises are less
certain than in the event-based approach. However, a sender might still
decide to return different data via its outports which will cause an error at
runtime
This also makes transparent, which data the UIBB you are currently
configuring, really uses
Drawbacks
Conclusion
Every approach has its specific advantages. What we learned in real implementation
projects, is, that there is always a mixture of these approaches depending on the
scenario and the requirements in terms of reusability of UIBBs. If your UIBBs need to be
reusable in various scenarios the approaches to exchange data should be (in order of
relevance): Wiring before Singleton before Events.