Flexible Serialization in SAP PI

Let us start by defining what strict serialization is - Serialization during message processing is a feature by which messages are delivered to the target in the same sequence as generated by the source via a middleware.

The quality of service defined for the same in EOIO (Exactly Once in Order).

Serialized messages are processed in a specified queue both on the middleware and the target system. In case of a processing error on any particular message in the queue, the message queue gets blocked; all subsequent messages go on a wait state, till the error is resolved.

Some implementations have a unique requirement for Flexible serialization. In this case, there is a need of serialization of messages and in case of error the other messages can continue, staying serialized, ignoring the failed one which can be attended manually at a later point of time.

The following are the advantages of flexible serialization.

1.  The message processing remains serialized in majority of error-free cases.

2.  The message processing for an interface does not halt due to the failure in one message on the queue.

3.  An error notification, informs the support team of the failure and the subsequent manual action can be performed by them.

It should be noted, that Flexible Serialization is implemented only in cases where, the percentage forecast for failures in less, and manual re-conciliation is possible.

SAP PI, like most middleware systems does not support this out of the box.  A simple WATCHER report can be written based on QRFC APIs in PI and connected ABAP Based SAP systems to achieve the same.  The purpose of this watcher program would be to move the error message out of the active LUW SMQ2 to a saved LUW SMQ3 for all queues requiring Flexible serialization.

The following would be the details of the watcher operation.

1.  Watcher to Monitor all specified Serialized queues on SMQ2

2.  The Watcher looks for specific failure statues like SYSFAIL or CPIC

3.  Upon determination of an error the watcher checks for the message depth on SMQ2 (running/active LUW). . The business team can define the active queue depth,  for flexible serialization to work

4.  The watcher also looks at the depth on the saved queue or SMQ3. This would be important to prevent message movement if there is a generic issue on the interface, which can impact every flowing message.

5.  The watcher based on the above parameters would then move the message to SMQ3.

6.  Finally an alert notification should be send out to the respective users, specifying the movement.

The following is a selection screen.

Selection Screen

The following is the code snippet for the same.

<!--StartFragment --> TYPE-POOLS: salrt.
* Get all errored inbound queues
TABLES: trfcqin.
SELECT-OPTIONS: s_qname FOR trfcqin-qname,
                s_eqname FOR trfcqin-qname,
                s_qstate FOR trfcqin-qstate,
                s_iqname FOR trfcqin-qname.
PARAMETERS: p_pdf AS CHECKBOX DEFAULT 'X',
            p_qdepth TYPE int4,
            p_sqdep TYPE int4.
DATA: v_err_qs TYPE sy-tabix,
      v_err_qss TYPE string,
      v_err_msg(200) TYPE c,
      v_msg TYPE string,
      v_trfcmess TYPE t100-text,
      v_qstate TYPE trfcqin-qstate,
      o_cont TYPE  REF TO if_swf_cnt_container,
      o_err TYPE REF TO cx_root,
      w_qin TYPE trfcqin,
      w_qstate TYPE trfcqstate,
      w_tid TYPE arfctid,
      t_no_pdf_cont TYPE soli_tab,
      t_qin TYPE TABLE OF trfcqin,
      t_qstate TYPE TABLE OF trfcqstate,
      v_q_deep TYPE sy-index,
      ls_message TYPE zsca_string,
      lt_message TYPE zttca_string,
      lt_qview TYPE TABLE OF  trfcqview,
      ls_qview LIKE LINE OF lt_qview.
*CONSTANTS: C_INT_ID TYPE ZOBJID VALUE 'ECC_BLOCKED_QUEUES'.
START-OF-SELECTION.
*Identify the queues
  CALL FUNCTION 'TRFC_QIN_GET_ERROR_QUEUES'
    EXPORTING
      client      = sy-mandt
      with_qstate = 'X'
    TABLES
      qtable      = t_qin
      qstate      = t_qstate.
  DELETE t_qin WHERE NOT qname IN s_qname.
*  DELETE T_QIN WHERE QNAME IN S_IQNAME.
  IF NOT s_qstate[] IS INITIAL.
    LOOP AT t_qin INTO w_qin.
      CLEAR: v_qstate.
      CALL FUNCTION 'TRFC_QIN_STATE'
        EXPORTING
          qname                   = w_qin-qname
        IMPORTING
          qstate                  = v_qstate
*         QLOCKCNT                =
          qdeep                   = v_q_deep
*         QRESCNT                 =
*         WQNAME                  =
*         ERRMESS                 =
*       EXCEPTIONS
*         INVALID_PARAMETER       = 1
*         OTHERS                  = 2
                .
      IF sy-subrc <> 0.
      ENDIF.
      IF  v_q_deep < p_qdepth.
        DELETE t_qin.
      ELSE.
        CHECK NOT v_qstate IS INITIAL.
        CHECK v_qstate NOT IN s_qstate.
      ENDIF.
    ENDLOOP.
  ENDIF.
*   * Move the first LUW to the saved queue
  LOOP AT t_qin INTO w_qin.
    CLEAR: w_tid.
    CALL FUNCTION 'TRFC_QINS_OVERVIEW'
      EXPORTING
        qname  = w_qin-qname
        client = sy-mandt
      TABLES
        qview  = lt_qview.
    READ TABLE lt_qview INDEX 1 INTO ls_qview.
    IF ls_qview-qdeep < p_sqdep.
      CALL FUNCTION 'TRFC_QIN_GET_FIRST_LUW'
        EXPORTING
          qname                   = w_qin-qname
          client                  = sy-mandt
*     NO_READ_LOCK            = ' '
       IMPORTING
         tid                     = w_tid
*     QSTATE                  =
*     WQNAME                  =
          errmess                 = v_trfcmess
*     FDATE                   =
*     FTIME                   =
*     FQCOUNT                 =
*     SENDER_ID               =
*   TABLES
*     QTABLE                  =
       EXCEPTIONS
         invalid_parameter       = 1
         OTHERS                  = 2
                .
      IF sy-subrc <> 0.
* MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
      ELSEIF w_tid IS NOT INITIAL.
*      IF NOT S_EQNAME[] IS INITIAL AND W_QIN-QNAME IN S_EQNAME.
*        WRITE: / '*', AT 3 W_QIN-QNAME, AT 40 W_TID, AT 70 V_TRFCMESS.
*        CONTINUE.
*      ENDIF.
        SUBMIT rstrfcdk AND RETURN WITH tid = w_tid.
* Activate the QIN scheduler for this queue.
        CALL FUNCTION 'QIWK_SCHEDULER_ACTIVATE'
          EXPORTING
            qname = w_qin-qname.
        WRITE: / w_qin-qname, AT 40 w_tid, AT 70 v_trfcmess.
      ENDIF. 

The above queue movement should be notified to the business user, with the help of any alerting mechanism.

SAP Developer Network SAP Weblogs: SAP Process Integration (PI)