Using persistent objects in SAP workflows
The subject I would like to share with you here might already be discussed somewhere else, but as I didn’t find any doc on this particular integration, I decided to write this blog to share what I use to do when designing a Business Workflow in SAP ERP. After several integrations to different Customers, I had quite good feedbacks about it.
The typical scenario
Let’s say you must implement some kind of frontend capturing some data from end-users. Data must transit between different actors who must carry out some actions on them (approval, changes,…). Some emails must be triggered as well. Typical I said. Seems a workflow could be useful here to design the process.
Ok, for the process, we plan to use a workflow (ERP based one). The frontend is going to use a MVC pattern, model would be implemented using an ABAP class (Web Dynpro/BSP/UI5+Gateway/…). Ultimately, data for our request will be defined as class attributes.
Then comes the persistence part. Several options here: simpliest could be to store persistently our attributes in the container of the workflow. But what about the Segregation of Concerns? That also means we would lose our OO model and even the OO world. Development cycle is tougher as it will require more interactions between the workflow expert and the frontend developer. As a second option: you might know that SAP provides an Object-Relational Mapping tool called Object Services (that includes the Persistent Service) and allows you to make your objects “persistents”. For who doesn’t know yet what is it: http://en.wikipedia.org/wiki/Object-relational_mapping. I won’t explain in details all the advantages you can have using such a framework, but if you never played with it, I highly recommend it. You can find collaborative doc on how to implement that in SAP here: http://scn.sap.com/docs/DOC-27055.
Great! Let’s say we opted for option two, so our model is an ABAP persistent class. Another good news is that Business Workflow can be implemented using a class also! So no needs to pass a Business Object to our workflow or copy the data in the container. Simply implements the interface IF_WORKFLOW.
Instanciation of a persistent class is protected . A dedicated “Agent” singleton class is provided to manage your instance(s). That also means, if you decide to implement the IF_WORKFLOW interface in the persistent class itself that the workflow engine won’t be able to instanciate the class.
Even “technically” you can make that model working, you’re going to face problems when using standard transactions to manage your workflow instance. I would also add to keep these two things separated, from a design perspective.
A (cleverer) way
The goal here is to get a reference to our persistent object (the model) in the container of workflow (so the data are not stored in the container or even copied locally but consumed in our workflow nodes directly).
The workflow uses a instance ID when getting an instance of the workflow class (LPOR-INSTID, 32 characters long). That’s one part of the LPOR key used by the workflow (two other ones can be set statically).
On the other side, our model has a unique key as well. Let’s assume here to keep it simple that we used a GUID as unique key for our persistent object. Means a RAW16 data type. Means a 32 characters long when represented.
The trick here is to get back the GUID from our persistent object and pass it as the instance ID of our workflow class, typically when creating the workflow instance. The reference of our persistent object (declared locally in the workflow container) will be set every time you access the workflow calling the “get_persistent_by_oid” method that the Agent class provides in the “find_by_lpor” method that you must implement (main one of the IF_WORKFLOW interface). So “find_by_lpor” returns an instance of the workflow class containing a reference to your model. I pasted a short core example below:
Must have attributes in your workflow class:
Short exemple of “find_by_lpor” method, commented:
Then when retrieving data in workitems, you can invoke the getter methods of the persistent object using this pers_ref reference! Nothing else to do… Done.
Basically the data model is decoupled from the process flow.
This is my first blog on SAP SCN, I hope you found it interesting, or even better useful! 🙂 Any thoughts, other ideas or comments are welcome.