** TEAM FPM ** – The FPM Event Phase Model – easy going or already lost? ;-)
also on SAP side it is sometimes the case that development systems are down – so my idea came up to write a short blog post about the FPM phase model to make it easier to understand.
If you are just interested in FAQ’s you will find them on the very bottom of this blog post.
When reading through our FPM developer’s guide, you will also be introduced to the following sequence diagram describing the FPM phase model (which encapsulates the so called FPM event loop). When you click directly on the below screenshot you get a deeper insight into it.
For some of you it might be a kind of complex picture which is not so easy to understand – but when having a deeper look into it and getting an overview of all involved entities and methods, you will be able to build/understand FPM applications much easier.
On the very top in the rectangular shapes you see the involved entities/agents participating within the FPM phase model.
On the bottom right corner you can see a small legend. The green written methods are methods called by the Web Dynpro runtime and blue written methods by the FPM runtime (sometimes this picture is displayed only black/white which makes it even more difficult to understand).
As this phase model is a sequence diagram, it shows how the involved agents interact and communicate. In this scenario it is important to know that a navigation takes place from UIBB1 to UIBB2 – this is of great importance because different activities take place for UIBB1 in comparison to UIBB2. (UIBB = User Interface Building Block)
Coming back to the involved agents – we have:
The user of an FPM application is doing an action on the UI – raises a Web Dynpro Action – which mostly is then transferred to an FPM event – which always ends up with the FPM event loop.
The Web Dynpro (WD) runtime takes care of all Web Dynpro action handler methods (which will be described later).
The involved Floorplan component, e.g. an OVP (FPM_OVP_COMPONENT), can start the FPM event loop with implicit FPM events, like FPM_START or FPM_LEAVE_INITIAL_SCREEN. This component knows also which UIBBs are currently on the screen or have to be loaded within the next roundtrip. It also implements the logic on how the UI should look like after the FPM event loop has been processed. On the other side the FPM event loop can also be triggered by a UIBB when raising FPM events.
Within the central class CL_FPM all FPM events will be processed. There can also be multiple FPM events raised in a certain point in time – they will be processed through the “first-in, first-out” principle. This is the starting point where all UIBBs on the screen will be informed that an FPM event has been raised. All UIBBs reacting on this event will now be involved – all methods of the interface IF_FPM_UI_BUILDING_BLOCK which is implemented by all UIBB components – are getting called in a certain sequence as you can see.
UIBB1 is already displayed on the UI and all methods like Flush or Process_Event are getting called.
UIBB2 is the new UIBB which will be loaded with the next roundtrip. You see that this component will be instantiated by the WD Runtime.
Further interfaces can play a role during the FPM event loop if needed and implemented.
The WD interface IF_FPM_SHARED_DATA only make sense when using freestyle components (no GUIBBs). It makes sense if you would like to have a central Shared Data (SD) instance. As today in most of the cases GUIBBs are used, this interface does not play a major role in an application. If you have many, many components involved which should work on a common data provider, you can point out a WD component implementing this WD interface. FPM is then taking care that only one instance of this component exist and that all entities are working on the same data base.
If your application should support transaction handling, one component should implement the interface IF_FPM_TRANSACTION. If the FPM event FPM_SAVE is raised, all methods of the Transaction Interface are called, like e.g. Check_Before_Save, Save and also After_Rejected_Save.
The interface IF_FPM_WORK_PROTECTION you need in case you would like to provide a protection mechanism that data on the screen cannot be lost so easily. This would make sense in e.g. an HR application when writing extensive employee appraisals. In this case – if e.g. the FPM Close Event is called and the application has set the flag IS_DIRTY. The consequence is that a data loss popup will be provided to the user where he can decide whether he would really like to leave the application and save his data.
Last but not least – the probably most used WD interface – is IF_FPM_*_CONF_EXIT. In case of a GAF you would use interface IF_FPM_GAF_CONF_EXIT. This is the so called application configuration controller (AppCC) where dynamic changes of the UI can be done as well as runtime information of the corresponding floorplan are provided (e.g. which UIBBs are on the screen at the moment, on which GAF step am I, …). Within the interface method OVERRIDE_EVENT you can do such things very easily.
Going through the FPM phase model
Having described all main entities let’s assume the user triggers now the FPM phase model by e.g. pressing the Next Step button on a currently loaded GAF (Guided Activity Floorplan) – where a navigation takes place from one mainstep to the second and where UIBB1 has to be left and UIBB2 has to be loaded. We now follow the path described in the sequence diagram above.
You see that all the Web Dynpro methods are called – of course – for all currently displayed Web Dynpro components – as this is also the case for our GAF Floorplan component. So the methods wdDoBeforeAction and onAction are called for the Floorplan component as well as for the currently displayed component UIBB1. UIBB2 doesn’t play a role at the moment.
To prevent not to get lost in all displayed methods I list up the most important methods in the following table before getting in a more detailed description.
Freestyle Components implement the WD interface IF_FPM_UI_BUILDING_BLOCK. GUIBBs are based on a feeder class, implementing an interface, depending on the GUIBB type (e.g. when using a GUIBB List ATS interface IF_FPM_GUIBB_LIST is used). You will find the below methods accordingly.
In the following paragraphs all methods will be described in the sequence they appear in the FPM Event Phase Model.
wdDoBeforeAction: A standard Web Dynpro method that is called by the Web Dynpro runtime on all visible UIBBs when the user triggers a roundtrip. According to Web Dynpro programming guidelines, generic validations must be handled in this method; for example it is checked that all mandatory fields are filled.
onAction: The registered Web Dynpro action handler is called. You then have the following options:
- If the user interaction does not affect other UIBBs, and there is no need for FPM features such as data-loss dialog boxes, you can handle the action locally in your UIBB. Use standard Web Dynpro programming; for example selection of another radio-button leads to different enabled/disabled settings of other controls on the same view.
- However, for all actions which may affect other UIBBs, raise an FPM event (how and when to raise an FPM event will be described later).
Flush: Now, after the FPM event loop has been started, method Flush is called on all involved UIBBs. A UIBB can flush its modified data e.g. to the Shared Data component so that other interested UIBBs are informed.
Override_Event: Now this event is called on the Application Configuration Controller (AppCC).
Is_Dirty: As mentioned in the sequence diagram as well this method is only called if the current application state is left by closing the application or starting over it.
Needs_Confirmation: This method is now called on all involved UIBBs – within this method a UIBB can influence the processing logic in the way that e.g. a data loss popup can be raised and the user has the possibility to end further processing of the event loop (to confirm or not confirm 😉 ). If this is the case the WD runtime is showing the respective popup (e.g. data loss or whether the deletion of an object should really be done).
At this stage a parallel block is opened within the sequence diagram which is relevant for the case that the user or any other instance is ending the FPM event loop – several lines from the first sequence block of CL_FPM to the second sequence block are indicating this.
Process_Event: This method is now called on all participating UIBBs where they can react on the respective event, e.g. also raising other events.
Then the transaction handler methods are called: Check_Before_Save, Save and After_Commit. Again, at this point in time the application still can interrupt the FPM event loop.
On_Hide: Now the method On_Hide of the participating UIBBs is called. As it can be seen in the sequence diagram only the UIBBs implementing the Resource Manager interface (IF_FPM_RESOURCE_MANAGER) are able to use it. It is possible now to free resources of instantiated but not visible and used UIBBs + UIBBs which won’t be used anymore after the execution of the current FPM event.
Now the FPM navigation takes place logically and everything is ready to build up the next screen/UIBBs.
The Web Dynpro runtime creates now the Shared Data component if available and initializes it.
Afterwards all participating UIBBs are created by WD runtime and initialized. Then CL_FPM is attaching the UIBB for using / accessing the Shared Data component.
After_Rejected_Save: Rarely used method! This method of the IF_FPM_TRANSACTION interface is called if the user or the runtime has rejected the save event.
After_Failed_Event: Rarely used method! If the current FPM Event was flagged as ‘FAILED’, this method is called on every participating UIBB.
Having again a look at the sequence diagram you can see that in case the navigation was skipped, that actions of UIBB2 are in this case actions of UIBB1 because UIBB2 won’t be instanciated at all.
Process_Before_Output: This method is now called on every participating UIBB where data can be fetched/updated before the content is displayed on the UI.
Is_Dirty: Now the application can activate/deactivate work-protect mode of the WD runtime.
The floorplan component is now modifying the view assembly with an updated set of UIBBs and the CL_FPM is closing the FPM event loop.
Afterwards the standard WD methods are called on every participating component (Floorplan component, UIBBs, …).
wdDoAfterAction: This method is called for all visible WD views at the time an action is executed. Here functions can be placed that are carried out equally for all associated event handlers. This avoids any unnecessary multiple programming in the event handlers.
wdDoBeforeNavigation: This method can only be used for the component controller. The method is used for the component assigned to the phase model instance and all embedded components.
WD navigation (not the FPM navigation) can be interrupted at this point if an error occurred during the event handling in the previous step.
wdDoModifyView: Is processed for all visible views of the component – here the application developer can modify the UI tree of a view, e.g. by dynamically adding view elements in Freestyle UIBBs.
wdDoPostProcessing: This method is called in the last process step before rendering. Therefore, it allows you to add application-specific clean-up processes.
Frequently Asked Questions
At the very end of this blog I like to share some FAQ’s on FPM events.
How does the FPM Event Loop behave if several FPM Events have been raised?
All raised FPM Events are stored within CL_FPM like on a pile, and one after another is being processed. If any event fails, the whole FPM Event Loop will be stopped immediately and cleared.
At which point in time is it possible to raise an FPM event?
- Within a WD ABAP UI action handler method.
- During the FPM event loop. That means within methods that are part of the FPM Event Loop and called by FPM, e.g. in methods like FLUSH, PROCESS_EVENT or PROCESS_BEFORE_OUTPUT.
FPM events must not be called outside of those point in time.
What is the correct procedure raising an FPM event?
Take the FPM instance of your FPM application – either via CL_FPM_FACTORY=>GET_INSTANCE( ) – or – when having implemented interface IF_FPM_MULTI_INSTANTIABLE in your UIBB – via method FPM_INITIALIZE.
Afterwards you can call methods RAISE_EVENT and RAISE_EVENT_BY_ID.
Where can I find more information on the FPM Event Loop and about FPM in general?
On the new SAP community pages you can raise questions or get further information on FPM, like e.g. learning material, documentation, other blog posts, videos about new FPM features .
If you would like to get a deeper look and understanding on the FPM event loop and further background, I can recommend you the 2 FPM books available at the moment:
Floorplan Manager für Web Dynpro ABAP (German, written by 2 of my colleagues, Thomas Frambach and Simon Hoeg)
Floorplan Manager: The Comprehensive Guide (English, written by James Wood)
Web Dynpro ABAP – 100 Tipps & Tricks (German, written by my colleague Dominik Ofenloch)
In the meanwhile my development system is again up and running… So I finish now this blog post and hope, that it is a little help for the daily work of other FPM developers. Have fun!
thanks a lot for the information. One issue regarding the FLUSH( ) method occured to us: We've got UIBB1 (FORM) and UIBB2 (Freestyle)
UIBB2 triggers an FPM event, which serves some callback purposes, every 5s
It looks like UIBB1 receives the user input done within those recurring 5s within the FLUSH method only in case the following conditions are met:
-the input field lost the focus in the meantime
-or the user pressed enter in the meantime
If the user does not hit ENTER between the two FLUSH( ) calls, or does not leave the input field, the most current input will not be passed to the FLUSH method of UIBB1.
Is that common behaviour, or might it be unwanted behaviour?
Thanks a lot, Regards,
Edit: This can be reproduced only with user input via input fields, not with user input via textareas - here everything works as expected 🙂
thanks a lot for the information.
i would like raised a message after save fright order in sap TM
its event id is "FPM_SAVE" but this event use in many places.
How can I separate it?