1 2 3 5 Previous Next

SAP Business Workflow

65 Posts

There are mainly 3 groups of Agents:

  • Possible Agents
  • Responsible Agents
  • Excluded Agents

Apart from these 3 groups, there are 2 other categories of agents:

  • Recipients
  • Actual Agents

Possible Agents

  • These are people who can execute a task.
  • Defined in the "Task" level
  • Best practice to assign possible agents, is to sync with Security Roles
  • A task can be marked as "General Task" to allow anyone to execute the work item.
  • There are different ways to assign possible agents.
    • For SAP provided workflows, we can assign possible agents using IMG.
    • When we are displaying a task, we can use the following menu path
      • Additional data --> Agent assignment --> Maintain
      • The transaction is PFTC_DIS.
    • From task profile section of organization plan
    • From profile generator (Roll Maintenance);  Transaction PFCG
    • From workflow builder during step definition.

Responsible Agents

  • Responsible agents are people who you want to execute a particular work item.
  • Responsible agents are usually assigned in workflow step level, but can also be assigned at the task level via default agent determination rules
  • Usually responsible agents are determined during runtime using two main ways
    • Expressions
      • In expressions, the data needed for agent determination is stored in workflow containers, which later is used in computations and agent is determined based on container values.
    • Rules
      • In rules, agents are determined dynamically when work items are created.
      • We can bind data from workflow to the rules to provide data for agent determination computations.
  • For a work item to be forwarded to a responsible agent, the agent should also be a possible agent.

 

Excluded Agents

  • Excluded agents are people who should not receive the work item for execution
  • Excluded agents are always assigned by an expression to the workflow step
  • Typically we put all excluded agents in a multi-line container in the workflow container, and use an expression to assign the list of excluded agents to a particular step.

 

Recipients

  • Recipients are agents who receive a work item.
  • Recipients are
    • Possible Agents
    • Responsible Agents
    • Are Not Part of Excluded Agents
  • If there are no possible agents, then nobody will receive the work item.
  • If no responsible agents are determined, the system checks to see if any default agents are defined in the task level.
  • Recipients can forward work items to another agent. Whether or not the recipient can forward the work item is determined by the attribute of task.
    • General Task
      • Work item can be forwarded to anyone and executed by anybody
    • General Forwarding
      • Work item can be forwarded to any user.
    • No General Forwarding
      • Work item can only be forwarded to possible agents.
    • No Forwarding
      • Work item cannot be forwarded.

 

Actual Agent

  • Actual agent is the agent that is currently processing a work item or the user who has last processed a work item.

 

Assigning Multiple Agents to Work Items

  • Many agents can be assigned to a single work item.
  • The work item shows up in all agents inbox, and disappears from everyone else when one agent reserves or executes a work item.
  • Sometimes we need every agent to make an active decision from particular process. To do this, we can create one work item per agent.

 

Deadline and Notification Agents

Deadline Agents

  • Deadline agents are people who receive work item when a deadline has exceeded for a work item
  • These agents are entered in the deadline Of workflow step.

 

Notification Agents

  • Notification agents are people who are notified when a work item is completed.
  • Usually entered in notification tab of workflow step.

 

Agent assignment using organizational structure

  • Every workflow agent must have a userid.
  • Assigning userid directly for task may be very high maintenance.
  • Organizational plan helps in simplifying this issue.
  • Every SAP application server comes with basic organizational plan

 

Basic organization Plan

Organizational Units

  • Represents a group of people such as 18, section, Department, work area, lab, help desk, or shared service Centre.

Jobs

  • A job described functional role within the organization.

 

Positions

  • Position represents a headcount placement.

Users

  • Users is the actual userid of a person.

 

  • Workflow task can be linked to one or more Organization units, positions, jobs, or users.

 

Extended Organization Plan

  • SAP my HR comes with extended organization plan
  • Extended organizational plan includes personal numbers
    • A person represents a PERNR
    • a person may be assigned to one or more positions.
    • A user is assigned to a person by setting up info type 105 (Communication)
  • From workflow perspective, extended organizational plan has following benefits
    • Much more data in organizational plan to help make decisions.
    • "Evaluation paths" can be custom built and used as rules to find organization objects.

Reassign Work Items from One Agent to Another

  • If a user changes job or position, existing work item may need reassignment.
  • Typically, only served work item needs reassignment.
  • We can find outstanding work items for the user using transaction : SWI5. This transaction should be run before removing the user
  • We can find orphaned work items using transaction : SWI2_ADM1

Temporary Substitution of Agents

Sometimes will need to temporarily substituted the agent. This can be done in two ways:

  • The HR substitute relationship A210
  • User Substitution (Table: HRUS_D2)

The HR substitute relationship A210

  • We create substitute for a position using A210 relation between position and substitute.
  • All work items for that position are made available to the substitute.

User Substitution Using Table HRUS_D2

  • This is usually maintained from user's inbox using menu path

   Inbox --> Settings --> Workflow Settings --> Maintain Substitutes

  • We can also create entries directly using ABAP

 

Substitute itself can be of two types:

Active Substitutes

  • In active substitution, work items are automatically forwarded or appear in the substitutes inbox.

 

Passive Substitute (also called adopt Substitute)

  • Require the substitutes to explicitly choose to see original agents work item

 

Refreshing Organisational Plan an Environment

  • The organisation plan is buffered for efficiency.
  • Changing an organisation plan will not immediately be updated in the buffer, and hence can create confusion especially for workflows using the plan for agent determination.
  • Typically buffer is refreshed at midnight.
  • Alternatively, in development systems, we can trigger refreshing of buffer using transaction: SWU_OBUF
  • It should be noted that the buffer afresh is a resource intensive process
  • When writing your own programs for buffer afresh, following function modules can be handy:
    • RH_WF_OM_INDICES_TIMESTAMP_RFS
    • RH_TASK_INBOX_VIEW_REFRESH
    • RH_TASK_AGENTS_INDEX_REFRESH

 


Work Item Execution

  1. Synchronous Dialog Chain
    1. Allows User to execute several work items one after the other without returning to Inbox
    1. Set using "Advance with Dialog" flag in workflow  definition.
  2. Multiple Execution
    1. Agent can select a set of work items from inbox, and execute all of them together.
    2. Decision of 1st work item is copied applied to all work items.

 

Forwarding Work Items

  • Forwarding a work item to another agent removes it from all other agent's inbox.
  • If the receiving agent "replaces" the work item, it will re-appear in all original agent's inbox, AND will also be in the agent's inbox to whome it was forwarded. In other words, the list of agents is modified when forwarding.
  • Forwarding can be configured in individual task. Following options exist
    • Work Item cannot be forwarded
    • Work Item can be forwarded to anyone.
    • Work Item can be forwarded only to possible agents.
  • Example scenario where forwarding may be useful
    • Change in position of an agent, and handing over remaining work to whoever is replacing
    • Agent determination is incorrect/failed.

 

Work Item Priority (In Inbox)

  • The priority only affects the sorting order in inbox.
  • Priority = 1, is the highest priority. If an agent gets a work item with Priority = "1", then a popup message is displayed if they are logged into SAP GUI, irrespective of which transaction they are in.

 

Work Item Re-Submission

  • If an agent does not want to handle a work item immediately, they can "Re-Submit" for a later time. Work items that are re-submitted are removed from the agent's inbox, and will be held in "Resubmit" queue.
  • When the re-submit time comes, it pops back in the agent's inbox.

 

 

Workflow Logs  

  • Technical log is the most detailed workflow log, and should be heavily used during development.
  • For average agent, there are mainly 3 kinds of logs:
    • Chronological View
      • Displays non-technical steps
    • Agent-Oriented View
      • Displays which agent worked on what, in the entire workflow execution.
    • Object Oriented View
      • Displays list of objects involved in the process.
      • Eg: Business Objects, Attachments..etc.

 

Work Item Delivery Strategies

  • Email Notification
    • Provided using report : RSWUWFML
    • Periodically polls work items.
  • Groupware Integration
  • Portal Integration
    • Can use workflow "iView" which has following features
      • Simple UI
      • Auto refresh in 10 mins
      • Display work items from all SAP components.
  • External Users

 

