Wednesday, March 28, 2012

Fighting problems of asynchronous processing in ABAP


In most Standard SAP applications, changes to data are not directly (“synchronously”) written back to the database. Instead, SAP Netweaver buffers these changes and writes them at a later time (“asynchronously”).


On many occasions, you won’t notice this asynchronous nature and it won’t cause any problems. Even better, asynchronous processing is good for performance! However, sometimes you’ll want to continue processing only when the database is completely up-to-date. For example:

  • When you are trying to get additional data not returned by the BAPI or Function Module you just called;
  • When you want to run another BAPI or Function Module that depends on the database being completely up to date after the previous call.

Especially in interface programming, I have seen some cumbersome solutions. The good news is: There are good solutions to enforce synchronous processing. This post lists these options.

The bad solution

During development or even during testing,  some developers notice the asynchronous behaviour and try to fight it - with varying success. One approach I have seen (and even used myself!) is to use a WAIT statement to let the program in the current work process sleep for several seconds:


* Step 1: Call your functions and BAPI’s
CALL FUNCTION 'BAPI_OUTB_DELIVERY_CHANGE'
   DESTINATION 'NONE'
     EXPORTING
       header_data    = ls_header_data
       header_control = ls_header_control
       delivery       = lv_bapi_delivery
     TABLES return    = lt_return.
* Step 2: Wait for some period of time that you see fit
WAIT UP TO 15 SECONDS.
While this example functions, there are some serious downsides to this ‘solution’:

  • Rather than changing the processing mode itself, it is fighting a symptom of asynchronous processing;
  • It is difficult to decide how long you should wait. A time interval that is long enough on your oversized development system, might be too short on your crowded production system.
  • The performance of your system and the overall user experience goes down the drain as the current process becomes unresponsive and waits for a period that is almost certainly far too long.

The good Solutions

The following solutions can be successful in changing an asynchronous processing mode to a synchronous processing mode:

Solution 1: Set Update task local

By using the SET UPDATE TASK LOCAL statement, SAP Netweaver executes database updates in the current work process instead of a separate background process. Then, by using the COMMIT WORK statement, you force all updates in the current process to finish before continuing.


* Step 1: Set all update task to the local session
SET UPDATE TASK LOCAL.
* Step 2: Call your functions and BAPI’s
CALL FUNCTION 'BAPI_OUTB_DELIVERY_CHANGE'
    EXPORTING
      header_data    = ls_header_data
      header_control = ls_header_control
      delivery       = lv_bapi_delivery
    TABLES return    = lt_return.
* Step 3: Commit the changes locally
COMMIT WORK AND WAIT.
In most situations, all databases updates are finished after this point.

Solution 2: Execute in a separate session

Using a two-step approach it is possible to achieve synchronous processing:

  • Force the execution of a Function Module or BAPI in a new, separate session.
  • Explicitly close that session so that all relevant database commits are actually triggered before continuing.

The following code demonstrates this strategy for a standard BAPI:
* Step 1: Create a separate session. This is done by calling
* your BAPI or Function Module from remote destination ‘NONE’
CALL FUNCTION 'BAPI_OUTB_DELIVERY_CHANGE'
  DESTINATION 'NONE'
    EXPORTING
      header_data    = ls_header_data
      header_control = ls_header_control
      delivery       = lv_bapi_delivery
    TABLES
      return         = lt_return.
* Commit the changes within this session
CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
  DESTINATION 'NONE'
    EXPORTING wait = 'X'.
* Step 2: Explicitly close the session.
* Main effect: All commits of all work processes in the
* the remote session will executed
* Side effects:
* -A next RFC call will be started in a new session.
* -This resets the globals data in the function group.
CALL FUNCTION 'RFC_CONNECTION_CLOSE'
  EXPORTING destination = 'NONE'
  EXCEPTIONS OTHERS = 0.
It is necessary to use the BAPI_TRANSACTION_COMMIT Function Module instead of the regular COMMIT WORK AND WAIT statement. This is because the COMMIT has to take place in the ‘remote’ work process and not in the local process.


Again, after this point, all database updates are finished.

1 comment:

  1. Great article Wilco.........Very informative

    ReplyDelete