Process Observer (POB) – working with BOR events made easy
When implementing Process Observer you will run occasionally into the situation that there are no existing Business Object Repository (BOR) events that can be used to instrument the activity that you need to monitor.
This has been addressed with the previous blog post Process Observer (POB) Direct Event API for Logging Processes from SAP and Non-SAP Systems. And while the approach shown there has several advantages to using events from the Business Object Repository (BOR), namely simplicity and some performance, there may be situations where using BOR events appears to be better. The main reasons are that you may generally feel more comfortable with BOR events and to avoid race conditions in a mixed-mode situation where you have direct events and BOR events. The first aspect covers aspects like the generic support for BOR events like the BOR event trace (transaction SWEL), the fact that you need to look at only one queue or generally work with only one technology.
The second aspect, race conditions, may be an issue if BOR events and direct events occur in close temporal proximity: The BOR queue and the direct event queue are processed sequentially, so if a direct event and a related BOR event occur in an order the order they are processed in may change and that can lead to events being lost, e.g. if the direct event relates to an object that is the predecessor of the BOR event. If the direct event is not (yet) processed and not available when processing the BOR event, the BOR event cannot be related to the process instance. This may be a rare case and in most scenarios situations like this can be ruled out or may not be relevant. [Update: Now, with note 2030279, we have a report for unified processing of BOR events and direct events available. Events of all types are now processed together, and in the order in which the events occur. Race conditions should be history now. You can find information about this also in the blog post Process Observer: Working with Tasks Made Easy.]
Whatever the reason for using BOR events, one issue with using BOR events is that you need to first create the appropriate BOR content, i.e. a BOR object and the event. Even if you add a new event to an existing object, you need to create a new object and set it as a substitute to the original object. To avoid this overhead while still providing all advantages of BOR events, Process Observer provides a generic BOR event.
The Generic BOR event
The generic BOR event delivered will let you easily raise generic events through the BOR interface. All processing will be as for a BOR event, but there is no need to create any BOR content. This is done by putting the task (or task event, from a technical perspective the task and the event representing the task are the same thing) information into the event container of the BOR event. With the provided example it is very simple to implement new events.
From this point I expect that you have some understanding of BOR events, otherwise have you tech-guy read this.
What does this look like in detail? SAP delivers:
- The BOR object POCGENERIC with the event EVENT_RAISED,
- Method cl_poc_bor_event=>raise_generic_bor_event
- A demo-Report: POCR_SIM_GENERIC_BOR.
What you have to do is raise the BOR event POCGENERIC.EVENT_RAISED. It has these parameters:
- Task_Type: It determines the task type, e.g. “21” for Create
- BO_Type: It determines the business object type, e.g. 114 for Sales Order; the BO_Type combined with the task type make up the task
- Previous_BO: This parameters is set to determine the previous business objects – multiple previous objects are possible; it is structured to hold
- PRE_BO_TYPE: The business object type of the previous business object, e.g. 30 for Customer Quote
- PRE_BO_ID: The ID of the previous business object
- PRE_ITEM_ID: The ID of the previous item, e.g. 00010 for position 10 of a sales order
- PRIO_TYPE: The priority type of the business object; you will want to fill this only in very rare cases since you need to evaluate this data in existing exits or BRFplus rules; possible values – besides leaving it empty – are:
- P – Predecessor
- A – Additional information
- Parameter_Data: This table is not processed in standard, but it allows you to bring additional data into exits and BRFplus rules
- SEQUENCE_NO: A sequence number that can be used if there are multiple parameters with the same name
- PARAMETER_NAME: The name of the parameter, generally a field name
- PARAMETER_VALUE: The value of the parameter, you will need to make sure that formatting is as expected
- PARAMETER_UNIT_PARAMETER_NAME: The name of the parameter holding the unit name of the parameter
- GenericEventID: This parameter is not used in standard processing; the event ID that is actually used is derived as for standard BOR events automatically when the event is raised.
The previous business object information is required if the current object is not the first object in the process. The activities in the process are linked by process observer through the business objects, so any object but the first in the process flow must have a predecessor. The best way to provide the predecessor information is with the event, i.e. through the Previous_BO parameter; only if this is not possible, you have to implement one of the exits, BAdIs or BRFplus rules, in process observer.
You can raise the event like any standard BOR event using method cl_swf_evt_event=>raise or function module SWF_CREATE_EVENT and alike. Or you can use method cl_poc_bor_event=>raise_generic_bor_event with parameters
- IV_BOR_ID: This parameter is passed to the BOR ID object key and used as the ID of the business object
- IV_EVENT_ID: This is passed directly to parameter GenericEventID of the generic BOR event (and should probably be optional as for the most part you will not need it)
- IV_TASK_TYPE: This is passed directly to parameter Task_Type of the generic BOR event
- IV_BO_TYPE:This is passed directly to parameter BO_Type of the generic BOR event
- IT_PRE_BO: This is passed directly to parameter Previous_BO of the generic BOR event
- IT_PARAMETER_DATA: This is passed directly to parameter Parameter_Data of the generic BOR event (and should probably be optional as for the most part you will not need it)
The method does not commit, so don’t forget to make sure that some COMMIT WORK is raised, but be careful if you do that in your code in the exit. Generally the application will COMMIT.
You now have the tools to raise the event. You will now have to look for the right place to raise the event. Finding that is left up to your knowledge of the application; most SAP extension techniques will allow you to insert the appropriate code, namely Business Add-Ins (BAdIs), but also User-Exits, Customer-Exits and generally the enhancement framework that allows adding source code virtually anywhere.
Technically there is no customizing to do.
But since you need to assign task events you raise to your process definition – otherwise Process Observer will not map them to your processes – these tasks need to be created in the façade layer. You do this using IMG activity Maintain Objects in Facade Layer (transaction POC_FACADE). In short you first check if the respective business object exists, otherwise it needs to be created. Then you check if the tasks exist, otherwise you create it. You will not need to create new task types, just use some task type that is “as close as possible” to what you need, but technically you can use any task type – or create a new one, if you want. So if you have a new task for a new business object, that is two table entries – and that’s all.
You may be aware of the IMG activity Check Process Monitoring Events for Bus. Object Repository. The related view (POC_V_BOR_EVT) shows all BOR events that are relevant for process observer. Relevant events are derived from the tasks used in active process definitions. The corresponding table (POC_C_BOR_EVT) is updated every time you save a process definition. And while POCGENERIC.EVENT_RAISED generally will not be relevant in that sense, it is always added into this view. So there is nothing you have to do here. If you raise a large number of events of this type and do not consume any of them, you may wish to delete the corresponding entry for performance reasons. You need to remove the entry every time the definitions are updated, though.
First check the demo report POCR_SIM_GENERIC_BOR that is available as part of the generic BOR events. The report will raise some events against the Process Observer test objects POC1 and POC2 when executed. It shows how to set the basic parameters, the previous business object, how to fill the event container and finally call the generic method to raise the event. And since it works against test objects, you can actually run and test it – make sure you have a process definition active that works on the related tasks, e.g. the pre-delivered test definition POC_SIM3 or else you won’t see anything happening in the process monitor (but you would see the BOR log in SWEL – if logging is switched on).
But let us look at a practical example. The creation of a transfer order as part of the order-to-cash process does not raise a BOR event. The first thing we have to do then is to find an exit where we can implement our event. We are using function exit EXIT_SAPLL03T_001 of enhancement MWMTO001 here (and the code shown will only work there since it refers to some data that is passed as parameters) using SAP Enhancements (transaction CMOD). I will not go into creating and activating the enhancement, let’s just look into the code:
*& Include ZXLTOU01
DATA lv_bo_id TYPE char70.
DATA lv_bo_type TYPE poc_bo_type.
DATA lv_task_type TYPE poc_ba_type.
DATA lv_pre_bo_type TYPE poc_bo_type.
DATA lv_bor_object TYPE string.
DATA lv_bor_event TYPE string.
DATA ls_pre_bo TYPE LINE OF poc_t_pre_bo.
DATA lt_pre_bo TYPE poc_t_pre_bo.
DATA lv_event_id TYPE char32.
DATA ls_context_data TYPE poc_s_gen_param_name_value.
DATA lt_context_data TYPE poc_t_gen_param_name_value.
* Set the Event Parameters and raise the Generic BOR Event
lv_bo_type = ‘121’. “transfer order
lv_task_type = ’21’. “create
ls_pre_bo–pre_bo_id = i_ltak_vb–vbeln.
ls_pre_bo–pre_bo_type = ’73’. “delivery
APPEND ls_pre_bo TO lt_pre_bo.
* this wrapper method prepares the container of the Event and raises the generic event
CALL METHOD cl_poc_bor_event=>raise_generic_bor_event
iv_bor_id = lv_bo_id
iv_event_id = lv_event_id “not used
iv_task_type = lv_task_type
iv_bo_type = lv_bo_type
it_pre_bo = lt_pre_bo
it_parameter_data = lt_context_data. “not used
You will also need to create the BO Type 121 Transfer Order and the Task 121 21 Create Transfer Order in the process façade (transaction POC_FACADE).
When you then add an activity Transfer Order Created to your process definition and assign task 121 21 Create Transfer Order, the activity will be logged against your process definition as expected.
Note that you can use transactions Switch Event Trance On/Off (SWELS) and Display Event Trace (SWEL) to trace your generic BOR events. The Create Event transaction (SWUE) can also be quite helpful for testing.
One topic should be noted here: Do not use Process Observer’s generic BOR event for purposes other than Process Observer. If you implement the generic BOR event now and later are tempted to use that event e.g. for a workflow, do not do it. These events are for process visibility and should not be used for other purposes. The main reason here is that you may need to adjust your event for process visibility purposes, which will become very difficult once you have operational functionality like a workflow linked to it.
What to use
The generic BOR event is not a replacement for the direct API. It gives you an additional option that you may want to consider.
So if, after reading this, you are confused whether you should use the direct API described previously or the generic BOR event, consider the following: If you are already using either solution and have no issues, continue to use it. If you may have issues with race conditions, feel more comfortable using BOR related tools and if you are not using any direct events, the generic BOR event is probably a good choice. Otherwise the direct API may be simpler to use.
The objects and the related functionality described above are available with different support package levels of Software Component “Cross-Application Component” (SAP_BS_FND), which holds all core objects of Process Observer.
- 747: SP-Level 0001
- 731: SP-Level 0008
- 702: SP-Level 0010
- 701: SP-Level 0012
Even if this blog post is a bit lengthy for what it describes, it should be fairly easy to apply. We are trying to fill a gap, that will not be relevant to every project, but may make implementing Process Observer easier for others.
As always, let me know if you have any remarks, questions or ideas – either in the comments below, in our Process Observer Discussion or through personal communication – and good luck with your Process Observer project!