Part 2 :  Agents

When it comes to symbolizing  the customer engagement between SAP and Customers for SAP (esp. Business Workflow), there’s no-one quite like Susan Keohan.  No one!

 

She is the Workflow Goddess.
   
SueKeohan.jpg 
[Susan Keohan]
 
Not even my t-shirts from the first ASUG events that I attended with Sue, have survived the aging processes as vividly as my memories of Sue – such is the impact she makes.  Ditto for the impact she has made on the software itself. We are talking about 15 years of continuous influence here, longer than the retention period of my emails!
 
Sue’s first presentation, “Plain Sailing”, was about a day in the life of a workflow administrator, in the days when the workflow sea was more like a boiling tempest compared to the mill-pond that it is now. I was inspired by Sue’s calm and confident way of describing how she tacked up one mountainous wave and down another as she made her workflow work wonders for her employer (Massachusetts Institute of Technology – no stranger to software or leading edge ideas). She had us falling off our seats in laughter, and gaping in amazement as she described one achievement after another. For example, how she used the workflow reporting to persuade the Nobel-prize-winning Principals and Deans that not every single purchase requisition needed to go through an n-step approval process – a radical departure from conventional workflow wisdom in those days.

 

Needless to say, Sue is a keen sailor in her spare time, so I’m sure she’s tamed the lake where her yacht is moored to be as quiet as a tadpole when SHE’s on board.

 

From joint shopping expeditions, I know she has two sons (they’ve grown out of their cowboy costumes by now) and a husband with his own career path, too. So family life was always important to Sue, and somehow she managed to juggle both family and career in such a way that neither got in the way of her influence on SAP’s software.  In fact, perhaps it’s because of her “mother hen” talents that we all had such a good time at the ASUG events and nobody
(from newbie to alumni) was neglected. 
Tip: If you’re new and lost at the 2013 event (it is pretty overwhelming) just say hi to Sue …. She’ll make you at home and steer you in the right direction.

 

SueInAction.jpg
[Sue during a typical ASUG moment]
Talking of influence – Let me slip in some praise for the VNSG (the SAP Dutch user group), assisted by Avelon  and Ralf Goetzinger from SAP,  for initiating Customer Satisfaction improvements in the workflow tool, and for reaching out to Sue to get the innovation jointly supported across user groups. This international collaboration was a bold and successful move – typical of Sue to see an opportunity the instant it arises, and have the patience of a captain to see it through.

 

<anectdote>… Attending a think-tank meeting near Boston, we were interrupted by a fire-alarm. Minutes later the fire brigade arrived sirens and all.  I think it was the reassuring posture of Sue, that sent the firemen back to the station so quickly that the meeting could continue without skipping a beat..</anectdote>

 

Sue was an SAP Mentor even before SCN or SDN were born.  Necessity being the mother of invention, this was built on a list-server (email technology) hosted by MIT.  In its peak (before the Web was mature enough to provide an alternative through SCN) there were many hundreds of messages a
week, and her message-based Fire-And-Inspire is a tradition she continues to this day. Confession: I secretly blamed Sue for the days when twitter used to go down under tweet load. Was it @SKEOHAN and the tweets she inspired that caused this?

 

But tweets and list-servers are transient, so it is with real satisfaction that I can pronounce it a huge win for the SAP customers that she joined the authors of the 2nd edition of the workflow book.  Her tremendous insight and experience as a seasoned administrator and workflow solution expert has been captured in a permanent form. And (my guess) influenced by Sue, the author-revenue is 100% donated to a worthy humanitarian cause (Doctors without Borders).
Historical note: Nevertheless it is Ginger Gatling who takes the full credit for this generous idea… just saying that Sue influenced.
WorkflowBook.jpg

[2nd Edition Workflow Book]

 

Enough said….if you want a passage through an IT storm… Sue is your captain of choice.

 

And if you like a good heroic tale, join her in her sessions at ASUG 2013.

 

 

 

Version management in SAP Workflow is very good feature to track the changes. Yet, we do not have easy way to compare two version unlikely in ABAP workbench, It gives us possibility to create different versions for requested changes in workflow.

 

Consider the following case. You have defined a workflow. It is working correctly on production system. A new requirement has arised and you had to make changes. After that you transported your changes to production system. Everything is fine till that point but there is a question mark. What will happen the current workflows which are still not completed. In some business cases it takes days or weeks to complete workflow. SAP Workflow version emerges at that point.

 

In SAP Help It's written that :

 

Each time a workflow definition is transported into another system, only the active version is transported. If the workflow definition exists in the target system with the same version number, it is overwritten by the transported version if it has no workflows running. Otherwise, the transported workflow definition is saved with a free version number. The transported workflow definition becomes the active workflow definition in the target system.

 

As a result, the old workflow instances will work as they were defined and the new ones will work with the new definition.

 

In most cases this works correctly. However in some cases workflow version is not activated. Since there is no active version of workflow exists, workflow doesn't start. I don't know the exact case but there is an OSS note about it (OSS note 1027175). To activate the version we can use report RSWDACTIVATE to manually activate the version

activateversion.png

 

When you click on activate icon the selected version is activated and workflow will be working correctly with new active definition.


Recently I was able to put my hands on a ECC 6.0 Ehp6. I read about the new functionalities available on SAP Business WF since the last year and I was curious to understand something more about the development described in note 1643764 - User decision with automatic note (available only via support package).

 

SETUP

 

I created a WF with three decision steps and the container element

Cattura1.JPG

The first question is “Can I write a note ?”

 

Cattura2.JPG

Note the “Justification” column in the Decision Option table. In this field you can decide if the note is “Required”, “Mandatory” or not needed for a specific alternative. In the Control tab, the binding is set as follow

 

Cattura3.JPG

The second decision is “Can I change a note ?”

 

Cattura4.JPG

In the Control tab, the binding is set as follow

 

Cattura5.JPG

The third question is “Does it work ?”.

 

Cattura6.JPG


Running the WF...

 

this is what you get.

 

Cattura7.JPG

If you answer “No” the WF goes on without asking anything. If you click on “Yes, you must” (note is mandatory) a pop up appears

Cattura8.JPG

If you press “Cancel”, you go back to the decision. If you press “Continue” without writing anything in the text box you get the error “Create a reason for the selected alternative”. If you specify a text and press continue, the WF goes on to the next question.

 

If, in the decision step, you click on “Yes” (note required) the same pop up appears but if you click on “continue” without writing anything, the WF goes on to the next activity.

 

Assuming we just wrote a note, this is the way the second question appears :

Cattura10.JPG

The previous note is shown as an attachment. The button “Create reference” is available in the tool bar (as a consequence of the binding defined in the WF). The right answer to the question is “No” but the button “Create reference” let you use an existing note as a template. You can update the message and save it as a new WF document (actually, this is not a new functionality).

Clicking on “No” the WF propose the last question… “Does it work ?”

 

Cattura11.JPG

 

Well, from a technical perspective the answer is "Yes". It’s quick, easy to understand and easy to develop  but I can’t swear that my customers will appreciate it as  I do....

Introduction

 

When you read through the blog post Another 10 Common Mistakes made by Workflow Beginners from Paul Bakker, you can find in section #16 the advice to avoid duplicate workflow instances and the advice

You could set a 'check function' on your event linkage, so that no new workflow is started if an active workflow already exists for the same object. Or, when a change occurs, raise an event to terminate the existing workflow and start a new one.

 

In this blog I will show you, how to achieve a very safe singleton concept, starting with

  1. The event coupling and check function to prevent duplicate workflows
  2. Trigger-Wait-Event concept for Singleton
  3. Enhanced event trigger for super-safe approach

 

 

1. Event check function for "is another workflow already running"

 

If you would like to check, if there's already the same workflow (i.e. to be exact: "A workflow instance of this object running, that is based on the same workflow pattern as this one"), you'll need two information

- The object instance identification: type and instance key

- The workflow pattern ID

 

Both is already available in the standard event coupling, if you're not using any specialty here:

  • - The object comes within the SENDER as an importing element
  • - The workflow pattern ID comes as the RECTYPE as another importing element

to the check function module.

 

This way, it's possibly to create a generic check function module Z_CHECK_OTHER_WORKFLOW_RUNS, that is working with all workflow implementations instantly:

 

FUNCTION Z_CHECK_OTHER_WORKFLOW_RUNS.

*"----------------------------------------------------------------------

*"*"Local Interface:

*"  IMPORTING

*"     VALUE(SENDER)          TYPE  SIBFLPORB

*"     VALUE(EVENT)           TYPE  SIBFEVENT

*"     VALUE(RECTYPE)         TYPE  SWFERECTYP

*"     VALUE(EVENT_CONTAINER) TYPE REF TO IF_SWF_IFS_PARAMETER_CONTAINER

*"  EXCEPTIONS

*"      OTHER_WORKFLOW_RUNS

*"----------------------------------------------------------------------

 

   "The method generically finds any workflow based on

   "the sender object.

 

   DATA: lt_task_filter       TYPE STANDARD TABLE

                                  OF SWR_TASK

                                  INITIAL SIZE 2,

         lt_worklist          TYPE STANDARD TABLE

                                  OF SWR_WIHDR.

 

   DATA: ls_task              TYPE swr_task.

   ls_task = recType.

   APPEND ls_task TO lt_task_filter.

 

   CALL FUNCTION 'SAP_WAPI_WORKITEMS_TO_OBJECT'

     EXPORTING

       OBJECT_POR                     = sender

       TOP_LEVEL_ITEMS                = 'X'

       TEXT                           = ' '

       OUTPUT_ONLY_TOP_LEVEL          = 'X'

     TABLES

       TASK_FILTER                    = lt_task_filter

       WORKLIST                       = lt_worklist.

 

 

   "Check running. If error-workflows, then start another instance

   READ TABLE lt_worklist TRANSPORTING NO FIELDS

                          WITH KEY wi_stat = 'STARTED'.

   IF sy-subrc = 0.

      RAISE OTHER_WORKFLOW_RUNS.   "Use better MESSAGE E... RAISING ...

   ENDIF.

 

   "You may also check for wi_stat = 'ERROR' if you like that

 

ENDFUNCTION.

 

ST00 Check workflow start.png

 

This looks already like we're done, and for normal cases it's working fine. However, the story continues, as soon as you have multiple starting events at the same time (right after posting a document or later on through a change document). In such cases, if the workflow instances are created simultaneously, each call to SAP_WAPI_WORKITEMS_TO_OBJECT will return that no instance is currently running, and at the end you still have two (or more) workflows running. Just think of the BUS2012.ReleaseStepCreated event, which can occur more than once at the same time.

 

This leads us to the next section, closing the door via the second workflow design pattern as mentioned by Paul before.

 

 

2. Trigger-Wait-Event concept for singleton

 

As outlined in chapter 1, it's still possible to have a another workflow instance running, although you're checking that in the check-FM during the creation event, or you just can't check at the time of the event creation and you have to rely on the workflow instance.

 

This trigger/wait event concept foresees, that each new workflow instance will close all already running workflows in place. So, yes, a new workflow will start, but in ends any other existing way, leaving only one left for the object instance.

 

As you need the instance identification anyways, I suggest to create an event .CloseProcess on the instance level of the object type, regardless if you're using the BOR design or the new ABAP OO Workflow design.

 

ST01-1 Close Process event definition.png

Within the workflow pattern, you design a sender fork/wait combination like this:

 

ST02 Workflow pattern for singleton.png

The sending step will raise the event for <instance>.CloseProcess and any other workflow who's already listening to that event (because it's running), will end up immediatly. After that is done, the workflow will itself wait for such an event, just for the case, there's a newer workflow coming up.

 

ST03-1 Event send step.png

The fork will cover the complete workflow implementation. So after receiving the event .CloseProcess for the <instance> you'd immediately need to complete your workflow gracefully.

 

ST05 Event wait step.png

 

So, that's all not real magic and you have another advantage, that if you'd like to start all-over with a couple of workflow instance, you can now easily raise the event .CloseProcess for the instance you don't like anymore and create a new start event (if you're including the solution of chapter 1 a new workflow wouldn't start with a second start event, because that is prevented).

 

However, there's a small piece missing, as I have experienced, that the event processing through the workflow runtime system can take some time, and under certain circumstances it may happen, that the workflow is receiving its own .CloseProcess event. This happens, when the rRFC queue is full and the event creation is delayed. In such cases, the wait step is already created, before the event is receiving, ending up with no workflow running at all.

 

To solve this, please read the next chapter.


 

3. Enhanced event trigger for super-safe approach

 

The event trigger for .CloseProcess must provide the own source top-Workflow ID, so that the receiving wait step can identify itself.

 

Add an event parameter EV_WORKFLOW_ID to the definition for .CloseProcess like this:

 

ST01 Close Process event definition.png

Create a dataflow upon creating the event like this now:

 

ST03 Event send step.png

Now the trick: Edit the instance linkage for the .CloseProcess event and add a check-function module there (transaction SWEINST):

 

ST04 Check not own subflow.png

And when done with it, you'd still need the coding excerpt from the check-FM, so here it comes:

 

FUNCTION Z_CHECK_NOT_OWN_TOPFLOW.

*"----------------------------------------------------------------------

*"*"Local Interface:

*"  IMPORTING

*"     VALUE(SENDER)          TYPE SIBFLPORB

*"     VALUE(EVENT)           TYPE SIBFEVENT

*"     VALUE(RECTYPE)         TYPE SWFERECTYP

*"     VALUE(EVENT_CONTAINER) TYPE REF TO IF_SWF_IFS_PARAMETER_CONTAINER

*"  EXCEPTIONS

*"      THIS_IS_THE_SAME_WORKFLOW

*"----------------------------------------------------------------------

 

   DATA: lv_sending_topflow_ID                  TYPE swwwihead-wi_id.

 

   TRY.

      CALL METHOD event_container->get

                    EXPORTING

                       name    = 'EV_WORKFLOW_ID'

                    IMPORTING

                       value   = lv_sending_topflow_id.

 

      IF NOT lv_sending_topflow_id IS INITIAL.

      "The top workflow IS present in the event container, so we will check it!

 

*    ** Read workitem instance and container from event

          DATA: lv_target_ei_id                 TYPE swwwihead-wi_id.   "Event wait step of target workflow

 

          CALL METHOD event_container->get

                           EXPORTING

                               name    = evt_receiver_id

                           IMPORTING

                               value   = lv_target_ei_id.

 

          IF NOT lv_target_ei_id IS INITIAL.

 

             "Yes, so we have not source TopFlow and target EventID.

             DATA: lo_wi_handle    TYPE REF TO if_swf_run_wim_internal.

             DATA: ls_context      TYPE sww_wimctx.

             DATA: lo_wi_container TYPE REF TO if_swf_cnt_container.

 

*         - set context

             ls_context-do_commit  = ' '.

             ls_context-called_btc = 'X'.

             ls_context-exec_user  = sy-uname.

             ls_context-fbname     = 'Z_CHECK_NOT_OWN_TOPFLOW'.

 

             CLEAR lo_wi_handle.

             CALL METHOD cl_swf_run_wim_factory=>initialize( ).

             CALL METHOD cl_swf_run_wim_factory=>find_by_wiid

                              EXPORTING

                                 im_wiid             = lv_target_ei_id

                                 im_read_for_update  = ' '

                                 im_context          = ls_context

                              RECEIVING

                                 re_instance         = lo_wi_handle.

 

             IF NOT lo_wi_handle IS INITIAL.

                DATA: ls_swwwihead_of_target_EI             TYPE swwwihead.

                ls_swwwihead_of_target_EI = lo_wi_handle->get_wi_header( ).

 

* *********************************************************************

*

*    COMPARE  the sending top-workflow  against the receiving  top-workflow

*

* *********************************************************************

 

                IF ls_swwwihead_of_target_EI-top_wi_id = lv_sending_topflow_ID.

 

                   MESSAGE E005 RAISING THIS_IS_THE_SAME_WORKFLOW.

                    "Received event from the own workflow instance

 

                ENDIF.

             ENDIF.

          ENDIF.

       ENDIF.

 

      CATCH CX_ROOT.

         "Exception handling is cut here for a better overview only

         "Attached coding file has full exception handling provided

 

   ENDTRY.

 

ENDFUNCTION.

 

 

Enjoy Workflow.

Take care.

 

Any helpful comments are highly appreciated.

 

    Florin Wach

    Systems-Integration

    SAP Business Workflow Senior-Expert

Torsten Schnorpfeil will be presenting several sessions (along with Martin Maguth) in the SAP Workflow and Business Process Management track at ASUG Annual Conference (May 14 - May 16).  As you may already know, ASUG is conveniently co-located with SAPPHIRENOW. (You have heard of SAPPHIRENOW, haven't you???)

 

I've known Torsten for many years and had the pleasure of learning from him at several prior ASUG conferences.

 

I had the chance to catch Torsten prior to the conference and find out a little more about him.

 

He lives in Miami with his 3 loves - his wife, his motorcycle, and his 1970 Chevy Impala convertible.  He graciously provided me with a couple of photos:

 

 

 

 

I believe he will be making the trip from Miami to Orlando in the Chevy (I also believe he owes me a ride in it!)

 

Torsten has been working with SAP since the mid-90s; he started with a 'little' archiving company in Germany, and then moved to the US to build the practice here.  When I asked him why he works with Workflow (besides joking that 'I can only do process improvement in SAP!') he said that it was the perfect match for him.  Torsten has a Masters in Business Administration, and says that since he likes Information Technology and has a business background, SAP Workflow was the perfect fit for him.

 

One of Torsten's favorite projects was connecting SAP Workflow with Sharepoint.  He said that integrating those platforms is very interesting and challenging.  He is also starting to work more in the Plant Maintenance area, and is having fun with that.

 

When I asked him what he would be doing if he wasn't working with SAP software, without hesitation he said 'I'd be riding my motorcycle all day!'.  I had to press a little to find out more... he finally admitted that he would run a motorcycle shop and fix up motorcycles (only vintage ones).  Or, he would have a tomato farm.  Well, that really got my attention - because I am a crazy tomato lover when they are in season.  Torsten said that there are so many wonderful varieties of heirloom tomatoes that he thought that would really be fun.  Plus, they would be totally organic, of course.

 

In addition to the land vehicles, he owns a small trimaran and enjoys sailing.  If I lived in Miami, I would too! 

 

This year, he can be found at the following sessions.

 

 

So, keep your eyes open for this guy...

 

 

He might give you a ride in a snazzy convertible.  Or not.  But you will definitely learn some great stuff about SAP Business Workflow from him!

Introduction

 

The new ABAP-Objects Workflow has taken over the existing concept of temporary and application exception, as it was used with BOR-based Workflows. It has been replaced by using a set of predefined exceptions within the method's implementation.

 

The most commonly used exceptions are the following

 

 

Exception class
Type
Description
CX_BO_ERRORErrorApplication error occurred
CX_BO_TEMPORARYTemporaryTemporary, recoverable error occured
CX_BO_ACTION_CANCELLEDTemporaryUser has cancelled the processing

 

You may also lookup for more exception, using the class builder and lookup the class hierarchy of CX_BO_TEMPORARY and CX_BO_APPLICATION, that are the two top-classes for the ABAP-OO Workflow Exceptions.

 

To use one of the given classes, you can just defined them in the "Exception" definition of the method.

01 Method exceptions.png

The simplest way to make use of the feature that you've just created, is like this

 

RAISE EXCEPTION TYPE cx_bo_error.

 

With the BOR-based implementation, you had to define each exception with reference to a message-ID. This message-ID, including the four variables sy-msgv1,... were then displayed in the workflow log, and under the "Message" button of the workitem, which is a very nice feature, as you can provide more detailed information othen than just saying "There was some kind of error, and you could recover it, because it's possibly temporary".

 

02 BOR Exception definition.png

And by raising the exception, you could pass more information to the workflow log.

 

exit_return 9001 'WACHF'.   "User &1 is currently locking table XYZ

 

With the ABAP-OO implementation, this has become a bit more complicated, but once you're through with it, it becomes fairly easy.

 

I do not repeat the common basis to define the outcomes in the step definition, how to create an ABAP-OO-Workflow class and so forth. Please read through the SCN, documentation or visit BIT611 for more information on that general topic.

 

 

Using custom text for OO-Workflow Exceptions

 

You can use the predefined classes and populate them with your own "text element" to have some more information displayed to the end user or the administration. The first - simplest - approach is, to create a new textID in the repository and use that, when raising the exception.

 

Create a new "concept" with transaction SOTR_EDIT.

 

Maintenance screen of SOTR_EDIT
Call menu option Concept - Create
03 SOTR_EDIT1.png04 SOTR_EDIT2.png

 

Then fill in the screen for a new concept, which becomes the TEXTID later on. The field "Object Type" needs to be filled, but it's pretty much useless here.

 

 

 

Please read through the documentation of the transaction to find out, how to translate the object into other languages, create a transport request, and so on.

05 SOTR_EDIT3 Create new concept.png

After you've created the new concept, you'll get a new GUID, which I would suggest to save it into a class constant.

06 SOTR_EDIT concept created.png

To make use of this custom text within the exception handling of the workflow, you can simply use the following ABAP:

 

RAISE EXCEPTION TYPE cx_bo_temporary EXPORTING textID = '0050568015291ED2ABB3C86EAD8513B4'.

 

That's it, already!

 

This will now look like this in the workflow log:

 

07 Log 1.png

08 Log2.png

 

However, sometimes, that not just enough. ... and the story continues ...

 

 

Using custom texts with variables

 

To make text replacements for the text of the exception class, there're two general approaches possible: Using a TEXTID based exception or a MESSAGE based exception. In the following section I will outline how to implement this with a TEXTID, as we should already know by now, how to use the SOTR elements.

 

Create a new concept with SOTR and create placeholders as you would like to provide them later in the class definition as public instance member attributes.

 

09 New concept2.png

 

Now create a new subclass of the exception type, you need, e.g. a temporary exception. So create a new class ZCX_TEMPORARY_WITH_TEXT, inheriting from CX_BO_TEMPORARY. Please be aware, that the exception class name must begin with ZCX..., YCX... or /<namespace>/CX...

 

Create new member attributes for that class, as you like. In this example: USERNAME. It must be the same naming as you're using between the & and & of the text element.

 

10 New attribute.png

The usage is now a bit different. So first of all, you need to list the exception in the method signature, of course:

 

11 Exception method with text.png

 

And you cannot use the shortcut ABAP statement anymore, because you will need the following three steps:

- Instance a new exception class

- Assign the text elements before raising the exception

- Raise the exception object instance

 

"Special lock exception with text replacement on-the-fly

DATA: lx_temporary_locked                TYPE REF TO ZCX_TEMPORARY_WITH_TEXT.

 

CREATE OBJECT lx_temporary_locked        EXPORTING textID = cv_textID_locked.

 

"All text elements embraced by & will be replaced by instance attributes

lx_temporary_locked->username = 'WACHF'.    "As an example

 

RAISE EXCEPTION lx_temporary_locked.   "Object is temporary locked by user WACHF

 

And in the workflow log, it appears now like this:

 

12 Object text with replace.png

 

And this is really an improvement, when comparing it with the default text:

 

13 standard message.png

 

It's some work, but it's very nice to use, when you got there.

 

Variant 2 - Using exception with message classes

 

Thanks to the comment of Jocelyn, I've added the part to populate a message-ID to an exception and raise that. However, I didn't find any substance need to modify/enhance the exception's constructor. It's working without any coding (changes).

 

The existing class CX_BO_TEMPORARY is not an exception-class "with message class", so you can't use it directly, but you have to subtype it. So please subtype a new class, e.g. ZCX_TEMP_EXCEPTION_WITH_MESSAGE from the super exception class CX_BO_TEMPORARY.

14 Create CX with message.png

Check the box "With Message Class" now.

 

After that, activate the new class. You don't need to make any changes in the subtyped class.

 

Then add the new temporary exception to your exception list of the method. And here's the coding excpert, how to correctly raise that message. In my example, I chose to set the message WF 015 "Cancelled by user":

 

DATA: ls_message              TYPE SCX_T100KEY,

      lv_message_text(50)     TYPE C.   "Dummy message holder

 

MESSAGE I015(WF) INTO lv_message_text.     "For where-used list and SY variables

ls_message-msgid = sy-msgid.

ls_message-msgno = sy-msgno.

ls_message-attr1 = sy-msgv1.

ls_message-attr2 = sy-msgv2.

ls_message-attr3 = sy-msgv3.

ls_message-attr4 = sy-msgv4.

 

RAISE EXCEPTION TYPE zcx_temporary_with_message EXPORTING textid = ls_message.

 

 

After that, you can find a temporary exception in your workflow log with  the detailed message!

 

15 Message in log.png

 

 

Any helpful comments are very welcome.

Please "rate" or "like" if you find this information useful.

 

Take care.

 

    Florin Wach

    Systems-Integration

    SAP Business Workflow Senior-Expert

I first met Martin years and years ago - and attendees at the upcoming ASUG Annual Conference (conveniently co-located with SAPPHIRE NOW) will have the chance to meet him too.  Martin will be co-presenting at 3 sessions, as well as the SAP Workflow and BPM Open Forum.  He was originally scheduled to co-present with his colleague Torsten Schnorpfeil for just 2 sessions, but I had a speaker back out and Martin was willing to fill in.  That's just the kind of guy he is.

 

I remember being so entertained - while learning so much - at all of Martin's sessions at earlier ASUG conferences (going back to, oh, I think the year 2000).  He was working for a company that specialized in Archiving and Workflow at the time, and Martin has the best stories to tell about how businesses ran prior to electronically storing their documents - back when paper invoices were warehoused in the basement of a 30 story building - and naturally, you needed to have the paper invoice in hand when you were processing payments against it.  We'll have to see if we can get Martin to share one or two of those stories, if time permits.

 

Here are the sessions that Martin will be participating in:

 

 

Martin does have spare time however (just not at the Annual Conference ) and when he has some, he will often go scuba-diving, or motorcycle riding.  He also travels a lot - as one might expect.  I am hoping he brings some photos of his scuba diving adventures to the conference. 

 

 

 

 

So if you see this guy wandering around at ASUG, follow him!  He is most likely going to one of the ASUG WF/BPM sessions. 

 

Cheers,

Sue

I'm addressing two difficulties that arise, when working with object instances of any kind during workflow processing:

 

  1. The same object instance is used several times during a single sequence of an ABAP transaction
  2. The same or different attributes from that instance are used

 

The approach to work with problem A is: Use a “caching algorithm”, which is put into place on the central spot, where the SAP Workflow Runtime system is picking up any instance: FIND_BY_LPOR of the workflow interface. There is a template implementation provided within the ABAP OO White-Paper from SAP AG, Jocelyn Dart (thanks again to Jocelyn), and I have extended it to be used for a central generic instantiation (please see below).

 

For the duration of an ABAP transaction, all created object instances, will be put into a system cache, where they are picked up again, whenever they are asked for again.

 

For problem B one can improve database performance to pre-select the main database tables that are commonly used, to avoid a second re-read at a later time.

 

This is good to provide a more simple delivery of the object’s attributes, that can more easily be used within a workflow implementation.

The approach to work with problem B is to follow the principle of a “big” object. Big objects pre-select all their possible values from the database before they are used. This is a very convenient way, how the workflow implementation can easily access and switch on the object’s attributes. The workflow is usually working with a very limited number of object instances (usually, there’s only one leading object). There is a certain drawback, when the object instances are used within mass processing, that takes place in front or aside of a workflow implementation: Too much data is selected, when there’re only a subset of attributes is needed, and secondly, the memory consumption of the ABAP runtime increases, as per solution to problem A, the object instances – once created – stay in place for the duration of the ABAP transaction.

 

In a "real" implementation, this could mean that a job, that previously took around 5 minutes to work, runs for hours and hours, because the system is busy to instantiate all the various objects for more-or-less nothing or barely no effect.

 

Counteractions, when using mass processing

 

  • Mass processing should avoid to instantiate the business objects, before there’s an action required, where the implementation or logic is really needed. So it can be advices to make some part of the database selection first, and have the object instantiated later on for processing.
  • The cache algorithm needs to be taken care of. A method .release() can be implemented to finish up the object instance cache, to reduce memory usage.

 

BOR Objects

 

Unlike with the ABAP Object implementation of a Business Workflow you have so-called "Virtual attribute" available, that processes an underlying getter-method, once the attribute's value is processed. (A "Table attribute" is basically the same, but they all refer to the same getter method). That is, the expression &BUS2081.CreatedOn& will execute implicitly a method get_createdOn within the BOR object's implementation. Here you can have a similar caching algorithm, which is usually generated by the BOR wizard when creating a "Table attribute".

Thanks to Sue, who outlined this feature below in the comment section, so I have included this section here for referring to it, too.

 

Once I had to manually downgrade an existing ABAP-OO implementation to a BOR-based workflow I have refactored the functional methods to become virtual attributes, and then using the existing caching algorithm from below. This worked really well, too.

 

So here follows the approach to have something similar with ABAP Objects.

 

The generic caching algorithm

 

Create a new class ZCL_WORKFLOW_CACHEABLE, non-final public instantiation implementing interface IF_WORKFLOW

Provide a private static attribute gt_instances_base, holding a table of object references to ZCL_WORKFLOW_CACHEABLE, including two more - the key -

fields: typeID and instID, as they are also used within the SIBFLPOR structure.

All classes that are being used within the SAP Business Workflow implementation inherit from here and implement the same CONSTRUCTUR signature.

Implementation the method BI_PERSISTENT~FIND_BY_LPOR method roughly as following:

 

Within such a centrally implementation object instantiation, one could also easily implement the functionality for system-wide delegation, as it was known with the BOR object implementation.

 

You'll need to fill in some gaps, like a DDIC structure for the cache table, but as this blog-post is mainly addressing experienced Workflow programmers, you'll know, how to fill the missing parts.

 

 

method BI_PERSISTENT~FIND_BY_LPOR.

**********************************************************************
*   Cache lookup for existing instance
**********************************************************************

    FIELD-SYMBOLS: <ls_instance> LIKE LINE OF gt_instances_base.

    READ TABLE gt_instances_base ASSIGNING <ls_instance>
                                 WITH KEY typeID   = lpor-typeID
                                          objectID = lpor-instID
                                 BINARY SEARCH.
    IF sy-subrc <> 0.

**********************************************************************
*   Instantiation of a new object
**********************************************************************

       DATA: lo_instance_object  TYPE REF TO ZCL_WORKFLOW_CACHEABLE,
             lv_objectID         TYPE SIBFINSTID.

       lv_objectID = lpor-instID.

       CREATE OBJECT lo_instance_object TYPE (ls_lpor-typeID)
                     EXPORTING
                        iv_objectID   = lv_objectID
                        iv_do_refresh = gc_true.          "Indicator to perform full database selection upon creation

       result ?= lo_instance_object.

       add_instance_to_cache( lo_instance_object ).

    ELSE.

**********************************************************************
*   Retrieving and assigning result from instance cache
**********************************************************************
       result ?= <ls_instance>-instance.

    ENDIF.

endmethod.

 

 

This was the most important algorithm. However you'd need some more small methods around it. One is to add an object to the cache, and another helpful one is, to check, if an object is already cached. The third one was to implement the BI_OBJECT~RELEASE method, as well.

 

The adding to the cache is done centrally to ensure the correct sorting. Be aware that the internal table may grow, when many instances are being processed. So a few thousand entries could be possible.

 

 

method ADD_INSTANCE_TO_CACHE.

    "Check on cache existence first, as the constructor of the class
    "may have added itself to the cache already to avoid endless loops
    READ TABLE gt_instances_base TRANSPORTING NO FIELDS
                                 WITH KEY typeID   = io_instance->ms_lpor-typeID
                                          objectID = io_instance->ms_lpor-instID
                                 BINARY SEARCH.
    IF sy-subrc <> 0.

       DATA: ls_instance       LIKE LINE OF gt_instances_base.

       ls_instance-typeID   = io_instance->ms_lpor-typeID.
       ls_instance-objectID = io_instance->ms_lpor-instID.
       ls_instance-instance = io_instance.

       APPEND ls_instance TO gt_instances_base.
       SORT gt_instances_base
            BY typeID objectID.

   ENDIF.

endmethod.

 

 

A helper method to work with an explicit release.


method BI_OBJECT~RELEASE.
    "Delete from instance cache

    "There should only be exactly one typeID/objectID existing
    "in the instance cache table. But however, we need to be
    "absolutely sure to erase all traces here, so we loop to
    "find everything.

    "We can be sure now, as I have checked all references to ensure sorted table
    READ TABLE gt_instances_base TRANSPORTING NO FIELDS
                                 WITH KEY typeID   = ms_lpor-typeID
                                          objectID = ms_lpor-instID
                                 BINARY SEARCH.

    "Lookup oneself in the instance cache and remove here
    IF sy-subrc = 0. "Found
       DELETE gt_instances_base INDEX sy-tabix.
    ENDIF.

    me->release_instance( ).   "Method, which is to be redefined by subclasses to do their cleanup

endmethod.

 

 

And a last (public) method to give a calling report/functionality the opportunity to switch program flow if an object is already cached or not, without instantiating the object.

 

method IS_IN_CACHE.


    READ TABLE gt_instances_base TRANSPORTING NO FIELDS
                                 WITH KEY typeID   = is_sibflpor-typeID
                                          objectID = is_sibflpor-instID
                                 BINARY SEARCH.
    IF sy-subrc = 0.
       rv_in_cache = gc_true.
    ELSE.
       rv_in_cache = gc_false.
    ENDIF.


endmethod.

 

 

 

Any helpful comments are very welcome.

 

Take care

 

    Florin Wach

    Systems-Integration

    SAP Business Workflow Senior-Expert

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.

 

Layers

 

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.

 

Visibility

 

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.

 

Hope

 

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.

I am writing a blog series to help introduce you to some of the speakers you will meet at the ASUG Annual Conference this year.

 

He ain’t heavy, he’s my Mentor (OK, one of them)

You can attribute the above misquote to Boys Town, or the song by the Hollies.  The song was recorded in 1969, and in spite of the fact that I had two older brothers, I still have some fondness for the (somewhat cheesy, I will admit) lyrics. 

It's a long, long road
From which there is no return
While we're on the way to there
Why not share

 

 

This year at the ASUG Annual Conference (conveniently co-located with another SAP-related event, SAPPHIRE) I will have the pleasure to welcome back into the fold someone I’ve known for about 15 years.  

 

We first met in, oh, 1998 I believe, at one of the very first ASUG meetings of the Workflow group (now the Workflow/BPM group).  Alan was the SAP Product Manager for Business Process Technology at the time, and he knew all about all things Workflow.  Even more than that, Alan really enjoyed connecting with users and hearing about our problems, and listening to our wish-lists.  Back then, our meetings were not huge events; we could choose a hotel in some agreed-upon location (with concurrence from a number of ‘board’ members), work with ASUG HQ to arrange the meeting, and search for speakers.  But the events were small, intimate,  focused.  If you traveled to the Tapitio Pointe in Phoenix in September, you were there to learn Workflow. Period.  You can tell from this photo.


 

Alan always followed up our face-to-face meetings with nice newsletters (remember, there was no SDN or SCN in those days!).  I stumbled across one today, and wanted to share this cute image of SAPGUI  from back then...

 

No more complaints about SAPGUI these

days, OK?  At least now we have colors!

 

 

 

 

 

 

 

 

 

 

Alan stayed with Workflow until 2005 – after he and Jocelyn Dart completed what is now known (in the Workflow World) as ‘the bible’ – the ultimate guide to Workflow development from SAP-Press called ‘Practical Workflow for SAP’.  

There is a newer edition, but it was  their blood, sweat, and tears that produced the original!

 

 

He still maintains the site www.workflowbook.com so that must demonstrate his ever-lasting affection for the product


ASUGworkflowMentorAlanRickayzen.JPG

 

 

 

 

 

 

Still, I was devastated to learn that Alan was moving on to other technologies in 2005 (little did I know that I  would get another awesome point-of-contact in Ginger Gatling!) The group decided Alan should have a little memento of our time together.

 

 

 

 

 

 

 

 

 

 

This year, Alan returns to ASUG Annual Conference!

 

Alan will be discussing another technology – Operational Process Intelligence.  If there is one thing I have learned about (and from) Alan over the years, it’s that he really gets the challenges that businesses face, and he is passionate about solving them.  Operational Process Intelligence is built on Process Observer, and then accelerated and visualized in a manner which allows strategic and tactical decision making. Or, instead of using a map to see where your business should go, you now use a GPS, right?  When driving, you need to know what road hazards lie ahead, where there are traffic jams, but a map won’t show you that.  SAPOPInt is GPS for your business.

 

There are dozens of blogs on SAP Operational Intelligence on the SAP Community Network – so you can delve in to them in order to whet your appetite.  And then, come to Alan’s session Tuesday, May 14, at 12:30 PM.  The session number is 3902

 

 

More fun stuff...

Alan was a physics teacher in a previous life.  He made such an impression on at least one of his students, that 32 years later, the boy (now a man) sent him a note in 2012.  This year, they met up for the first time in years. 

An extract of the letter says:

I remember you gave me a feeling of appreciation. You treated me well. I started to enjoy your classes tremendously. Usually I finished the homework on the train; I lived on the other side of Hamburg in Bergedorf. Once I came home I started to write everything down neatly, so I could present a decent piece of homework. You made me feel really good, I started receiving sevens (excellent). What you probably didn’t realise is that due to your teaching and fantastic sense of humour I started getting better in the other subjects as well. I enjoyed learning and going to school.

 

Wow, that's quite a letter.  Alan was always ready to regale us with tales of his teaching days - so ask him if you get a chance!

 

He is also an avid supporter of the First Lego League, and I can only imagine how many kids have gotten the same benefit from Alan’s experience, charm, and natural teaching abilities.

http://scn.sap.com/people/alan.rickayzen/blog/2011/12/01/youd-better-watch-out-generation-fll-is-on-its-way-lego-rules

 

I guess he just never stops teaching in some way - check this using Facebook for Project Managment? 


I hope you will come to Alan's session on SAP Operational Intelligence - you will also find him in some of the other WF/BPM sessions at the ASUG conference.

You can follow Alan on Twitter at @alanrick or challenge him to a game of bridge online alanrick (bbo ID).  That's his newest hobby!

No, that does not mean a Kiss By an Associate.  Or a Kick-Back Afternoon.  I mean a Knowledge-Based Article.

 

I had an issue with a workflow that was running happily for 10 years.  Then we applied support packs, and it started failing occasionally.  The event would be raised, but the object key (PERNR in this case) was blank.


Although my first thought was ‘Hmmm, occasional failures?  It must be a timing issue’ I was able to reproduce the problem in the Dev system, and that was one good thing (don’t you hate it when you can’t reproduce the problem???) The not-so-good thing was that it was caused by a sequence of transactions in HR – which I am assuming is pretty well customized. I have to assume this as I have never worked on a different HR system.


What happened was, in a certain order of events, a custom HR event was raised – correctly, when it should have been – but without any object key. Of course, workflows have a very hard time if they don’t have an object to work on. 


This was quite frustrating, as the HR processes that caused this to occur had to be executed exactly as the HR folks did it.  And they had the benefit of the passage of time (as well as intimate familiarity with the transactions) whereas I, once I started debugging, had to recreate the situation over and over again.

I searched OSS notes, and I searched SCN.  First I tried general terms (why not hope for a quick solution?) such as SWEHR3, HR Events, BUS1065.  And then, as time went on, and I got deeper into debugging, I was searching on various tables, HR event functions, and SWW* and SWE* functions.  I tried deleting the event and re-adding it (hey, it’s worked before, for someone, right?). 


I came across an OSS Note which kind of, sort of, in a vague way looked as though it might apply.  At least, I knew we did not have the note already in our systems.  We applied the note, and boom!  The problem was gone.  When I asked  The Fabulous Eddie Morris if he could enhance the description to this note so it would be easier to find, he referred me to a Knowledge-Based Article (otherwise known as a KBA).

So here’s how it started out:


 

Well, yeah, now that I can see it, it makes pretty good sense.  It’s not exactly what I was experiencing, but it was darned close. 

 

 

So here’s the thing. Although I have known about KBA’s for a while, and even read some, I had sort of forgotten about them.  And yes, while knowing about that specific KBA after-the-fact is great, I can’t be sure I would have zoomed in on it earlier in my searches. 

 

But there is a possibility that the information I required was in a Knowledge Based Article, so don’t overlook this important source of information.  If you see the little yellow asterisk the next time you are doing a note search, maybe you should click on THAT first – in addition to having a little more language in them than your typical SAP Note, you might notice some kind of key phrase, like ‘after updating your Basis Support Pack or Upgrading’.  If I had done that, I would have found the corresponding note much more easily!

 

So, what KBAs have you come across lately?  Care to share your story?

Here are ten more common mistakes made by SAP workflow beginners. An earlier blog discussing the numbers #1 - #10 can be found here.

 

Have a laugh at my missteps, and make sure you don't repeat them!

11. BOR: Referencing Z subtypes instead of the supertype

 

This has to be the most common beginners' mistake, and yet is perfectly understandable.

 

If you delegate a BOR object (say BUS1006 - business partner) to a sub-object ZBUS1006, you should still always refer to 'BUS1006' in your workflows, tasks and event linkages.

 

That's right: 'ZBUS1006' should ONLY be used while creating the BOR object and setting up a subtype.

 

Otherwise: nunca / never / nimmer / niemals / aldrig / jamais!

 

event linkage.jog.JPG

Don't do this

 

Here are some of the reasons:

  • when you search for workflow instances that use object BUS1006, you now have to also search for ZBUS1006
  • when you see an explicit reference to a Z* object, you don't know if it has been copied or subtyped
  • it also presents difficulties when searching through an alphabetical list of events (Z* is a long way from B*)
  • if you only ever refer to 'BUS1006', you can easily switch to a new subtyped object (e.g. ZBUS1006V2) and your workflows won't miss a beat..

 

12. Not catering for all outside events

 

This is a blunder I have made many, many times. Just because you have built a great workflow for approving (say) leave requests, this doesn't mean that users will instantly change their habits. No, they will still get desk visits, and they will still approve the leave request through the old SAP transaction.

 

If your workflow doesn't recognize that this has happened, then you have a big problem. Users will ring, asking you why they have to approve something twice; or the workflow will go into error when it tries to change a request that is already approved.

 

So you need to consider all possible terminating events - 'Approved', 'Withdrawn', 'Changed', 'Deleted' etc.

 

Functional specifications rarely mention these scenarios, so it's up to you to include them.

 

 

13. Not setting deadlines based on the factory calendar

 

When a business analyst specifies that they want a reminder sent after 5 days, they usually mean 5 working days - weekends and holidays don't count. It seems obvious, but is often missed.

 

To implement this you need to specify the use of a factory calendar in your workitem deadlines.  The workflow book shows you how.

 

calendar.jpg

Copyright (c) 123RF Stock Photos

 

 

Even if your business runs 24/7, it still pays to use a factory calendar to cover all eventualities - e.g. future changes or Christmas shutdowns.

 

Be careful though - if you choose a custom factory calendar make sure it is correct and maintained well into the future. Otherwise - as reported in SCN - your workflows will stop dead when the calendar stops.

 

 

14. Over-complicated workflows

 

When I arrive at a new site, the first sign of trouble is a workflow definition that looks like a tangled ball of spaghetti.

 

chikatetsu.jpg

 

Pasta Chikatetsu (source: www.tokyometro.jp)

 

It's pretty rare that all this noise and fury is really needed to implement a mundane business process (such as PO approval).

 

Typically, such workflows contain:

  1. A string of container operation steps, which serve as ersatz initializations
  2. Numerous activity steps that do nothing more than call a method to 'get' a value (e.g. a user's email address)
  3. Unnecessary Sendmail steps
  4. A long list of workflow container elements that, really, are just object attributes
  5. A sprinkling of undefined steps (why oh why?)

 

undefined_step.JPG

Justify your existence

 

Does this sound like one of the workflows at your site? Here’s how to clean it up:

  1. Initializations: use the 'initial' tab on the workflow container element instead
  2. Use object attributes (as explained further in #12)
  3. Delete SendMail steps that simply warn the user of a workitem. Use Extended Notifications instead
  4. Again, use object attributes
  5. Delete delete delete!

 

And once you've done all that, consider trashing the whole thing.

 

In my experience, workflows are often built 'on the fly', as requirements are drip-fed or regularly changed. Once you finish the build, it's worth considering whether to redesign from scratch.

 

Why? I like to think of a workflow definition as a LEGO(tm) house, where the tasks/steps are LEGO(tm) blocks. It's no problem breaking it all down again, just to see if you can design something sleek and elegant using the same steps.

 

Simplicity is so underrated.

edsel.jpg

My first workflow

 

yaris.jpg

Small, sleek & reliable

 

15. Using 'get' methods instead of attributes

 

This item ties in with #14. It is a common mistake made by folks who are used to procedural programming and not so comfortable with OO concepts.

 

Does your workflow have a step called 'Get User Name', based on a method 'GetUsername', which fetches user data and stores it in a workflow container called 'Username'? Which is then bound to a task container element 'UserName', just so that it can be used in the workitem text?

 

Sounds just like a traditional ABAP program :-)

 

All this complexity can be avoided if you instead define a (virtual) attribute called 'Username' that is automatically populated when the ('UserID') object is instantiated. The workitem text can then just use ‘Userid.Username’.

 

 

Note: Of course, you have to use your judgement in this. If the determination of an attribute is very expensive, you may not want it executed every time an object is instantiated. In this case, a GET method might be the best approach.


 

 

16. Allowing multiple copies of the same workflow to be started for the same object/event

 

Very typical beginner's error. I can't believe we didn't put this in the top 10.

 

You create a workflow for approving changes to a PO. It gets triggered when they change a field from 'Ted' to 'Fred'. But should another 3 workflows be triggered if (before approval is granted) 'Fred' then becomes 'Ned', then 'Ed' and finally 'Mildred'? Uh, no. Users hate this; which one should they approve?

 

You could set a 'check function' on your event linkage, so that no new workflow is started if an active workflow already exists for the same object. Or, when a change occurs, raise an event to terminate the existing workflow and start a new one.

 

 

17. Panicking when you see 'No Agent Available' in the workflow log

 

Don't worry - it doesn't mean that the workitem can't find an agent. It just means that no one has started processing this dialog workitem yet.

 

Perhaps a better translation from the German would be 'Not yet started' or 'Waiting to be processed'.

 

no agent.JPG

 

18. Using dummy wait steps of arbitrary length

 

Some workflows are punctuated with wait steps - dummy steps that call a dummy method that has an ABAP statement like WAIT UP TO 100 SECONDS in it.

 

Apart from being inelegant, you should question why a 'wait' is required and whether 100 SECONDS is long enough. Or perhaps too long. Wouldn't that depend on how busy the system is? And might it not change over time?

 

Typically a 'wait' step is inserted because you need a process to finish before you can continue - for example, the business partner has to be fully created before we can change it. In cases like this, a 'wait for event' step might be more appropriate.

 

Another option - e.g. in locking scenarios - is to use temporary exceptions.

 

 

19. Paying lip service to OO design

 

I sigh loudly when I see custom events with names like 'StartApprovalWorkflow'.  That name does not describe a real 'event' in the life of a assessment document.  (And it leaves open the mystery of where this event might be raised...)

 

In contrast, here are some real-life object events: CREATED, CHANGED, REJECTED. If you want to start an approval workflow, you should figure out which event(s) should trigger it, not invent a bogus one purely for workflow purposes.

 

For example, if an assessment needs approval when it's CREATED or CHANGED, then you can simply link the approval workflow to these two events (via SWE2).

 

Similarly, the methods of an object should represent ACTIONS on that object. Don't shoehorn a 'Sendmail' method onto a SalesOrder object, just because you can!

 

 

20. Developing custom programs to change workflows / workflow containers

 

This chimera comes up fairly regularly in SCN - a misbegotten idea to write a report that will automatically approve / forward / obsolete some outstanding workitems. That's bad enough, but much much worse are programs that seek to 'pop the bonnet*' and directly update container values from outside the workflow.

Good luck trying to understand your workflow log, once programs like that start messing with it!

 

If you feel you have to resort to such measures, then you probably need to study up on workflow features and design principles. Pretty much all of the above can be handled through modelled deadlines or terminating events.

 

geniet!

Paul Bakker

 

*North American readers might say ‘pop the hood’

This SAP workflow blog – the third in an overly-ambitious series – spotlights the top 10 mistakes made by workflow beginners (aka ‘noobs’).  I can truly call myself an expert in this area, because I’ve probably done them all!

 

1. Trying to muddle through workflow using just your ABAP skills

 

I got my start in workflow back in 2004 when our 'workflow guy' left suddenly, just before an R/3 implementation go-live.

 

I confidently volunteered to take over, expecting to use my ABAP skills to ‘debug’ the workflow log and figure out how it all fit together. Ridiculous of course - I'd have more luck dissecting a cat. Within 2 weeks I had booked myself on an (excellent)  1-week SAP workflow course run by Paul Batey.  And then the scales lifted from my eyes.

 

I realised that workflow is more about 'concepts' and 'configuration' than it is about 'code'. Do not attempt to mess with it if you haven't done the SAP course (or at least partly digested the Workflow Book).

 

2. Confusing workitems with emails

 

A very common conceptual  error. Put simply, a workitem is a single piece of work - typically a decision task - that can be viewed from multiple inboxes, and disappears as soon as one agent processes it. Workitems can only be sent to SAP system users.

 

In contrast, emails are typically flat information items. Multiple copies are made and sent separately to inboxes. They remain in each person’s inbox until individually read or deleted. Emails can be sent to anyone.

 

3. Not executing SWU_OBUF before testing your workflow changes

 

I sometimes hear that workflow is 'flaky' or 'unpredictable'. And it certainly is - if you have no understanding of how buffering works.  But don't worry: you only need to remember to run transaction SWU_OBUF before executing a workflow that has been changed.

 

This applies during development, but also in Test or Production systems after a workflow has been transported in. The whole buffer is refreshed at midnight.

 

4. Flooding users' inboxes with hundreds of workitems

 

I’ve learnt the hard way that not all approval / decision processes are suited to workflow.  If hundreds of items are generated per day for one process, it's probably better to handle them via a report instead.

 

It may just be a psychological thing, but users react violently to inboxes that they can't possibly clear (often compounded by a torrent of reminder emails).  They either stop using their inboxes completely or clamour to get the workflow switched off.  No news is better than a tsunami of bad news.

 

flooded inbox.jpg

 

Copyright (c) 123RF Stock Photos

 

 

 

5. Not changing the default 'Receiver error feedback' setting in SWEQADM

 

If you start a workflow via an event, and something goes wrong  (e.g.  a mandatory parameter is missing), the default  SAP response is to deactivate the linkage between the event and workflow. 

 

Yes, you read that right; and yes, it is DISASTROUS. Any subsequent events are lost forever, until you realise what happened. Then you have to scramble to fix the problem, transport it to Production, and reactivate the linkage.

 

In SWEQADM, the setting should instead be 'Mark linkage as having errors'. This means that the linkage will not be cut, and the events will be stored until they can be safely delivered later.

 

sweqadm.jpg


Jocelyn D. explains it all perfectly here .

 

6. Starting workflows directly from a program, instead of using events

 

I have visited many sites where WS* workflows (and even TS* standard tasks!) are started directly by a call to SAP_WAPI_START_WORKFLOW. Bzzzt. It is far better to trigger workflows using events.

 

There are millions of reasons for this, but at the moment I can only think of five:
- you can easily switch a workflow on/off (even in Production) by (de)activating the event linkage
- you can easily switch from an old workflow to a new one, by manipulating the event linkage
- you can choose new workflows to be started by the same event
- if a workflow doesn't start for some reason, you can examine the event log (SWEL)
- there are no authorization issues with starting workflows

 

7. Falling behind in the housekeeping

 

It is wrong to assume that if users are not reporting any problems, then the workflows must be humming along. You have to be proactive and go out looking for errors, especially when a new workflow goes live.

 

We reckon there should be zero tolerance for SWI2_DIAG errors. At some sites we have found hundreds of them, and dozens (re)occurring every day! Transaction SWI2_DIAG should not be considered a tool for error handling, but a bucket of last resort.

 

 

bin.jpg

 

Copyright (c) 123RF Stock Photos

 

Go ahead now: check SM58, SWI2_ADM1, SWI2_DIAG, SWEQADM and SWEL.

 

 

8. Using internal function modules (and tables) instead of SAP_WAPI*s

 

A common question posed on SCN runs along the lines of: what table holds the workflow container values? Who has sample code for function SWE_EVENT_CREATE?  Bzzzt  (again). Developers should not be messing with internal SAP function modules or tables. These could be changed on the next release, which means your code may stop working.

 

Instead, use a WAPI. These are the SAP workflow equivalent of BAPIs: function modules that provide a documented service, with an interface that is guaranteed not to change. For example: SAP_WAPI_CREATE_EVENT, SAP_WAPI_READ_CONTAINER, SAP_WAPI_GET_WI_AGENTS.

 

9. Not putting enough information in the workitem text

 

The three ‘R’s of workflow are that work lands on the desk of the ‘right’ person at the ‘right’ time, and that all the information they need to make a decision, is ‘right’ there at their fingertips.

 

For example, when approving a leave request, the supervisor might need to know the employee details, their current leave balance, team  leave requests for the same period, and so on.

 

A good workitem text contains all – yes all - of this information.  The user shouldn’t need to go anywhere or click anything. (Tip: using webdynpros to render workitems makes rich displays a lot easier). 

 

leave workflow.JPG

A comprehensive leave approval workitem

 

If that all seems a bridge too far, at the very least provide hyperlinks to all the relevant business objects.  This means the information is only one click away.

Too often I see workitems with telegraph-style texts like: ‘Please approve leave request #45 for USRICKB’. The poor users are left to track down the details on their own, causing frustration and delay.

 

10. Agreeing to develop custom workflow reports

 

This is one of my pet hates.  We get called in to ‘fix the workflows’ and it turns out that the main problem is actually with a dodgy workflow report .

 

In almost every project, managers request a ‘Z’ report so that they can track the progress of (say) a PO through the approval process. They want to know: Who has it in their inbox now? How long is it taking?

 

If you, as a workflow developer, cave in to these requests, you will soon be up to your armpits in Z tables and update BADIs. But all this pain adds no value at all.

 

I try to push back and demonstrate that all the reporting they need is covered by GOS, SWLO, SWI1, SWI2_FREQ and (for more detailed analyses), BI. Once familiar with these tools, they can use them for reporting on any workflow.

 

 

I probably have a few more of these and will put them in a blog later. Please share some of your own pet hates.

 

Happy workflowing!
Paul Bakker
Hanabi Technology

 

PS Here's a followup blog, listing another 10 common mistakes:

http://scn.sap.com/community/bpm/business-workflow/blog/2013/02/25/more-common-mistakes-made-by-workflow-beginners

Filter Blog

By author:
By date:
By tag: