Skip to end of metadata
Go to start of metadata

List of all pages

Pages at first level

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
METHOD if_mapping~execute.
  DATA:
    hex TYPE x,                                   "1-byte hex variable
    text.                                         "1-character text variable
  result = source.                                "input-parameter source unchangeable, copy to result export-parameter
  hex = result.                                   "get first byte
  text = result.                                  "get first character
  WHILE hex = '00'                                "check byte is NUL
     OR text IS INITIAL.                          "check character is space
    SHIFT result IN BYTE MODE.                    "shift result left
    IF xstrlen( result ) = 0. EXIT. ENDIF.        "stop processing when hex string is empty
    hex = result.                                 "get next byte
    text = result.                                "get next character
  ENDWHILE.
ENDMETHOD.                    "IF_MAPPING~EXECUTE

Check Blog SAP XI/PI: Alerts for Queue Errors for complete end-to-end scenario.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
REPORT z_queue_alert.

DATA: z_qview_inb LIKE trfcqview OCCURS 1,
      z_qview_oub LIKE trfcqview OCCURS 1,
      z_qview LIKE trfcqview OCCURS 1,
      wa_qview LIKE LINE OF z_qview_oub,
      z_it_container LIKE swcont OCCURS 1,
      wa_it_container LIKE LINE OF z_it_container,
      lcl_car TYPE char4,
      lcl_dir TYPE char10.

CALL FUNCTION 'TRFC_QIN_OVERVIEW'
  EXPORTING
    qname  = '*'
    client = sy-mandt
  TABLES
    qview  = z_qview_inb.

CALL FUNCTION 'TRFC_QOUT_OVERVIEW'
  EXPORTING
    qname  = '*'
    dest   = '*'
    client = sy-mandt
  TABLES
    qview  = z_qview_oub.

IF NOT z_qview_inb IS INITIAL.
  lcl_dir = 'INBOUND'.
  PERFORM createalert TABLES z_qview_inb.
ENDIF.
IF NOT z_qview_oub IS INITIAL.
  lcl_dir = 'OUTBOUND'.
  PERFORM createalert TABLES z_qview_oub.
ENDIF.

*&---------------------------------------------------------------------*
*&      Form  CREATEALERT
*&---------------------------------------------------------------------*
FORM createalert TABLES i_qview LIKE z_qview.

  LOOP AT i_qview INTO wa_qview WHERE qstate EQ 'SYSFAIL'.

    wa_it_container-element = 'ZQUEUE'.
    wa_it_container-elemlength = '70'.
    wa_it_container-type = 'C'.
    wa_it_container-value = wa_qview-qname.

    APPEND wa_it_container TO z_it_container.
    CLEAR wa_it_container.

    wa_it_container-element = 'ZQUEUE_NO'.
    wa_it_container-elemlength = '10'.
    wa_it_container-type = 'C'.
    WRITE wa_qview-qdeep TO lcl_car.
    wa_it_container-value = lcl_car.

    APPEND wa_it_container TO z_it_container.
    CLEAR wa_it_container.

    wa_it_container-element = 'ZDIR'.
    wa_it_container-elemlength = '10'.
    wa_it_container-type = 'C'.
    wa_it_container-value = lcl_dir.

    APPEND wa_it_container TO z_it_container.
    CLEAR wa_it_container.

    wa_it_container-element = 'ZERROR'.
    wa_it_container-elemlength = '73'.
    wa_it_container-type = 'C'.
    wa_it_container-value = wa_qview-errmess.

    APPEND wa_it_container TO z_it_container.

    CALL FUNCTION 'SALERT_CREATE'
      EXPORTING
        ip_cat                 = 'QUEUE_ERR'
      TABLES
        it_container           = z_it_container
      EXCEPTIONS
        alert_category_unknown = 1
        alert_no_recipients    = 2
        alert_error_unknown    = 3
        OTHERS                 = 4.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
      WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.

    CLEAR: wa_it_container, z_it_container.

  ENDLOOP.

ENDFORM.                    "CREATEALERT
{      try
       {                 Thread.sleep (40000);        }

 
       catch (InterruptedException ie){}

      return a;
}

Thread.sleep will stop the processing of mapping for the given period of time. We need to provide the required time delay in the bracket as shown in code snippet. (40000). The time is in milli second. (40000) will give you the result after 40 sec.
I have used the try catch block to catch the thread exception.
We can use this UDF in between the main nodes to insert the delay. This is a small thing but very useful.

Author: Bersani Francesco
Submitted: 10 sept 2008
Related Links:

Abap report to automatically apply 1172942 note.

During the upgrade procedure from of XI/PI Netweaver 2004/s to PI 7.1 you have to apply the Note 1154961 - Checks to be executed before ESR/PI Upgrade to 7.1 and perform the checks using http://<server>:<port>/<appln>/support/CheckService.
If some inconsistent directory objects are present Note 1172942 - Resolve db inconsistencies before starting XI upgrade shows how to proceed in detail for each object type.
Since each inconsistent object must be adjusted executing a SQL insert query direclty on the database the report i'm presenting could be very useful and precius to prevent errors and above all loose to much time executing queries. Inconsistent repository object are automatically adjusted by the checkservice as described in the note.

The report will automatically execute all the insert queries for each inconsistent object. To do that the starting point is a csv file containing the complete list of all inconsistent object version ids and their object type. You can get this list from the result list executing ttp://<server>:<port>/<appln>/support/CheckService.

The file must have a structure like the following structure:

OBJECT_TYPE;VERSIONID

Here an example:

Channel;1d8c1d60-462f-11da-808e-00306e4ab473
DirectoryView;8c849f90-6a63-11db-8769-000f203ca29e
DOCU;8f813dc1-6a63-11db-89aa-000f203ca29e
MappingRelation;5aa76dd0-5a70-11da-c4e5-00306e4ab473
Party;87d8a3b0-74d9-11dd-c561-0019bbeb0ede
RoutingRelation;31650501-a3d0-11da-ce42-00306e4ab473
Service;d5b29940-55ee-11da-c44a-00306e4ab473

The report is developed to run just for Oracle databases, and it hasn't been tested with any other database engine.

It's very important that before running the report the db user SAP<SID> has granted the access to XI tables for SELECT and INSERT executing the following commands on the Oracle database with SQLPLUS:

grant select on SAP<SID>DB.XI_DIRDATAADMIN TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEYBINDING TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEY_RD_RELAT TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEYSERVICE TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEYPARTY TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEYCHANNEL TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEYNAME TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEY_DIR_VIEW TO SAP<SID>
grant select on SAP<SID>DB.XI_DIRKEYMAPKIDET TO SAP<SID>

grant insert on SAP<SID>DB.XI_DIRDATAADMIN TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEYBINDING TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEY_RD_RELAT TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEYSERVICE TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEYPARTY TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEYCHANNEL TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEYNAME TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEY_DIR_VIEW TO SAP<SID>
grant insert on SAP<SID>DB.XI_DIRKEYMAPKIDET TO SAP<SID>

Additionally you've to create a synonym for each table name with the following commands:

create public synonym XI_DIRDATAADMIN for SAP<SID>DB.XI_DIRDATAADMIN
create public synonym XI_DIRKEYBINDING for SAP<SID>DB.XI_DIRKEYBINDING
create public synonym XI_DIRKEY_RD_RELAT for SAP<SID>DB.XI_DIRKEY_RD_RELAT
create public synonym XI_DIRKEYSERVICE for SAP<SID>DB.XI_DIRKEYSERVICE
create public synonym XI_DIRKEYPARTY for SAP<SID>DB.XI_DIRKEYPARTY
create public synonym XI_DIRKEYCHANNEL for SAP<SID>DB.XI_DIRKEYCHANNEL
create public synonym XI_DIRKEYNAME for SAP<SID>DB.XI_DIRKEYNAME
create public synonym XI_DIRKEY_DIR_VIEW for SAP<SID>DB.XI_DIRKEY_DIR_VIEW
create public synonym XI_DIRKEYMAPKIDET for SAP<SID>DB.XI_DIRKEYMAPKIDET

Here the source code of the report:

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  Z_APPLY_NOTE1172942
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*


PARAMETERS:
  p_fname LIKE  rlgrap-filename OBLIGATORY  DEFAULT 'C:\inconsistencies.csv',
  p_test AS CHECKBOX DEFAULT 'X'.


CONSTANTS:
  c_x(1)     TYPE c VALUE 'X',
  c_csv(4)   TYPE c VALUE '.CSV',
  c_numbers(10) TYPE c VALUE '0123456789',
  c_trans(4) TYPE c VALUE '(-) '.

* Int. table to keep PC file records
DATA: BEGIN OF it_struct OCCURS 0,
        object_name(32)  TYPE c,
        version_id(38)  TYPE c,
      END OF it_struct.


DATA: lw_ib_object LIKE it_struct.
DATA: lt_ib_object LIKE it_struct OCCURS 0.

* Declare type for table with CSV-text line 1024 chars max (can change)
TYPES: type_raw_csv TYPE string OCCURS 0.

DATA: it_raw TYPE TABLE OF string.
DATA: lw_raw TYPE string.

DATA:
  m_error(1) TYPE c,
  m_msg(256) TYPE c.
***********************************************************************************************


INITIALIZATION.
  %_p_fname_%_app_% = 'File Name'.
  %_p_test_%_app_% = 'Test Mode, do not write'.



START-OF-SELECTION.


  DATA: l_counter TYPE i.
  DATA: l_missing_id TYPE i.
  DATA: l_missing_type_counter TYPE i.
  DATA: exc_ref    TYPE REF TO cx_sy_native_sql_error,
        error_text TYPE string.
  DATA: l_tmp_string TYPE string.

  PERFORM upload_csv_spreadsheet
    TABLES it_raw
    USING p_fname
    CHANGING m_error m_msg.

  LOOP AT it_raw INTO lw_raw.
    CLEAR lw_ib_object.
    CLEAR l_tmp_string.
    SPLIT lw_raw AT ';' INTO: lw_ib_object-object_name l_tmp_string.

*Convert to upper case and replace split
    TRANSLATE l_tmp_string TO UPPER CASE.
    REPLACE ALL OCCURRENCES OF '-' IN l_tmp_string WITH '' IN CHARACTER MODE.
    lw_ib_object-version_id = l_tmp_string.

    APPEND lw_ib_object TO lt_ib_object.
    ADD 1 TO l_counter.
  ENDLOOP.


  WRITE :/ 'Number of inconsistencies: ', l_counter.


  DATA: l_object_id(40) TYPE c.

*First check that all objects can be found in XI_DIR_DATAADMIN.
  LOOP AT lt_ib_object INTO lw_ib_object.
    TRY.
        CLEAR l_object_id.
        EXEC SQL.
          SELECT OBJECTID into :l_object_id from XI_DIRDATAADMIN  where VERSIONID = :lw_ib_object-version_id
        ENDEXEC.
      CATCH cx_sy_native_sql_error INTO exc_ref.
        error_text = exc_ref->get_text( ).
        MESSAGE error_text TYPE 'I' RAISING sql_error.
    ENDTRY.
    IF l_object_id IS INITIAL.
      WRITE : /  'OBJECTID is initial for: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
      ADD 1 TO l_missing_id.
    ELSE.
      WRITE : / 'OBJECTID found for: ' COLOR COL_POSITIVE,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
    ENDIF.
  ENDLOOP.

  IF l_missing_id NE 0.
    WRITE : / 'Missing OBJECTID for: ' COLOR COL_NEGATIVE,  l_missing_id , ' Objects'.
  ENDIF.


*Check objects for which no correction rule is available.
  LOOP AT lt_ib_object INTO lw_ib_object.
    CASE lw_ib_object-object_name.
      WHEN 'RoutingRelation'.
      WHEN 'Service'.
      WHEN 'Party'.
      WHEN 'Channel'.
      WHEN 'DOCU'.
      WHEN 'DirectoryView'.
      WHEN 'MappingRelation'.
      WHEN OTHERS.
        ADD 1 TO l_missing_type_counter.
    ENDCASE.
  ENDLOOP.


  IF l_missing_type_counter NE 0.
    WRITE : / 'Unmatching OBJECTNAME for: ' COLOR COL_NEGATIVE,  l_missing_type_counter , ' Objects'.
  ENDIF.


  IF p_test EQ 'X'.
    RETURN.
  ENDIF.
*******************************************************************************
* EXECUTION OF ADJUSTMENTS
*******************************************************************************

  DATA:
        l_dummy_sender_party_name(60) TYPE c VALUE 'DUMMY SENDER PARTY',
        l_dummy_sender_service_name(60) TYPE c VALUE 'DUMMY SENDER SERVICE',
        l_dummy_party_name(60) TYPE c VALUE 'DUMMY PARTY',
        l_dummy_service_name(60) TYPE c VALUE 'DUMMY SERVICE',
        l_dummy_interface_namespace(60) TYPE c VALUE 'DUMMY INTERFACE NSPACE',
        l_dummy_interface_name(120) TYPE c VALUE 'DUMMY INTERFACE NAME',
        l_dummy_receiver_party_name(60) TYPE c VALUE 'DUMMY RECEIVER PARTY',
        l_dummy_receiver_service_name(60) TYPE c VALUE 'DUMMY RECEIVER SERVICE',
        l_dummy_channel_name(60) TYPE c VALUE 'DUMMY CHANNEL',
        l_dummy_scenario_name(60) TYPE c VALUE 'DUMMY SCENARIO',
        l_dummy_name(60) TYPE c VALUE 'DUMMY NAME',
        l_dummy_namespace(60) TYPE c VALUE 'DUMMY NAMESPACE'.




  DATA: l_duplicate_counter TYPE  i.

  LOOP AT lt_ib_object INTO lw_ib_object.
    CLEAR l_duplicate_counter.
    CLEAR l_object_id.
*find the corresponding objects id
    TRY.
        EXEC SQL.
          SELECT OBJECTID into :l_object_id from XI_DIRDATAADMIN  where VERSIONID = :lw_ib_object-version_id
        ENDEXEC.
      CATCH cx_sy_native_sql_error INTO exc_ref.
        error_text = exc_ref->get_text( ).
        MESSAGE error_text TYPE 'I' RAISING sql_error.
    ENDTRY.
    IF l_object_id IS INITIAL.
      WRITE : /  'OBJECTID is initial for: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
      CONTINUE.
    ENDIF.


    CASE lw_ib_object-object_name.
* OUTBOUND BINDING ############################################################
      WHEN 'OutboundBinding'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYBINDING where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEYBINDING(OBJECTID, TYPEID, FROMPARTY, FROMSRVC, TOPARTY, TOSRVC, ACTIONNS, ACTIONNAME, DIRECTION) values
              (
                :l_object_id,
                'OutboundBinding',
                :l_dummy_sender_party_name,
                :l_dummy_sender_service_name,
                :l_dummy_receiver_party_name,
                :l_dummy_receiver_service_name,
                :l_dummy_interface_namespace,
                :l_dummy_interface_name,
                'O'
              )
            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

* INBOUND BINDING ############################################################
      WHEN 'InboundBinding'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYBINDING where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEYBINDING(OBJECTID, TYPEID, FROMPARTY, FROMSRVC, TOPARTY, TOSRVC, ACTIONNS, ACTIONNAME, DIRECTION) values
              (
                :l_object_id,
                'InboundBinding',
                :l_dummy_sender_party_name,
                :l_dummy_sender_service_name,
                :l_dummy_receiver_party_name,
                :l_dummy_receiver_service_name,
                :l_dummy_interface_namespace,
                :l_dummy_interface_name,
                'I'
              )
            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.


* ROUTING RELATION ############################################################
      WHEN 'RoutingRelation'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEY_RD_RELAT where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEY_RD_RELAT (OBJECTID, TYPEID, FROMPARTY, FROMSRVC, FROMACTIONNS, FROMACTION, TOPARTY, TOSRVC) values
              (
                :l_object_id,
                'RoutingRelation',
                :l_dummy_sender_party_name,
                :l_dummy_sender_service_name,
                :l_dummy_interface_namespace,
                :l_dummy_interface_name,
                :l_dummy_receiver_party_name,
                :l_dummy_receiver_service_name
              )
            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

* SERVICE #####################################################################
      WHEN 'Service'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYSERVICE where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEYSERVICE (OBJECTID, TYPEID, PARTY, SERVICE) values
              (
                :l_object_id,
                'Service',
                :l_dummy_party_name,
                :l_dummy_service_name
              )
            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

* PARTY #######################################################################
      WHEN 'Party'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYPARTY where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEYPARTY(OBJECTID, TYPEID, PARTY) values
              (
                :l_object_id,
                'Party',
                :l_dummy_party_name
              )

            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

* CHANNEL #####################################################################
      WHEN 'Channel'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYCHANNEL where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEYCHANNEL(OBJECTID, TYPEID, PARTY, SERVICE, CHANNEL) values
              (
                :l_object_id,
                'Channel',
                :l_dummy_party_name,
                :l_dummy_service_name,
                :l_dummy_channel_name
              )
            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

* DOCU ########################################################################
      WHEN 'DOCU'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYNAME where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name .
              CONTINUE.
            ENDIF.

            DATA nspace type string.
            DATA name type string.
            wait up to 2 SECONDS.
            get time.
            concatenate 'DUMMY NAME' sy-datum sy-uzeit into nspace .
            concatenate 'DUMMY NAMESPACE' sy-datum sy-uzeit into name .
            l_dummy_namespace = nspace.
            l_dummy_name = name.
            EXEC SQL.
              insert into XI_DIRKEYNAME(OBJECTID,TYPEID,NAME,NAMESPACE) values
              (
                :l_object_id,
                'DOCU',
                :l_dummy_name,
                :l_dummy_namespace
              )
             ENDEXEC.
             WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.


* DIRECTORY VIEW ##############################################################
      WHEN 'DirectoryView'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEY_DIR_VIEW where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name .
              CONTINUE.
            ENDIF.
            EXEC SQL.
              insert into XI_DIRKEY_DIR_VIEW(OBJECTID, TYPEID, DIRVIEW) values
              (
                :l_object_id,
                'DirectoryView',
                :l_dummy_scenario_name
              )
             ENDEXEC.
             WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

* MAPPING RELATION ############################################################
      WHEN 'MappingRelation'.
        TRY.
            EXEC SQL.
              SELECT COUNT(*) into :l_duplicate_counter from XI_DIRKEYMAPKIDET where OBJECTID = :l_object_id
            ENDEXEC.
            IF l_duplicate_counter NE 0.
              WRITE : /  'OBJECTID already exists: ' COLOR COL_NEGATIVE ,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
              CONTINUE.
            ENDIF.
            EXEC SQL.
                insert into XI_DIRKEYMAPKIDET (OBJECTID, TYPEID, FROMACTIONNS, FROMACTION, FROMPARTY, FROMSRVC, TOPARTY, TOSRVC) values
                (
                  :l_object_id,
                  'MappingRelation',
                  :l_dummy_interface_namespace,
                  :l_dummy_interface_name,
                  :l_dummy_sender_party_name,
                  :l_dummy_sender_service_name,
                  :l_dummy_receiver_party_name,
                  :l_dummy_receiver_service_name
                )
            ENDEXEC.
            WRITE : /  'OBJECTID successfully inserted: ' COLOR COL_POSITIVE, lw_ib_object-version_id , ':', lw_ib_object-object_name, ':', l_object_id.
          CATCH cx_sy_native_sql_error INTO exc_ref.
            error_text = exc_ref->get_text( ).
            MESSAGE error_text TYPE 'I' RAISING sql_error.
        ENDTRY.

      WHEN OTHERS.
        WRITE : / 'No Rule found for object: ' COLOR COL_NEGATIVE,  lw_ib_object-version_id , ':', lw_ib_object-object_name.
    ENDCASE.
  ENDLOOP.







*---------------------------------------------------------------------*
*       FORM UPLOAD_CSV_SPREADSHEET                                   *
*---------------------------------------------------------------------*
*       Reads CSV file from PC                                        *
*---------------------------------------------------------------------*
*  -->  PI_SSHEET    [in]  Spreadsheet                                *
*  -->  PI_FNAME     [in]  File name                                  *
*  -->  PO_ERRORFLAG [out] Error flag, 'X' if error                   *
*  -->  PO_ERRORMSG  [out] Error message                              *
*---------------------------------------------------------------------*
FORM upload_csv_spreadsheet
  TABLES
    pi_raw
  USING
    pi_fname
  CHANGING
    po_errorflag
    po_errormsg.

  CONSTANTS:
    c_ascii_file(3) TYPE c VALUE 'ASC'.


  CALL FUNCTION 'WS_UPLOAD'
    EXPORTING
      filename            = pi_fname
      filetype            = c_ascii_file
    TABLES
      data_tab            = pi_raw
    EXCEPTIONS
      conversion_error    = 1
      file_open_error     = 2
      file_read_error     = 3
      invalid_table_width = 4
      invalid_type        = 5
      no_batch            = 6
      unknown_error       = 7
      OTHERS              = 8.

  IF sy-subrc NE 0.
    po_errorflag = c_x.
    po_errormsg = text-erf.
  ENDIF.

ENDFORM.                    "upload_csv_spreadsheet

Author: Sergio Cipolla
Submitted: 25 February 2009

This report shows how to Create Third Party Business Systems in the System Landscape Directory.

The main form is create_3rd_party_bs and can be used inside a loop to create a set of business systems.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  ZTEDGE_SLD_CREATE_3PBS
*&
*&---------------------------------------------------------------------*
*& Author: Sergio Cipolla
*&
*&---------------------------------------------------------------------*

REPORT  ZTEDGE_SLD_CREATE_3PBS.

data : lt_keyprop type sld_t_valuelist,
       lo_instref type ref to cl_sld_cim_instance,
       l_value type string,
       m_rc type i,
       accessor type ref to cl_sld_accessor,
       lt_instances_created_handle type table of string.

constants: gc_success type i value 0,
           gc_error type i value 4,
           gc_sap_bus_sys type string value 'SAP_BusinessSystem',
           gc_sap_appl_sys type string value 'SAP_ApplicationSystem',
           const_sap_globaluniqueid type string value 'SAP_GlobalUniqueID',
           gc_sap_bus_sys_guid type string value 'SAP_BusinessSystemGuid',
           csap_logicalsystemviewedsystem type string value 'SAP_LogicalSystemViewedSystem',
           gc_log_ale_sys type string value 'SAP_LogicalALESystem',
           csap_alesystemviewedbs type string value 'SAP_ALESystemViewedBusinessSystem',
           csap_ins_prod_log_app_sys type string value 'SAP_InstalledProductLogicalApplicationSystem',
           csap_businesssystem_exc_srv type string value 'SAP_BusinessSystemExchangeServer',
           gc_sap_coll_bus_sys type string value 'SAP_CollectedBusinessSystems',
           gc_sap_bus_sys_group type string value 'SAP_BusinessSystemGroup'.


*******************************************************************************
define set_property.
  &1->set_property( pname = &2
                    value = &3 ).
end-of-definition.
*******************************************************************************

*******************************************************************************
define check_existence.

  clear m_rc.
  clear : lt_keyprop, lo_instref, l_value.
  refresh lt_keyprop.
  try.
      m_rc = 0.
      lt_keyprop = &1->get_keyproperties( ).

      call method accessor->get_instance
        exporting
          cname   = &2
          keyprop = lt_keyprop
        receiving
          ret     = lo_instref.

      if not lo_instref is initial.
        m_rc = 1.
      endif.

    catch cx_sld_api_exception into ex.
      if ex->textid = cx_sld_api_exception=>no_such_instance.
*         instance does not exist, no problem.
      else.
        m_rc = 1.
      endif.
  endtry.

  if m_rc ne 0.
    l_value = &1->get_classname( ).
    write: / 'Object ',  &2, ': ', l_value, ' already exists'.
    perform sld_rollback.
    return.
  endif.
end-of-definition.
*******************************************************************************

****************************************************************************************
SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE txt01.
PARAMETERS: psldhost TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: pport TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: pnspace TYPE char30 LOWER CASE OBLIGATORY DEFAULT 'sld/active'.
PARAMETERS: puser TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: ppass TYPE char30 LOWER CASE OBLIGATORY.
SELECTION-SCREEN END OF BLOCK block1.

SELECTION-SCREEN BEGIN OF BLOCK block2 WITH FRAME TITLE txt02.
PARAMETERS: ptsname type char100 lower case obligatory.
PARAMETERS: phost type char100 lower case obligatory.
PARAMETERS: pbsname type char100 lower case obligatory.
PARAMETERS: palename type char100 lower case obligatory.
PARAMETERS: pxbsname type char100 lower case obligatory.
PARAMETERS: pgroup type char100 lower case obligatory.
SELECTION-SCREEN END OF BLOCK block2.

****************************************************************************************
INITIALIZATION.
  txt01 = 'SLD parameters'.
  %_psldhost_%_app_% = 'Hostname'.
  %_pport_%_app_% = 'Port'.
  %_pnspace_%_app_% = 'Namespace'.
  %_puser_%_app_% = 'User'.
  %_ppass_%_app_% = 'Password'.

txt02 = 'Business Systems parameters'.
 %_ptsname_%_app_% = 'Tec. System Name'.
 %_phost_%_app_% = 'Host Name'.
 %_pbsname_%_app_% ='New Business System Name'.
 %_palename_%_app_% ='New Logical System Name'.
 %_pxbsname_%_app_% ='PI Bus. Sys. Name'.
 %_pgroup_%_app_% ='Group Name'.


 DATA: lt_destinations type sld_s_accessdata_display occurs 0,
       lw_destination type sld_s_accessdata_display,
       lt_return type bapiret2 occurs 0.

 if sy-saprl = '640'.
  else.
    call function 'BAPI_SLD_DEST_LIST'
      tables
        destinations = lt_destinations
        return       = lt_return.
    read table lt_destinations into lw_destination index 1.

    psldhost  = lw_destination-host.
    pport  =  lw_destination-port.
    pnspace = 'sld/active'.
    puser      = lw_destination-user.
    ppass  = lw_destination-password.
  endif.

****************************************************************************************
start-of-selection.
  data:
        l_tec_sys_name type string,
        l_hostname type string,
        l_bus_sys_name type string,
        l_alename type string,
        l_is_bsname type string,
        l_is_group type string.

  l_tec_sys_name = ptsname.
  l_hostname = phost.
  l_bus_sys_name = pbsname.
  l_alename = palename.
  l_is_bsname = pxbsname.
  l_is_group = pgroup.

  data: l_rc type i.

  perform create_3rd_party_bs using l_tec_sys_name
                                    l_hostname
                                    l_bus_sys_name
                                    l_alename
                                    l_is_bsname
                                    l_is_group
                                    l_rc.

*&---------------------------------------------------------------------*
*&      Form  create_3rd_party_bs
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_TEC_SYS_NAME  text
*      -->P_HOSTNAME      text
*      -->P_BUS_SYS_NAME  text
*      -->P_ALENAME       text
*      -->P_IS_BSNAME     text
*----------------------------------------------------------------------*
form create_3rd_party_bs using  p_tec_sys_name type string
                                p_hostname type string
                                p_bus_sys_name type string
                                p_alename type string
                                p_is_bsname type string
                                p_group_name type string
                                p_rc type i.

  data:
        lo_bus_sys type ref to cl_sld_cim_instance,
        lo_guid type ref to cl_sld_cim_instance,
        lo_bus_sys_guid type ref to cl_sld_cim_instance,
        lo_log_sys_view type ref to cl_sld_cim_instance,
        lo_log_sys_ale  type ref to cl_sld_cim_instance,
        lo_ale_sys_view type ref to cl_sld_cim_instance,
        lo_inst_prod_log_app_sys type ref to cl_sld_cim_instance,
        lo_bs_exc_srv type ref to cl_sld_cim_instance,
        lo_sap_coll_bus_sys type ref to cl_sld_cim_instance.

  data: l_bus_sys_handle type string,
        l_guid_handle type string,
        l_bus_sys_guid_handle type string,
        l_log_sys_view_handle type string,
        l_log_sys_ale_handle type string,
        l_ale_sys_view_handle type string,
        l_inst_prod_log_app_sys_handle type string,
        l_bs_exc_srv_handle type string,
        l_sap_coll_bus_sys_handle type string.

*Objects to find....
  data: l_tec_sys_handle type string.
  data: l_inst_prod_handle type string.
  data: l_is_bs_handle type string.
  data: l_coll_handle type string.

  data: ex type ref to cx_sld_api_exception.


  data: l_rc type i.
  data: l_msg type string.

  p_rc = gc_error.

*******************************************************************************
* Validate Parameters
*******************************************************************************
  data: l_len type i value 0.
  data: l_mcnt type i value 0.

  if p_tec_sys_name is initial.
    write: / 'Missing parameter Technical System Name'.
    return.
  endif.

  if p_hostname is initial.
    write: / 'Missing parameter hostname'.
    return.
  endif.


  if p_bus_sys_name is initial.
    write: / 'Missing parameter Business System Name'.
    return.
  endif.

  if p_alename is initial.
    write: / 'Missing parameter Ale Name' .
    return.
  endif.


  l_len = strlen( p_alename ).
  if l_len > 10.
    write: / 'Ale Name too Long: ', p_alename , ' (', l_len, ' chars)'.
    return.
  endif.

  if p_is_bsname is initial.
    write: / 'Missing parameter Integration Server BS Name'.
    return.
  endif.

  if p_group_name is initial.
    write: / 'Missing parameter Group Name'.
    return.
  endif.


*******************************************************************************
* GET ACCESS TO SLD
*******************************************************************************
  perform connect_to_sld changing accessor l_rc l_msg.
  if l_rc ne gc_success.
    write: / l_msg.
    return.
  endif.

*******************************************************************************
* IDENTIFY OBJECTS NEEDED DURING THE PROCEDURE
*******************************************************************************
  data: lo_tec_sys type ref to cl_sld_cim_instance.

*1 Technical System Handle
  perform get_tec_sys_handle using p_tec_sys_name p_hostname changing lo_tec_sys l_tec_sys_handle l_rc l_msg.
  if l_rc ne gc_success.
    write: / l_msg.
    return.
  endif.
*WRITE : / 'Tech Sys. handle: ', l_tec_sys_handle.

*2 Product Handle
  perform get_product_handle using lo_tec_sys changing l_inst_prod_handle l_rc l_msg.
  if l_rc ne gc_success.
    write: / l_msg.
    return.
  endif.
*WRITE : / 'Installed Product handle: ', l_inst_prod_handle.

*3 Integration Server (Business System) Handle
  perform get_is_bs_handle using p_is_bsname changing l_is_bs_handle l_rc l_msg.
  if not l_rc eq 0.
    write: / l_msg.
    return.
  endif.
*WRITE : / 'IS handle: ', l_is_bs_handle.

*4 Group (Collection Handle)
  perform get_group_handle using p_group_name changing l_coll_handle l_rc l_msg.
  if not l_rc eq 0.
    write: / l_msg.
    return.
  endif.
*  WRITE : / 'Group Handle: ', l_coll_handle.

  data: value type string.

*******************************************************************************
* PREPARE SLD OBJECTS TO BE CREATED
*******************************************************************************
*1 Create SAP_BusinessSystem
  try.
      create object lo_bus_sys
        exporting
          classname = gc_sap_bus_sys
          accessor  = accessor.
      set_property lo_bus_sys 'CreationClassName' gc_sap_bus_sys.
      set_property lo_bus_sys 'Name' p_bus_sys_name.
      set_property lo_bus_sys 'Caption' p_bus_sys_name.
      set_property lo_bus_sys 'Description' 'Created via ABAP SLD API'.

      check_existence lo_bus_sys gc_sap_bus_sys.
      perform write_object using lo_bus_sys changing l_bus_sys_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*2 Create SAP_GlobalUniqueID for Business System
  try.
      data: l_guid type string.
      data: l_caption type string.

*VALID from PI 7.0
*      l_guid = cl_sld_util=>create_guid( ).

      perform old_release_create_guid changing l_guid.

      concatenate 'GUID for' p_bus_sys_name into l_caption separated by space.

      create object lo_guid
        exporting
          classname = const_sap_globaluniqueid
          accessor  = accessor.
      set_property lo_guid 'Name' l_guid.
      set_property lo_guid 'Caption' l_caption.

      check_existence lo_guid const_sap_globaluniqueid.
      perform write_object using lo_guid changing l_guid_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*3 Create BusinessSystemGuid
  try.
      create object lo_bus_sys_guid
        exporting
          classname = gc_sap_bus_sys_guid
          accessor  = accessor.
      set_property lo_bus_sys_guid 'SameElement' l_guid_handle.
      set_property lo_bus_sys_guid 'SystemElement' l_bus_sys_handle.

      check_existence lo_bus_sys_guid gc_sap_bus_sys_guid.
      perform write_object using lo_bus_sys_guid changing l_bus_sys_guid_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*4 Create LogicalSystemViewedSystem
  try.
      create object lo_log_sys_view
        exporting
          classname = csap_logicalsystemviewedsystem
          accessor  = accessor.
      set_property lo_log_sys_view 'SameElement' l_bus_sys_handle.
      set_property lo_log_sys_view 'SystemElement' l_tec_sys_handle.

      check_existence lo_log_sys_view csap_logicalsystemviewedsystem.
      perform write_object using lo_log_sys_view changing l_log_sys_view_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*5 Create SAP_LogicalALESystem
  try.
      data: l_name type string.

*if sy-saprl = '640'.
*Old Release XI 3.0
      concatenate p_alename '.System.' p_bus_sys_name into l_name.
*else.
*New Release PI 7.0
*      CONCATENATE p_alename '.SystemName.' p_bus_sys_name INTO l_name.
*endif.

      create object lo_log_sys_ale
        exporting
          classname = gc_log_ale_sys
          accessor  = accessor.
      set_property lo_log_sys_ale 'CreationClassName' gc_log_ale_sys.
      set_property lo_log_sys_ale 'Name' l_name.
      set_property lo_log_sys_ale 'ALEName' p_alename.
      set_property lo_log_sys_ale 'Caption' p_alename.

      check_existence lo_log_sys_ale gc_log_ale_sys.
      perform write_object using lo_log_sys_ale changing l_log_sys_ale_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*6 Create SAP_ALESystemViewedBusinessSystem
  try.
      create object lo_ale_sys_view
        exporting
          classname = csap_alesystemviewedbs
          accessor  = accessor.
      set_property lo_ale_sys_view 'SameElement' l_log_sys_ale_handle.
      set_property lo_ale_sys_view 'SystemElement' l_bus_sys_handle.

      check_existence lo_ale_sys_view csap_alesystemviewedbs.
      perform write_object using lo_ale_sys_view changing l_ale_sys_view_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.


*7 Create SAP_InstalledProductLogicalApplicationSystem
  try.
      create object lo_inst_prod_log_app_sys
        exporting
          classname = csap_ins_prod_log_app_sys
          accessor  = accessor.
      set_property lo_inst_prod_log_app_sys 'Product' l_inst_prod_handle.
      set_property lo_inst_prod_log_app_sys 'System' l_bus_sys_handle.

      check_existence lo_inst_prod_log_app_sys csap_ins_prod_log_app_sys.
      perform write_object using lo_inst_prod_log_app_sys changing l_inst_prod_log_app_sys_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*8 Create SAP_BusinessSystemExchangeServer
  try.
      create object lo_bs_exc_srv
        exporting
          classname = csap_businesssystem_exc_srv
          accessor  = accessor.
      set_property lo_bs_exc_srv 'Antecedent' l_bus_sys_handle.
      set_property lo_bs_exc_srv 'Dependent' l_is_bs_handle.

      check_existence lo_bs_exc_srv csap_businesssystem_exc_srv.
      perform write_object using lo_bs_exc_srv changing l_bs_exc_srv_handle.

    catch cx_sld_api_exception into ex.
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*9 Modify SAP_BusinessSystem (add Role)
  try.
      data: lt_properties type sld_t_valuelist.
      data: lt_sld_t_string type sld_t_string.
      data: lo_bus_sys_upd type ref to cl_sld_cim_instance.
      lo_bus_sys_upd = accessor->get_instance( ihandle = l_bus_sys_handle ).

*Set the Role Application System
      append 'Application System' to lt_sld_t_string.

      call method lo_bus_sys_upd->set_property_array
        exporting
          pname  = 'Roles'
          values = lt_sld_t_string.

      lt_properties = lo_bus_sys_upd->get_properties( ).

      call method accessor->modify_instance
        exporting
          ihandle    = l_bus_sys_handle
          properties = lt_properties.

      write : / 'Object SAP_BusinessSystem Modified, Added Role Application System'.
    catch cx_sld_api_exception .
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

*10 Create SAP_CollectedBusinessSystems
  try.
      create object lo_sap_coll_bus_sys
        exporting
          classname = gc_sap_coll_bus_sys
          accessor  = accessor.

      set_property lo_sap_coll_bus_sys 'Collection' l_coll_handle.
      set_property lo_sap_coll_bus_sys 'Member' l_bus_sys_handle.

      check_existence lo_sap_coll_bus_sys gc_sap_coll_bus_sys.
      perform write_object using lo_sap_coll_bus_sys changing l_sap_coll_bus_sys_handle.


    catch cx_sld_api_exception .
      value = ex->get_text( ).
      write: / 'Failure:',  value.
      perform sld_rollback.
      return.
  endtry.

  p_rc = gc_success.
endform.                    "create_3rd_party_bs

*&---------------------------------------------------------------------*
*&      Form  sld_rollback
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
form sld_rollback raising cx_sld_api_exception..
  data:
        l_value type string,
        l_class type string,
        l_assoc_class type string,
        ex type ref to cx_sld_api_exception.


  data: lo_inst type ref to cl_sld_cim_instance.
  data: lo_assoc_inst type ref to cl_sld_cim_instance.

  data: lt_inames type sld_t_string.
  data: l_inst_handle type string.
  data: l_assoc_inst_handle type string.

  write : / 'ROLLBACK START'.
  loop at lt_instances_created_handle into l_inst_handle.
    try.

*Check if the objects exist on the SLD
        try.
            lo_inst = accessor->get_instance( ihandle = l_inst_handle ).
            l_class = lo_inst->get_classname( ).
          catch cx_sld_api_exception .
            continue.
        endtry.


*     Get all association handles of this instance:
        lt_inames = accessor->referencenames( ihandle = l_inst_handle ).

*      Before Deleting the instance Delete all association instances:
        loop at lt_inames into l_assoc_inst_handle.
          try.
              lo_assoc_inst = accessor->get_instance( ihandle = l_assoc_inst_handle ).
              l_assoc_class = lo_assoc_inst->get_classname( ).
            catch cx_sld_api_exception .
              continue.
          endtry.
          accessor->delete_instance( ihandle = l_assoc_inst_handle ).
          write : / 'Object deleted (Assoc): ', l_assoc_class ,' ', l_assoc_inst_handle.

        endloop.

*     Finally, delete the instance:
        accessor->delete_instance( ihandle = l_inst_handle ).

        write : / 'Object deleted: ', l_class ,' ', l_inst_handle.
      catch cx_sld_api_exception into ex.

        l_value = ex->get_text( ).
        write: / 'Failure:',  l_value.
    endtry.

  endloop.
  write : / 'ROLLBACK END'.
endform.                    "sld_rollback

*&---------------------------------------------------------------------*
*&      Form  GET_IS_BS_HANDLE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_I_IS_BSNAME  text
*      <--P_E_IS_BS_HANDLE  text
*----------------------------------------------------------------------*
form get_is_bs_handle  using pi_is_bsname type string
                       changing pe_is_bs_handle type string
                                p_rc type i
                                p_msg type string
                        raising cx_sld_api_exception.

  data: l_filter type ref to cl_sld_filter.
  data: l_xi_inst type ref to cl_sld_cim_instance.
  data: lt_instances type sld_t_instref.
  data: lc_tmp_inst type ref to cl_sld_cim_instance.
  data: l_classname type string.
  data: l_counter type i.
  data: l_string type string.
  data: ex type ref to cx_sld_api_exception.

  clear: p_rc, p_msg.

  data: l_is_xi type c.
  data: lt_properties type sld_t_string.


  try.
      create object l_filter.
      l_filter->add_pattern( pname = 'Name'
                           value = pi_is_bsname ).

      lt_instances = accessor->enumerate_instances( cname = gc_sap_bus_sys
                                                    filter = l_filter ).

      loop at lt_instances into lc_tmp_inst.
        clear l_classname.
        l_classname = lc_tmp_inst->get_property( pname = 'CreationClassName' ).

* To avoid usage of inherited classes
        if l_classname ne gc_sap_bus_sys.
          continue.
        endif.

        lt_properties = lc_tmp_inst->get_property_array( pname  = 'Roles' ).
        loop at lt_properties into l_string.
          if l_string eq 'Integration Server'.
            l_xi_inst = lc_tmp_inst.
            l_counter = l_counter + 1.
          endif.
        endloop.

      endloop.

    catch cx_sld_api_exception .
      l_string = ex->get_text( ).
      concatenate 'Failure:'  l_string into p_msg separated by space.
      p_rc = gc_error.
      return.
  endtry.

  if not l_counter = 1.
    l_string = l_counter.
    concatenate l_string 'Business System with Name' pi_is_bsname 'found' into p_msg separated by space.
    p_rc = gc_error.
    return.
  endif.

*Check if it is an integration server
  refresh: lt_properties.
  clear: lt_properties, l_is_xi.
  try.
      lt_properties = l_xi_inst->get_property_array( pname  = 'Roles' ).
      loop at lt_properties into l_string.
        if l_string eq 'Integration Server'.
          l_is_xi = 'X'.
        endif.
      endloop.
    catch cx_sld_api_exception .
      l_string = ex->get_text( ).
      concatenate 'Failure:'  l_string into p_msg separated by space.
      p_rc = gc_error.
      return.
  endtry.

  if not l_is_xi eq 'X'.
    concatenate pi_is_bsname 'is not an Intergration Server ' into p_msg separated by space.
    p_rc = gc_error.
    return.
  endif.

  pe_is_bs_handle = l_xi_inst->get_objectname( ).
endform.                    " GET_IS_BS_HANDLE

*&---------------------------------------------------------------------*
*&      Form  GET_PRODUCT_HANDLE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_I_TECH_SYS  text
*      <--P_E_INST_PROD_HANDLE  text
*----------------------------------------------------------------------*
form get_product_handle  using    pi_tech_sys type ref to cl_sld_cim_instance
                         changing pe_inst_prod_handle type string
                                  p_rc type i
                                  p_msg type string
                        raising cx_sld_api_exception.


  data:
        lt_irefs type sld_t_instref,
        instref type ref to cl_sld_cim_instance,
        lt_swc_irefs  type sld_t_instref,
        lo_swc_iref type ref to cl_sld_cim_instance.

  data: l_tmp_value type string.
  data: l_counter type i.
  data: l_classname type string.
  data: l_string type string.
  data: ex type ref to cx_sld_api_exception.

  clear: p_rc, p_msg.
  clear: pe_inst_prod_handle.

  try.
      call method accessor->associators
        exporting
          iref = pi_tech_sys
        receiving
          ret  = lt_irefs.

      loop at lt_irefs into instref.
        l_classname = instref->get_classname( ) .

        if l_classname eq 'sap_installedsoftwarecomponent'.
          call method accessor->associators
            exporting
              iref = instref
            receiving
              ret  = lt_swc_irefs.

          loop at lt_swc_irefs into lo_swc_iref.
            l_classname = lo_swc_iref->get_classname( ) .
            if l_classname eq 'sap_installedproduct'.

              clear l_tmp_value.
              l_tmp_value = lo_swc_iref->get_objectname( ).


              if pe_inst_prod_handle is initial.
                pe_inst_prod_handle = l_tmp_value.
                l_counter = 1.
              else.
                if pe_inst_prod_handle ne l_tmp_value.
                  l_counter = l_counter + 1.
                endif.
              endif.
            endif.
          endloop.
        endif.

      endloop.

    catch cx_sld_api_exception .
      l_string = ex->get_text( ).
      concatenate 'Failure:' l_string into p_msg separated by space.
      p_rc = gc_error.
      return.
  endtry.

  if not l_counter = 1.
    l_string = l_counter.
    concatenate 'Found:' l_string  'products Installed, Multiple Products Not Yet Supported' into p_msg separated by space.
    p_rc = gc_error.
  endif.


endform.                    " GET_PRODUCT_HANDLE
*&---------------------------------------------------------------------*
*&      Form  GET_TEC_SYS_HANDLE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_P_TEC_SYS_NAME  text
*      -->P_P_HOSTNAME  text
*      <--P_LO_TEC_SYS  text
*      <--P_L_TEC_SYS_HANDLE  text
*----------------------------------------------------------------------*
form get_tec_sys_handle  using    pi_tec_sys_name type string
                                  pi_hostname type string
                         changing pe_tec_sys type ref to cl_sld_cim_instance
                                  pe_tec_sys_handle type string
                                  p_rc type i
                                  p_msg type string
                        raising cx_sld_api_exception.


  data: lo_filter type ref to cl_sld_filter.
  data: l_counter type i value 0.
  data: l_tech_sys_full_name type string.

  data: lt_instances type sld_t_instref.
  data: lo_instance type ref to cl_sld_cim_instance.
  data: l_classname type string.
  data: l_string type string.


  clear: p_rc, p_msg.

  concatenate pi_tec_sys_name '.SystemHome.' pi_hostname into l_tech_sys_full_name.

  create object lo_filter.
  lo_filter->add_pattern( pname = 'Name'
                          value = l_tech_sys_full_name ).

  lt_instances = accessor->enumerate_instances( cname = gc_sap_appl_sys
                                                filter = lo_filter ).

  loop at lt_instances into lo_instance.
    l_classname = lo_instance->get_property( pname = 'CreationClassName' ).

* To avoid usage of inherited classes
    if l_classname ne gc_sap_appl_sys.
      continue.
    endif.
    l_counter = l_counter + 1.
  endloop.

  if not l_counter = 1.
    l_string = l_counter.
    concatenate 'Error:' l_string 'Technical System with Name ' l_tech_sys_full_name 'found' into p_msg separated by space.
    p_rc = gc_error.
    return.
  endif.

  pe_tec_sys = lo_instance.
  pe_tec_sys_handle = lo_instance->get_objectname( ).

endform.                    " GET_TEC_SYS_HANDLE
*&---------------------------------------------------------------------*
*&      Form  CONNECT_TO_SLD
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_ACCESSOR  text
*----------------------------------------------------------------------*
form connect_to_sld  changing pe_accessor type ref to cl_sld_accessor
                              p_rc type i
                              p_msg type string
                     raising cx_sld_api_exception.


  data:
      l_string type string,
  my_sld_host     type string,
  my_sld_port     type i,
  my_namespace    type string,
  my_user         type string,
  my_password     type string,
  lt_destinations type sld_s_accessdata_display occurs 0,
  lw_destination type sld_s_accessdata_display,
  lt_return type bapiret2 occurs 0.
  data: ex type ref to cx_sld_api_exception.

  clear : p_rc, p_msg.

* Read SLD access Parameters
*Not available in old releases
    my_sld_host  = psldhost.
    my_sld_port  =  pport.
    my_namespace = pnspace.
    my_user      = puser.
    my_password  = ppass.

* Create accessor object to SLD server:
  create object pe_accessor
    exporting
      host      = my_sld_host
      port      = my_sld_port
      namespace = my_namespace
      user      = my_user
      password  = my_password.

* set trace level for java logging.
  pe_accessor->set_tracelevel( 1 ).

* Test the connection to the SLD server:
  try.
      pe_accessor->ping( ).
    catch cx_sld_api_exception into ex.
      l_string = ex->get_text( ).
      p_rc = gc_error.
      concatenate 'Ping Failed: ' l_string into p_msg separated by space.
      return.
  endtry.

endform.                    " CONNECT_TO_SLD

*&---------------------------------------------------------------------*
*&      Form  write_object
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PI_CIM_INSTANCE  text
*      -->PE_HANDLE        text
*----------------------------------------------------------------------*
form write_object using pi_cim_instance type ref to cl_sld_cim_instance
                  changing pe_handle type string
                  raising cx_sld_api_exception.

  data : l_class type string.

  pe_handle = accessor->create_instance( iref = pi_cim_instance ).
  l_class = pi_cim_instance->get_classname( ).

  append pe_handle to lt_instances_created_handle.
  write: / '** Instance Created: ', l_class, ' (', pe_handle, ')'.
endform.                    "write_object
*&---------------------------------------------------------------------*
*&      Form  old_release_create_guid
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      <--P_L_GUID  text
*----------------------------------------------------------------------*
form old_release_create_guid  changing p_l_guid.

  data: ret	type string.


  data: guid       type sysuuid-c,
        s1(8)      type c,
        s2(4)      type c,
        s3(4)      type c,
        s4(4)      type c,
        s5(12)     type c.

  call function 'SYSTEM_UUID_C_CREATE'
    importing
      uuid = guid.

  move: guid(8)     to s1,
        guid+8(4)   to s2,
        guid+12(4)  to s3,
        guid+16(4)  to s4,
        guid+20(12) to s5.

  concatenate s1 s2 s3 s4 s5 into ret separated by '-'.
  translate ret to lower case.                           "#EC TRANSLANG

  p_l_guid = ret.
endform.                    " old_release_create_guid
*&---------------------------------------------------------------------*
*&      Form  GET_GROUP_HANDLE
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_P_GROUP_NAME  text
*      <--P_L_IS_COLL_HANDLE  text
*      <--P_L_RC  text
*      <--P_L_MSG  text
*----------------------------------------------------------------------*
form get_group_handle  using    pi_group_name type string
                       changing pe_is_coll_handle type string
                                  p_rc type i
                                  p_msg type string
                        raising cx_sld_api_exception.

  clear: p_rc, p_msg.
  data: lo_filter type ref to cl_sld_filter.
  data: lt_instances type sld_t_instref.
  data: lo_instance type ref to cl_sld_cim_instance.
  data: l_classname type string.
  data: l_string type string.
  data: l_counter type i value 0.

  create object lo_filter.
  lo_filter->add_pattern( pname = 'Name'
                          value = pi_group_name ).

  lt_instances = accessor->enumerate_instances( cname = gc_sap_bus_sys_group
                                                filter = lo_filter ).

  data lc_sap_bus_sys_group type string.
  lc_sap_bus_sys_group = gc_sap_bus_sys_group.
  translate lc_sap_bus_sys_group to lower case.

  loop at lt_instances into lo_instance.
    l_classname = lo_instance->get_classname( ).

* To avoid usage of inherited classes
    if l_classname ne lc_sap_bus_sys_group.
      continue.
    endif.
    l_counter = l_counter + 1.
  endloop.

  if not l_counter = 1.
    l_string = l_counter.
    concatenate 'Error:' l_string 'Group with Name ' pi_group_name 'found' into p_msg separated by space.
    p_rc = gc_error.
    return.
  endif.

  pe_is_coll_handle = lo_instance->get_objectname( ).
  endform.                    " GET_GROUP_HANDLE

Author: Satish Jaiswal
Submitted: June 26, 2007

import com.sap.aii.mapping.api.StreamTransformation;import java.awt.image.BufferedImage;
import java.io.*;
import java.util.Map;
import javax.imageio.ImageIO;/**
 * @author satishj
 */
public class MapImage implements StreamTransformation {
 private Map map;
 BufferedImage img;
  public void setParameter (Map param){
   map = param;
  }
  public void execute (InputStream in, OutputStream out){
   try
   {
    img = ImageIO.read(in);
    ImageIO.write(img, "PNG",out); // This example converts JPG file to PNG Format
    
   }//End Of Try
   catch(Throwable t)
   {
    t.printStackTrace();
   }
  }//End Of Execute Function }

Author: Sergio Cipolla
Submitted: 17 May 2008

The following report can be used to modify the status of an inbound proxy message on an Application System. This is something that should not be done (especially in a productive environment) but that might be useful while doing some developments and test of custom proxy implementation.

In particular, this report changes a successfully processed message into a message with an Application error, giving the ability to reprocess the same message again and verify that the code underneath the proxy is working as expected.

It plays with three tables:

  • SXMSPMAST which holds the current status of the message
  • SXMSPVERS which holds all the versions of the message
  • SXMSPERROR which holds an entry for each message with an error

    Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
    *&---------------------------------------------------------------------*
    *& Report  Z_CHANGE_STATUS
    *&
    *&---------------------------------------------------------------------*
    *&
    *& AUTHOR: Sergio Cipolla
    *&
    *&---------------------------------------------------------------------*
    
    
    REPORT  z_change_status.
    
    
    PARAMETERS p_msg_id TYPE sxmspmast-msgguid OBLIGATORY.
    
    START-OF-SELECTION.
    
      DATA :
            lw_sxmspmast TYPE sxmspmast,
            lw_sxmsperror TYPE sxmsperror,
            lt_sxmspvers TYPE sxmspvers OCCURS 0,
            lw_sxmspvers TYPE sxmspvers,
            l_tstamp TYPE timestampl,
            l_oldtimestamp TYPE timestampl,
            l_answer.
    
      CALL FUNCTION 'POPUP_TO_CONFIRM_STEP'
        EXPORTING
         defaultoption        = 'N'
          textline1            = 'This is a test report, not to be used in productive environment.'
         textline2            =  'Do you want to proceed?'
          titel                = 'Warning'
    *   START_COLUMN         = 25
    *   START_ROW            = 6
    *   CANCEL_DISPLAY       = 'X'
      IMPORTING
         answer               = l_answer.
    
      IF l_answer EQ 'J'.
        WRITE : / 'Action Confirmed by user ', sy-uname.
      ELSE.
        MESSAGE 'Action Canceled' TYPE 'E'.
      ENDIF.
    
      GET TIME STAMP FIELD l_tstamp.
    
      SELECT SINGLE * FROM  sxmspmast
             INTO lw_sxmspmast
             WHERE  msgguid   = p_msg_id
             AND pid = 'RECEIVER'
             AND    msgstate  = '003'.
    
      IF sy-subrc <> 0.
        MESSAGE 'No record found in SXMSPMAST for Received message' TYPE 'E'.
      ENDIF.
      l_oldtimestamp = lw_sxmspmast-exetimest.
    
      WRITE : / 'Record found in SXMSPMAST for message id ', p_msg_id.
    
      SELECT * FROM  sxmspvers
        INTO TABLE lt_sxmspvers
        WHERE msgguid  = lw_sxmspmast-msgguid
        AND  pid      = lw_sxmspmast-pid
        AND  msgstate  = '3'
        AND timestamp EQ l_oldtimestamp.
    
      IF sy-subrc <> 0.
        MESSAGE 'No record found in SXMSPVERS' TYPE 'E'.
      ENDIF.
    
      WRITE : /  'Record found in SXMSPVERS for message id ', p_msg_id.
      READ TABLE lt_sxmspvers INTO lw_sxmspvers INDEX 1.
      IF sy-subrc <> 0.
        MESSAGE 'Error with SXMSPVERS' TYPE 'E'.
      ENDIF.
    
    
    
    ***********************************************************
    ***********************************************************
      WRITE : /  'Updating SXMSPMAST...'.
      lw_sxmspmast-msgstate = '017'.
      lw_sxmspmast-adminuser = sy-uname.
      lw_sxmspmast-exetimest = l_tstamp.
      UPDATE sxmspmast FROM lw_sxmspmast.
      IF sy-subrc <> 0.
        MESSAGE 'Error while updating SXMSPMAST' TYPE 'E'.
        ROLLBACK WORK.
      ENDIF.
      WRITE :  'Updated'.
    
    
    ***********************************************************
    ***********************************************************
      WRITE : /  'Updating SXMSPVERS...'.
      lw_sxmspvers-msgstate = '17'.
      lw_sxmspvers-timestamp = l_tstamp.
      UPDATE sxmspvers FROM lw_sxmspvers.
      IF sy-subrc <> 0.
        MESSAGE 'Error while updating SXMSPVERS' TYPE 'E'.
        ROLLBACK WORK.
      ENDIF.
      WRITE :  'Updated'.
    
    
    ***********************************************************
    ***********************************************************
      WRITE : /  'Creating entry in SXMSPERROR...'.
      lw_sxmsperror-msgguid = lw_sxmspmast-msgguid.
      lw_sxmsperror-pid = lw_sxmspmast-pid.
      lw_sxmsperror-errstat = 'E'.
      lw_sxmsperror-errcat = 'ABAP'.
      lw_sxmsperror-errcode = 'APPLICATION_ERROR'.
      lw_sxmsperror-errtxt = 'Dirty Status Change'.
      lw_sxmsperror-retry = 'M'.
      lw_sxmsperror-exetimest = l_tstamp.
      INSERT sxmsperror FROM lw_sxmsperror.
      IF sy-subrc <> 0.
        MESSAGE 'Error while updating SXMSPERROR' TYPE 'E'.
        ROLLBACK WORK.
      ENDIF.
      WRITE :  'Created'.
    
    ***********************************************************
    ***********************************************************
      COMMIT WORK AND WAIT.
    
      WRITE : / 'Status update Completed'.
    

Author: Zahid Murtaza
Submitted: <26-Jun-2008>
Related Links:

 Description:

In my previous Snippet (Link above) I wrote about writing payload data an FTP Location. In this snippet we will be doing the same but at the same time, change the actual payload, I am expecting a coma separated file, and to get things simple, I check that the record should have only 2 "," in it, if not so, the actual payload is written to an FTP location , while another string is assigned to message payload.. For libraries required for FTP processing please check my previous code snipper -- Link Above-- , more over follow the other link for complete guide for adapter module writing.

package
 changeLoad;
/**

* @author Zahid

*

* To change the template for this generated type comment go to

* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

*/
import
 java.io.*;
import
 sun.net.ftp.FtpClient;
import
 java.util.Hashtable;
import
 javax.ejb.CreateException;
import
 javax.ejb.SessionBean;
import
 javax.ejb.SessionContext;
import
 com.sap.aii.af.mp.module.*;
import
 com.sap.aii.af.ra.ms.api.*;
import
 com.sap.aii.af.service.auditlog.*;
/**
*
 @ejbHome <{com.sap.aii.af.mp.module.ModuleHome}>
*
 @ejbLocal <{com.sap.aii.af.mp.module.ModuleLocal}>
*
 @ejbLocalHome <{com.sap.aii.af.mp.module.ModuleLocalHome}>
*
 @ejbRemote <{com.sap.aii.af.mp.module.ModuleRemote}>
* @stateless*/
public class FTPCheckError implements SessionBean, Module {
private SessionContext myContext;
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext context) {myContext = context;
}
public void ejbCreate() throws CreateException {}
public ModuleData process(ModuleContext moduleContext,
ModuleData inputModuleData)
throws ModuleException {String returnMsg;
byte[] out = null;
byte[] file = null;
byte[] data = null;
int OK;
Message xiMessage = null;Message retMessage =
null;
Object retObject = null;XMLPayload xmlLoad =
null;

// FTP related Declarations
FtpClient m_client;
String host = "172.0.0.1";String user =
"user";
String password = "pwd";String m_sLocalFile =
"";
String m_sHostFile = "";String sDir =
"";
String fileName = null;String messageId =
null;

//Check Load
try {Object dataObject =
null;
int result = 0;ByteArrayOutputStream outXML = null;String Message_Text;
dataObject = inputModuleData.getPrincipalData();
xiMessage = (Message) dataObject;
AuditMessageKey amk =
new AuditMessageKey(xiMessage.getMessageId(),
AuditDirection.INBOUND);
Audit.addAuditLogEntry(
amk,
AuditLogStatus.SUCCESS,
"FileValidation Module is called");Hashtable mp =
(Hashtable) inputModuleData.getSupplementalData(
"module.parameters");
if (mp != null)
fileName = (String) mp.get("FileName");messageId = xiMessage.getMessageId();
m_sHostFile =
"/ReadError/" + fileName + "_" + messageId + "_Error.txt";data = xiMessage.getDocument().getContent();
xmlLoad = xiMessage.getDocument();
String errorString = new String(data, 0, data.length);Message_Text = errorString;
int length = Message_Text.length();
//the text message should have only two ","
int start = Message_Text.indexOf(",");while (start != -1) {result++;
start = Message_Text.indexOf(",", start + 1);}
if (result != 2) {OK = 0;
AuditMessageKey amk2 =
new AuditMessageKey(xiMessage.getMessageId(),
AuditDirection.INBOUND);
Audit.addAuditLogEntry(
amk2,
AuditLogStatus.SUCCESS,
"Invalid File Found, would be written to 'Read Error' Folder");String outData = "00,error,407";//Get data in byte type variable 
out = outData.getBytes();
//byte type variable can than be assigned to paylaod data
xmlLoad.setContent(out);
inputModuleData.setPrincipalData(xiMessage);
try {m_client = new FtpClient(host);m_client.login(user, password);
m_client.ascii();
OutputStream os = m_client.put(m_sHostFile);
file = Message_Text.getBytes();
int filesize = data.length;os.write(file, 0, filesize);
os.close();
} catch (Exception ex) {System.out.println("Error: " + ex);}
}
} catch (Exception e) {
// raise exception, when an error occurred
ModuleException me = new ModuleException(e);throw me;}
return inputModuleData;}
}

 This custom code is getting used to convert a XML file into flat file using custom adapter module in PI7.1. 

 XML file getting used : 

<?xml version="1.0" encoding="UTF-8"?>
<MT_Employee>
<Details>
<Name>Amit</Name>
<Age>23</Age>
</Details>
<Details>
<Name>Srivastava</Name>
<Age>24</Age>
</Details>
</MT_Employee>

Coverting XML file into flat file using Adapter module in PI7.1

/*Coverting XML file into flat file using Adapter module in PI7.1*/
import java.io.InputStream;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.sap.aii.af.lib.mp.module.ModuleContext;
import com.sap.aii.af.lib.mp.module.ModuleData;
import com.sap.aii.af.lib.mp.module.ModuleException;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.engine.interfaces.messaging.api.Message;
import  com.sap.engine.interfaces.messaging.api.MessageKey;
import com.sap.engine.interfaces.messaging.api.MessagePropertyKey;
import com.sap.engine.interfaces.messaging.api.XMLPayload;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
public class ConvertXMLToFile implements SessionBean, TimedObject {
/* (non-Javadoc)
* @see javax.ejb.SessionBean#ejbActivate()
*/
private SessionContext myContext;
public void ejbActivate() throws EJBException, RemoteException {

TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#ejbPassivate()
*/
public void ejbPassivate() throws EJBException, RemoteException {

TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#ejbRemove()
*/
public void ejbRemove() throws EJBException, RemoteException {

TODO Auto-generated method stub
}
/* (non-Javadoc)
* @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
*/
public void setSessionContext(SessionContext context) throws EJBException,RemoteException {
myContext = context;
}
/* (non-Javadoc)
* @see javax.ejb.TimedObject#ejbTimeout(javax.ejb.Timer)
*/
public void ejbTimeout(Timer arg0) {

TODO Auto-generated method stub
}
public void ejbCreate() throws javax.ejb.CreateException {}
public ModuleData process(ModuleContext mc,ModuleData inputModuleData)
throws ModuleException
{
Object obj =null;
Message msg = null;
MessageKey amk =null;
String output="";
try{
obj = inputModuleData.getPrincipalData();
msg = (Message) obj;
amk = new MessageKey(msg.getMessageId(),msg.getMessageDirection());
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "ConvertXMLToFile Module called");
// Returns the main document as XMLPayload
XMLPayload xpld = msg.getDocument();
InputStream inps = (InputStream) xpld.getInputStream();
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "XML message successfully converted into InputStream");
//Parsing input stream which contains XML message
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(inps);
doc.getDocumentElement().normalize();
//Reading Details node(having multiple occurences)
NodeList nodeLst = doc.getElementsByTagName("Details");
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "Reading Details node Started");
for (int x = 0; x < nodeLst.getLength(); x++)
{
Node fstNode = nodeLst.item(x);
if (fstNode.getNodeType() == Node.ELEMENT_NODE)
{
Element fstElmnt = (Element) fstNode;
//Reading first element "Name"
NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("Name");
Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
NodeList fstNm = fstNmElmnt.getChildNodes();
String value1 =((Node) fstNm.item(0)).getNodeValue();
//Reading Second element "Age"
NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("Age");
Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
NodeList lstNm = lstNmElmnt.getChildNodes();
String value2 = ((Node) lstNm.item(0)).getNodeValue();
output= output + value1 + "," + value2 +"\n";
}
}
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "Payload Successfully Readed" +output);
// Set content as byte array into payload
xpld.setContent(output.getBytes());
// Sets the principle data that represents usually the message to be processed
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "Message Successfully updated");
inputModuleData.setPrincipalData(msg);
}
catch (Exception e)
{
Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"AO: Module Exception caught:");
ModuleException me =new ModuleException(e);
throw me;
}
return inputModuleData;}
}




Output will be:
Amit,23




Srivastava,24

The Requirement

A customer I was working at asked me to design a way for them to push files of structured flat file data to their SFTP server (which was incidentally, also a de-central adapter of their PI system). As most of the interfaces currently were writing directly to the apps server file system, they wanted a way to move away from this. They also wanted to avoid creating multiple interfaces for each different file they were pushing and reduce the overall load of such a transition.

The Idea

The only conclusion was to create a generic interface structure, which passed header information about the directory on the SFTP server and the file name. It also passed line information, which would contain the actual flat file content of the file itself. This line information would be pre-formatted by the developer of the file (i.e. fixed width or delimited). By using adapter specific message attributes to dynamically set the file directory and name in PI using the header info.

A Stumbling Block or Two

An ABAP proxy was created based on the interface to push the data to the XI system. When trying to pass our structured data into our table line data for the interface, which was defined as string, we immediately stumbled on problems with numeric typed fields of the structure. It was obvious that the numeric data needed to be converted to character data and make a simple way to help the ABAP developers pass data to the interface. So I came up with the concept of a writing a helper class to handle the conversion for them. They could pass their table to a method of the class and it would convert the table to a string table for them.

During development I stumbled upon a second problem with our fixed width data not preserving spaces. As the version of NW we were using did not have the “CONCATENATE” “RESPECTING BLANKS” I had no way of preserving the whitespace.

The Final Solution

I finally came up with the following solution. I effectively dynamically create a new structured data type based on the types of the data from any table passed into the method. I convert any non-numeric types to equivalent length string types. Then finally I move the data from the original table to the new string typed based table.

In Conclusion

As a result I can directly my developers have no work to do in the conversion and I guarantee the data will pass through the interface.

It’s a little bit overkill but certainly worked well for the requirement. It’s also a pretty good example of how to utilise runtime type services and how handy field symbols can be.

Error rendering macro 'code': Invalid value specified for parameter 'com.atlassian.confluence.ext.code.render.InvalidValueException'
*&---------------------------------------------------------------------*
*& Report  ZZZKP_TEST2
*&
*&---------------------------------------------------------------------*
*& A program to simplify the creation of fixed width data as a string
*& table
*&---------------------------------------------------------------------*

REPORT  zzzkp_test2 LINE-SIZE 400.  "#EC * Length far too big but its just for a demo

TYPE-POOLS: abap.

*----------------------------------------------------------------------*
*       CLASS lcx_str_conversion_excp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcx_str_conversion_excp DEFINITION INHERITING FROM cx_static_check.

  PUBLIC SECTION.
    METHODS: constructor IMPORTING e_additional_error_text TYPE string OPTIONAL,
             get_text REDEFINITION.

  PRIVATE SECTION.
    DATA: g_error_text TYPE string.
ENDCLASS.                    "lcx_str_conversion_excp DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_string_utilities DEFINITION
*----------------------------------------------------------------------*
* String utility class to handle any structure data and convert
* to string type structured data
*----------------------------------------------------------------------*
CLASS lcl_string_utilities DEFINITION.

  PUBLIC SECTION.
    CLASS-METHODS: convert_to_fixed_string_table IMPORTING et_table_in TYPE ANY TABLE
                                                 EXPORTING it_string_table_out TYPE stringtab,
                   get_string_type_for_structure IMPORTING et_structure_in TYPE any
                                                 EXPORTING io_structure_string_type_def TYPE REF TO cl_abap_structdescr
                                                           it_struct TYPE abap_compdescr_tab
                                                 RAISING lcx_str_conversion_excp.

ENDCLASS.                    "lcl_string_utilities DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcl_test_string_utilities DEFINITION
*----------------------------------------------------------------------*
* A test class to execute our program functionality
*----------------------------------------------------------------------*
CLASS lcl_test_string_utilities DEFINITION ABSTRACT FINAL.
  PUBLIC SECTION.
    CLASS-METHODS: execute_program.
ENDCLASS.                    "lcl_test_string_utilities DEFINITION

*----------------------------------------------------------------------*
*       CLASS lcx_str_conversion_excp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcx_str_conversion_excp IMPLEMENTATION.
  METHOD constructor.
    super->constructor( ).

    g_error_text = e_additional_error_text.
  ENDMETHOD.                    "constructor

  METHOD get_text.
    result = 'An exception occurred converting the structure to a string type'(001).

    IF g_error_text IS NOT INITIAL.
      CONCATENATE result ':' space g_error_text INTO result.
    ENDIF.
  ENDMETHOD.                    "get_text
ENDCLASS.                    "lcx_str_conversion_excp IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_string_utilities IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_string_utilities IMPLEMENTATION.
  METHOD convert_to_fixed_string_table.

    DATA: l_string TYPE string,
          lt_struct TYPE abap_compdescr_tab,
          lo_struct_type TYPE REF TO cl_abap_structdescr,
          lo_struct_out_ref TYPE REF TO data,
          lo_str_conversion_excp TYPE REF TO lcx_str_conversion_excp,
          l_error_text TYPE string.

    FIELD-SYMBOLS: <structure_record> TYPE abap_compdescr,
                   <structure_in_field> TYPE ANY,
                   <structure_out_record> TYPE ANY,
                   <structure_out_field> TYPE ANY,
                   <table_in_record> TYPE ANY.

    LOOP AT et_table_in ASSIGNING <table_in_record>.
      TRY.
          AT FIRST.
            " For the first record in our table we need to create a new
            " string only structured data type. We only need to do this once,
            " as all the other data records will have the same structure
            CALL METHOD lcl_string_utilities=>get_string_type_for_structure
              EXPORTING
                et_structure_in              = <table_in_record>
              IMPORTING
                io_structure_string_type_def = lo_struct_type
                it_struct                    = lt_struct.

            " Create a new data reference based on the new string structured type
            " and then assign it to a field symbol
            CREATE DATA lo_struct_out_ref TYPE HANDLE lo_struct_type.
            ASSIGN lo_struct_out_ref->* TO <structure_out_record>.
          ENDAT.

          " On each loop pass clear out the string structured type data reference
          CLEAR: <structure_out_record>.

          " Dynamically assign each field of the input structured type to the data reference
          " which has a string only structured type
          LOOP AT lt_struct ASSIGNING <structure_record>.
            " Assign the table field to a field symbol
            ASSIGN COMPONENT <structure_record>-name OF STRUCTURE <table_in_record> TO <structure_in_field>.
            ASSIGN COMPONENT <structure_record>-name OF STRUCTURE <structure_out_record> TO <structure_out_field>.

            " This logic will be used to convert the input data into relevant string value and
            " assign to the corresponding value in the structured  string type data reference
            CASE <structure_record>-type_kind.
              WHEN 'C' OR 'N' OR 'I' OR 'D' OR 'T'.
                <structure_out_field> = <structure_in_field>.
              WHEN 'P' OR 'F'.
                WRITE <structure_in_field> TO <structure_out_field> DECIMALS <structure_record>-decimals.
            ENDCASE.

          ENDLOOP.

          " Finally add the string to our string table
          " As all the components in the new structured type are string based
          " we can directly assign the structure data to our string and
          " also preserves any white space
          l_string = <structure_out_record>.
          APPEND l_string TO it_string_table_out.

        CATCH lcx_str_conversion_excp INTO lo_str_conversion_excp.
          l_error_text = lo_str_conversion_excp->get_text( ).
          WRITE:/ l_error_text.

      ENDTRY.
    ENDLOOP.

  ENDMETHOD.                    "convert_to_string_table

  METHOD get_string_type_for_structure.

    DATA: lo_type_des TYPE REF TO cl_abap_typedescr,
          lo_struct_desc TYPE REF TO cl_abap_structdescr,
          lt_comp_tab TYPE cl_abap_structdescr=>component_table,
          lo_string_comp_type TYPE REF TO cl_abap_elemdescr,
          lo_cast_error TYPE REF TO cx_sy_move_cast_error,
          l_error_text TYPE string.

    FIELD-SYMBOLS: <comp> TYPE abap_componentdescr,
                   <structure_record> TYPE abap_compdescr,
                   <table_field_data> TYPE ANY.

    TRY.
        " Get the structure definition of one line of the table
        CALL METHOD cl_abap_typedescr=>describe_by_data
          EXPORTING
            p_data      = et_structure_in
          RECEIVING
            p_descr_ref = lo_type_des.

        " Cast the type description to the narrower structure description
        lo_struct_desc ?= lo_type_des.

        " Get all the components of the structure
        it_struct = lo_struct_desc->components.

        " Loop through all the fields in the table record
        " and create a dynamic structure of type char
        LOOP AT it_struct ASSIGNING <structure_record>.
          " Add a new line to the structure component table
          APPEND INITIAL LINE TO lt_comp_tab ASSIGNING <comp>.

          " Assign the table field to a field symbol
          ASSIGN COMPONENT <structure_record>-name OF STRUCTURE et_structure_in TO <table_field_data>.

          CHECK sy-subrc = 0.

          " This logic will be used to convert the types to the equivalent string types
          CASE <structure_record>-type_kind.
            WHEN 'C' OR 'I'.
              " Get a reference to a char with a dynamic string length
              lo_string_comp_type = cl_abap_elemdescr=>get_c( <structure_record>-length ).
            WHEN 'N'.
              " Get a reference to a char with a dynamic string length
              lo_string_comp_type = cl_abap_elemdescr=>get_n( <structure_record>-length ).
            WHEN 'D'.
              " Get a reference to a char with a dynamic string length
              lo_string_comp_type = cl_abap_elemdescr=>get_d( ).
            WHEN 'F'.
              " Get a reference to a char with a dynamic string length
              " For F 2 digits are stored in each byte and the last digit contains a sign
              " A final addition is to add 6 chars for the exponential
              <structure_record>-length =  ( <structure_record>-length * 2 ) + 6 .
              lo_string_comp_type = cl_abap_elemdescr=>get_c( <structure_record>-length ).
            WHEN 'T'.
              " Get a reference to a char with a dynamic string length
              lo_string_comp_type = cl_abap_elemdescr=>get_t( ).
            WHEN 'P'.
              " Get a reference to a char with a dynamic string length
              " For P 2 digits are stored in each byte and the last digit contains a sign
              " A final addition is to add the decimal place
              <structure_record>-length =  ( <structure_record>-length * 2 ) + 1 .
              lo_string_comp_type = cl_abap_elemdescr=>get_c( <structure_record>-length ).
          ENDCASE.

          " Update the name and the type for the component of our dynamic structure
          <comp>-name = <structure_record>-name.
          <comp>-type = lo_string_comp_type.

        ENDLOOP.

        io_structure_string_type_def = cl_abap_structdescr=>create( lt_comp_tab ).

      CATCH cx_sy_move_cast_error INTO lo_cast_error.
        l_error_text = lo_cast_error->get_text( ).

        RAISE EXCEPTION TYPE lcx_str_conversion_excp
            EXPORTING e_additional_error_text = l_error_text.

    ENDTRY.
  ENDMETHOD.                    "get_string_type_for_structure

ENDCLASS.                    "lcl_string_utilities IMPLEMENTATION

*----------------------------------------------------------------------*
*       CLASS lcl_test_string_utilities IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_test_string_utilities IMPLEMENTATION.
  METHOD execute_program.
    DATA: lt_bseg TYPE STANDARD TABLE OF bseg,
          lt_string TYPE stringtab.

    FIELD-SYMBOLS: <out_string> TYPE string.

    " Get some data from a table. In my example I chose bseg
    SELECT  *
      UP TO 10 ROWS
      FROM bseg
      INTO TABLE lt_bseg.           "#EC * Not a great select but it's a test program

    " Now pass the contents to the utility class to convert to a fixed width
    " string table
    CALL METHOD lcl_string_utilities=>convert_to_fixed_string_table
      EXPORTING
        et_table_in         = lt_bseg
      IMPORTING
        it_string_table_out = lt_string.

    LOOP AT lt_string ASSIGNING <out_string>.
      WRITE:/ <out_string>.
    ENDLOOP.
  ENDMETHOD.                    "execute_program

ENDCLASS.                    "lcl_test_string_utilities IMPLEMENTATION

START-OF-SELECTION.

  lcl_test_string_utilities=>execute_program( ).
try
{  DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);  
 
DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/JMS","DCJMSMessageProperty1");  
 
String MycontractID = conf.get(key);  
 
return MycontractID;
}
catch (Exception e)
{
String exception = e.toString();  
return exception;
}

In a passthrough File to File scenarios (i.e no IR objects involved), there are quite a few times when we have to create a dynamic file names on a receiver (FTP/NFS) application side with some part of source file name.
Take an instance where source is sending a file having name as "Source_123_TimeStamp.txt" and on target Side we want something like "Target_123_TimeStamp.txt". So in order to achieve this we have to do some work arounds.
Here i am jotting one of the ways in which we can achieve this requirement by using Custom Adapter module.
 

Note: This code is very generic you can tweak it to accomplish your requirement. 

package com.DynamicName;

import java.rmi.RemoteException;

import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.ejb.TimedObject;
import javax.ejb.Timer;
import com.sap.aii.af.lib.mp.module.ModuleContext;
import com.sap.aii.af.lib.mp.module.ModuleData;
import com.sap.aii.af.lib.mp.module.ModuleException;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.engine.interfaces.messaging.api.Message;
import com.sap.engine.interfaces.messaging.api.MessageKey;
import com.sap.engine.interfaces.messaging.api.MessagePropertyKey;
import com.sap.engine.interfaces.messaging.api.XMLPayload;
import com.sap.engine.interfaces.messaging.api.auditlog.AuditLogStatus;
import java.util.Calendar;
import java.text.SimpleDateFormat;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;

import java.io.InputStream;




/**
 * @author AMISRIVA
 *
 */
public class DynamicNameBean implements SessionBean, TimedObject {

	/* (non-Javadoc)
	 * @see javax.ejb.SessionBean#ejbActivate()
	 */
	public void ejbActivate() throws EJBException, RemoteException {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see javax.ejb.SessionBean#ejbPassivate()
	 */
	private SessionContext myContext;
	public void ejbPassivate() throws EJBException, RemoteException {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see javax.ejb.SessionBean#ejbRemove()
	 */
	public void ejbRemove() throws EJBException, RemoteException {
		// TODO Auto-generated method stub

	}

	/* (non-Javadoc)
	 * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
	 */
	public void setSessionContext(SessionContext context) throws EJBException,
	RemoteException {
		myContext = context;
	}

	/* (non-Javadoc)
	 * @see javax.ejb.TimedObject#ejbTimeout(javax.ejb.Timer)
	 */
	public void ejbTimeout(Timer arg0) {
		// TODO Auto-generated method stub

	}

	public void ejbCreate() throws javax.ejb.CreateException {

	}

	public ModuleData process(ModuleContext mc,ModuleData inputModuleData)throws ModuleException {
		Object obj = null;
		Message msg = null;
		MessageKey amk = null;

		String filename = null;

		try{
			// Retrieves the current principle data, usually the message , Return type is Object
			obj = inputModuleData.getPrincipalData();
			// A Message is what an application sends or receives when interacting with the Messaging System.
			msg = (Message) obj;
			// MessageKey consists of a message Id string and the MessageDirection
			amk = new MessageKey(msg.getMessageId(),msg.getMessageDirection());
			// Audit log message will appear in MDT of Channel Monitoring
			Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS,"Dynamic File name Module called");
			// Returns the main document as XMLPayload
			XMLPayload xpld = msg.getDocument();
			//Reading the file name from message header
     		MessagePropertyKey mpk = new MessagePropertyKey("FileName","http://sap.com/xi/XI/System/File");
			filename = msg.getMessageProperty(mpk);
			Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "filename is" +filename );

			if(filename == null || filename.length() == 0)
			{
				Audit.addAuditLogEntry(amk, AuditLogStatus.WARNING, "Message Property FileName does not exist");
				filename = "Default";
			}

			String [] temp = filename.split("_");

			//setting the current date and time
			 Calendar currentDate = Calendar.getInstance();
			  SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
			  String CurrentDate = formatter.format(currentDate.getTime());

			  String output = temp[1] + "_" + CurrentDate + ".txt";

			  //setting the new file name in the message header
			msg.setMessageProperty("http://sap.com/xi/XI/System/File","FileName",output);
     		 Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "filename is" +output );
			 Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "File name is Successfully set");

				    // Sets the principle data that represents usually the message to be processed
		    Audit.addAuditLogEntry(amk, AuditLogStatus.SUCCESS, "Message Successfully updated");
		    inputModuleData.setPrincipalData(msg);

		}catch(Exception e) {
			Audit.addAuditLogEntry(amk, AuditLogStatus.ERROR,"Module Exception caught");
			ModuleException me = new ModuleException(e);
			throw me;
		}
		return inputModuleData;
	}



}

Once done with coding part you have to deploy this custom module on PI server (there are many links/blogs available regarding the same).

Setting in PI communication channels:
1) File sender adapter: Check ASMA (FileName) in sender adapter.
2) File Receiver adapter: under module tab add your custom adapter module created (basically its JNDI name).
3) File receiver adapter: Check ASMA(FileName) in file receiver adapter.

/*
 *Module To Validate EDIANSIX12 Header Segments
 *
 *
 */


import java.io.ByteArrayOutputStream;
import javax.ejb.CreateException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;

import com.sap.aii.af.mp.module.Module;
import com.sap.aii.af.mp.module.ModuleContext;
import com.sap.aii.af.mp.module.ModuleData;
import com.sap.aii.af.mp.module.ModuleException;
import com.sap.aii.af.ra.ms.api.Message;
import com.sap.aii.af.ra.ms.api.MessageDirection;
import com.sap.aii.af.ra.ms.api.TextPayload;
import com.sap.aii.af.service.auditlog.Audit;
import com.sap.aii.af.service.auditlog.AuditDirection;
import com.sap.aii.af.service.auditlog.AuditLogStatus;
import com.sap.aii.af.service.auditlog.AuditMessageKey;
import com.sap.aii.af.service.trace.Trace;

/**
* @ejbHome <{com.sap.aii.af.mp.module.ModuleHome}>
* @ejbLocal <{com.sap.aii.af.mp.module.ModuleLocal}>
* @ejbLocalHome <{com.sap.aii.af.mp.module.ModuleLocalHome}>
* @ejbRemote <{com.sap.aii.af.mp.module.ModuleRemote}>
* @stateless
*/
public class EDITransformer implements SessionBean, Module {
	private SessionContext myContext;
	Object obj = null;
	Message msg = null;
	private static String strISA = "", strGS = "", strST = "", strIEA = "";
	private static int ISAcount = 0, GScount = 0, STcount = 0;
	private static int transet_cnt = 0;
	private static String SType = "";
	private String[] strArr = null;

	public static final String VERSION_ID = "$Id:001$";
	private static final Trace trace = new Trace(VERSION_ID);

	public void ejbRemove() {
	}

	public void ejbActivate() {
	}

	public void ejbPassivate() {
	}

	public void setSessionContext(SessionContext context) {
		myContext = context;
	}

	public void ejbCreate() throws CreateException {
	}

	public ModuleData process(
		ModuleContext moduleContext,
		ModuleData inputModuleData)
		throws ModuleException {

		Element rootnode_target_1 = null,
			rootnode_target_2 = null,
			rootnode_target = null;
		Element child_node = null;
		NodeList node_lst = null;
		Node nd = null;
		Text txt_node = null;
		String nodeName = null;
		String edi_Str = "";
		String empname = null;
		String rslt_xml_str = "";
		int valid_chk = 0;
		AuditMessageKey amk = null;
		try {
			obj = inputModuleData.getPrincipalData();
			msg = (Message) obj;
			if (msg.getMessageDirection().equals(MessageDirection.OUTBOUND))
				amk =
					new AuditMessageKey(
						msg.getMessageId(),
						AuditDirection.OUTBOUND);
			else
				amk =
					new AuditMessageKey(
						msg.getMessageId(),
						AuditDirection.INBOUND);
			Audit.addAuditLogEntry(
				amk,
				AuditLogStatus.SUCCESS,
				"EDIProcess:Module called");
		} catch (Exception e) {
			ModuleException me = new ModuleException(e);
			throw me;
		}

		try {
			//XMLPayload xmlpayload = msg.getDocument();
			TextPayload xmlpayload = msg.getDocument();
			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			//Document doc = db.parse((InputStream) xmlpayload.getInputStream());
			Document new_doc = db.newDocument();
			rootnode_target = new_doc.createElement("ns0:MT_edi");
			rootnode_target.setAttribute(
				"xmlns:ns0",
				"http://yash.com/yh1302/CaseStudy1");
			new_doc.appendChild(rootnode_target);
			//node_lst = doc.getElementsByTagName("SDATA");
			edi_Str = xmlpayload.getText();
//			for (int i = 0; i < node_lst.getLength(); i++) {
//				nd = node_lst.item(i);
//				nodeName = nd.getNodeName();
//				edi_Str = edi_Str + nd.getFirstChild().getNodeValue();
//			}
			rootnode_target_1 = new_doc.createElement("RECORDSET");
			strArr = edi_Str.split("[~]");
			for (int i = 0; i < strArr.length; i++) {
				rootnode_target_2 = new_doc.createElement("RECORD");
				child_node = new_doc.createElement("SDATA");
				valid_chk = validateEDI(strArr[i], i, strArr.length - 1);
				ExceptionHandler(valid_chk, strArr[i]);
				txt_node = new_doc.createTextNode(strArr[i]);
				child_node.appendChild(txt_node);
				rootnode_target_2.appendChild(child_node);
				rootnode_target_1.appendChild(rootnode_target_2);

			}
			rootnode_target.appendChild(rootnode_target_1);
			ByteArrayOutputStream myBytes = new ByteArrayOutputStream();
			StreamResult trgt = new StreamResult(myBytes);
			Source src = new DOMSource(new_doc);
			TransformerFactory tFactory = TransformerFactory.newInstance();
			Transformer transformer = tFactory.newTransformer();
			transformer.transform(src, trgt);
			byte[] docContent = myBytes.toByteArray();

			if (docContent != null) {
				xmlpayload.setContent(docContent);
				inputModuleData.setPrincipalData(msg);
				Audit.addAuditLogEntry(
								amk,
								AuditLogStatus.SUCCESS,
								"EDIProcess:Message Processed");
			}

		} catch (Exception e) {
			ModuleException me = new ModuleException(e);
			throw me;
		}

		return inputModuleData;
	}

	public int validateEDI(String strMsg, int curr_line, int maxlen) {
		int rslt_value = 0;
		String[] eleArr = strMsg.split("[*]");
		if (curr_line == 0) {
			strISA = eleArr[0];
			if (!strISA.equals("ISA")) {
				rslt_value = 6;
			} else {
				ISAcount = Integer.parseInt(eleArr[13]);
				if (eleArr[5].trim().length() == 0
					|| eleArr[6].trim().length() == 0
					|| eleArr[7].trim().length() == 0
					|| eleArr[8].trim().length() == 0)
					rslt_value = 4;
			}

		} else if (curr_line == 1) {
			strGS = eleArr[0];
			GScount = Integer.parseInt(eleArr[6]);
		} else if (curr_line == 2) {
			transet_cnt++;
			strST = eleArr[0];
			STcount = Integer.parseInt(eleArr[2]);
			SType = eleArr[1];

		} else {

			if (eleArr[0].equals("SE") || eleArr[0].equals("ST")) {
				transet_cnt++;
				if (eleArr[0].equals("SE") && strST.equals("ST")) {
					strST = eleArr[0];
					if (Integer.parseInt(eleArr[1]) != transet_cnt)
						rslt_value = 5;
					if (Integer.parseInt(eleArr[2]) != STcount)
						rslt_value = 2;
					transet_cnt = 0;
				} else if (eleArr[0].equals("ST") && strST.equals("SE")) {
					strST = eleArr[0];
					STcount = Integer.parseInt(eleArr[2]);
					SType = eleArr[1];
				} else {
					rslt_value = 2;
				}

			} else if (eleArr[0].equals("GS") || eleArr[0].equals("GE")) {
				if (eleArr[0].equals("GS") && strGS.equals("GE")) {
					strGS = eleArr[0];
					GScount = Integer.parseInt(eleArr[6]);
				} else if (eleArr[0].equals("GE") && strGS.equals("GS")) {
					strGS = eleArr[0];
					if (Integer.parseInt(eleArr[2]) != GScount)
						rslt_value = 1;
				} else {
					rslt_value = 1;
				}
			} else if (eleArr[0].equals("ISA")) {
				rslt_value = 3;
			} else if (eleArr[0].equals("IEA")) {
				strIEA = eleArr[0];
				if (Integer.parseInt(eleArr[2]) != ISAcount)
					rslt_value = 3;
				if (!strST.equals("SE"))
					rslt_value = 2;
				if (!strGS.equals("GE"))
					rslt_value = 1;

			} else if (curr_line == maxlen) {
				if (strIEA.equals(""))
					rslt_value = 7;
			} else {
				transet_cnt++;
				if (SType.equals("850") && transet_cnt > 1) {
					EDI850Validate insEDI = new EDI850Validate();
					insEDI.validateEDI850(eleArr, strArr);
				}

			}
		}
		return rslt_value;
	}

	public void ExceptionHandler(int exec_type, String segment_line) {

		switch (exec_type) {
			case 1 :
				trace.debugT(
					EDIConstants.GS_GE_DATA_SEGMENT_NOT_EQUAL,
					segment_line);
				throw new RuntimeException(
					"GS_GE_DATA_SEGMENT_NOT_EQUAL:"
						+ EDIConstants.GS_GE_DATA_SEGMENT_NOT_EQUAL
						+ segment_line);
			case 2 :
				trace.debugT(
					EDIConstants.ST_SE_DATA_SEGMENT_NOT_EQUAL,
					segment_line);
				throw new RuntimeException(
					"ST_SE_DATA_SEGMENT_NOT_EQUAL:"
						+ EDIConstants.ST_SE_DATA_SEGMENT_NOT_EQUAL
						+ segment_line);
			case 3 :
				trace.debugT(
					EDIConstants.ISA_IEA_DATA_SEGMENT_MISMATCH,
					segment_line);
				throw new RuntimeException(
					"ISA_IEA_DATA_SEGMENT_MISMATCH:"
						+ EDIConstants.ISA_IEA_DATA_SEGMENT_MISMATCH
						+ segment_line);
			case 4 :
				trace.debugT(EDIConstants.ISA_IEA_DATA_NOT_VALID, segment_line);
				throw new RuntimeException(
					"ISA_IEA_DATA_NOT_VALID:"
						+ EDIConstants.ISA_IEA_DATA_NOT_VALID
						+ segment_line);
			case 5 :
				trace.debugT(
					EDIConstants.MISMATCH_NUMBET_OF_SE_DATA_SEGMENT,
					segment_line);
				throw new RuntimeException(
					"MISMATCH_NUMBET_OF_SE_DATA_SEGMENT:"
						+ EDIConstants.MISMATCH_NUMBET_OF_SE_DATA_SEGMENT
						+ segment_line);
			case 6 :
				trace.debugT(EDIConstants.ISA_SEGMENT_NOT_FOUND, segment_line);
				throw new RuntimeException(
					"ISA_SEGMENT_NOT_FOUND:"
						+ EDIConstants.ISA_SEGMENT_NOT_FOUND
						+ segment_line);
			case 7 :
				trace.debugT(EDIConstants.IEA_SEGMENT_NOT_FOUND, segment_line);
				throw new RuntimeException(
					"IEA_SEGMENT_NOT_FOUND:"
						+ EDIConstants.IEA_SEGMENT_NOT_FOUND
						+ segment_line);
			case 8 :
				trace.debugT(EDIConstants.ST_SEGMENT_NOT_FOUND, segment_line);
				throw new RuntimeException(
					"ST_SEGMENT_NOT_FOUND:"
						+ EDIConstants.ST_SEGMENT_NOT_FOUND);
			case 9 :
				trace.debugT(EDIConstants.GS_SEGMENT_NOT_FOUND, segment_line);
				throw new RuntimeException(
					"GS_SEGMENT_NOT_FOUND:"
						+ EDIConstants.GS_SEGMENT_NOT_FOUND);

		};
	}

}

Class to validate PurchaseOrder Detail Segments(850)

import java.util.Map;



/**
 * @author Prasanna.Mynam
 *
 * To change the template for this generated type comment go to
 *  */
public class EDI850Validate {
	private Map param = null;
	private static String segBEG = "";


	public void validateEDI850(String[] tranSetSeg, String[] segArr) {
		if (tranSetSeg[0].equals("BEG")) {
			segBEG = tranSetSeg[0];
			if (tranSetSeg[1].trim().length() < 2
				|| tranSetSeg[1].trim().length() > 2) {

				throw new RuntimeException(EDIConstants.BEG01_ELEMENT_LENGTH);
			} else {
				try {
					if (Integer.parseInt(tranSetSeg[1]) < 0
						|| Integer.parseInt(tranSetSeg[1]) > 99) {

						throw new RuntimeException(EDIConstants.BEG01_ELEMENT_NOTVALID);
					}

				} catch (Exception e) {

					throw new RuntimeException(EDIConstants.BEG01_ELEMENT_TYPE);
				}
			}

			if (!tranSetSeg[2].equals("DS") && !tranSetSeg[2].equals("KN")) {

				throw new RuntimeException(EDIConstants.BEG02_ELEMENT_NOTVALID);
			}
			if (tranSetSeg[3].trim().length() < 1
				|| tranSetSeg[3].trim().length() > 22) {

				throw new RuntimeException(EDIConstants.BEG03_ELEMENT_LENGTH);
			}
			if (tranSetSeg[5].trim().length() < 8
				|| tranSetSeg[5].trim().length() > 8) {

				throw new RuntimeException(EDIConstants.BEG05_ELEMENT_LENGTH);
			}

		} else if (tranSetSeg[0].equals("CURR")) {
			if (!tranSetSeg[1].equals("BT")) {

				throw new RuntimeException(EDIConstants.CUR01_ELEMENT_NOTVALID);
			}
		} else if (tranSetSeg[0].equals("REF")) {
			if (!tranSetSeg[1].equals("06")
				&& !tranSetSeg[1].equals("8M")
				&& !tranSetSeg[1].equals("DP")
				&& !tranSetSeg[1].equals("ON")
				&& !tranSetSeg[1].equals("PO")) {

				throw new RuntimeException(EDIConstants.REF01_ELEMENT_NOTVALID);
			}

		} else if (tranSetSeg[0].equals("PER")) {
			if (!tranSetSeg[1].equals("AE") && !tranSetSeg[1].equals("OC")) {

				throw new RuntimeException(EDIConstants.PER01_ELEMENT_NOTVALID);
			}

		} else if (tranSetSeg[0].equals("FOB")) {
			if (!tranSetSeg[1].equals("PC")) {

				throw new RuntimeException(EDIConstants.FOB01_ELEMENT_NOTVALID);
			}

		} else if (tranSetSeg[0].equals("AMT")) {
			if (!tranSetSeg[1].equals("F7")
				&& !tranSetSeg[1].equals("GV")
				&& !tranSetSeg[1].equals("1")
				&& !tranSetSeg[1].equals("UI")) {

				throw new RuntimeException(EDIConstants.AMT01_ELEMENT_NOTVALID);
			}

			if (tranSetSeg[2].trim().length() < 1
				|| tranSetSeg[2].trim().length() > 18) {

				throw new RuntimeException(EDIConstants.AMT02_ELEMENT_LENGTH);
			}

		} else if (tranSetSeg[0].equals("N9")) {
			if (!tranSetSeg[1].equals("ZZ")) {

				throw new RuntimeException(EDIConstants.N901_ELEMENT_LENGTH);
			}

		} else if (tranSetSeg[0].equals("MSG")) {
			if (tranSetSeg[1].trim().length() < 1
				&& tranSetSeg[1].trim().length() > 264) {

				throw new RuntimeException(EDIConstants.MSG01_ELEMENT_LENGTH);
			}

		} else if (tranSetSeg[0].equals("N1")) {
			if (!tranSetSeg[1].equals("BT")
				&& !tranSetSeg[1].equals("ST")
				&& !tranSetSeg[1].equals("VN")) {

				throw new RuntimeException(EDIConstants.N101_ELEMENT_NOTVALID);
			}

		} else if (tranSetSeg[0].equals("N3")) {
			if (tranSetSeg[1].trim().length() < 1
				&& tranSetSeg[1].trim().length() > 55) {

				throw new RuntimeException(EDIConstants.N301_ELEMENT_LENGTH);
			}

		} else if (tranSetSeg[0].equals("PID")) {
			if (!tranSetSeg[1].equals("F")) {

				throw new RuntimeException(EDIConstants.PID01_ELEMENT_NOTVALID);
			}

		} else if (tranSetSeg[0].equals("TXI")) {
			if (!tranSetSeg[1].equals("TX")) {

				throw new RuntimeException(EDIConstants.TXTI01_ELEMENT_NOTVALID);
			}

		} else if (tranSetSeg[0].equals("SCH")) {
			if (tranSetSeg[1].trim().length() < 1
				|| tranSetSeg[1].trim().length() > 15) {

				throw new RuntimeException(EDIConstants.SCH01_ELEMENT_LENGTH);
			}

			if (tranSetSeg[2].trim().length() < 2
				|| tranSetSeg[2].trim().length() > 2) {

				throw new RuntimeException(EDIConstants.SCH02_ELEMENT_LENGTH);
			}

			if (!tranSetSeg[5].equals("002")) {

				throw new RuntimeException(EDIConstants.SCH05_ELEMENT_NOTVALID);

			}

			if (tranSetSeg[6].trim().length() < 8
				|| tranSetSeg[6].trim().length() > 8) {

				throw new RuntimeException(EDIConstants.SCH06_ELEMENT_LENGTH);
			}

		} else if (tranSetSeg[0].equals("CTT")) {
			if (tranSetSeg[1].trim().length() < 1
				|| tranSetSeg[1].trim().length() > 6) {

				throw new RuntimeException(EDIConstants.CTT01_ELEMENT_LENGTH);
			}

		}
		segManditChk(segArr);

	}

	public void segManditChk(String[] segArr) {
		int chkBEG = 0;
		int chkPO1 = 0;
		for (int i = 0; i < segArr.length; i++) {
			if (segArr[i].indexOf("BEG") == 0)
				chkBEG = 1;
			if (segArr[i].indexOf("PO1") == 0)
				chkPO1 = 1;
		}
		if (chkBEG == 0)
			throw new RuntimeException(EDIConstants.BEG_SEGMENT_MISSING);
		if (chkPO1 == 0)
			throw new RuntimeException("Manditory Segment PO1 is missing");

	}

}

Class contains the static constant for Exceptions

/**
 * @author Prasanna.Mynam
 *
 * To change the template for this generated type comment go to
 *  */
public class EDIConstants {
	public static final String GS_GE_DATA_SEGMENT_NOT_EQUAL =
		"GS and GE Data Segments Not Equal At ";
	public static final String ST_SE_DATA_SEGMENT_NOT_EQUAL =
		"ST and SE Data Segments Not Equal At ";
	public static final String ISA_IEA_DATA_SEGMENT_MISMATCH =
		"ISA and IEA Data Segments Not Equal At ";
	public static final String ISA_IEA_DATA_NOT_VALID =
		"ISA and IEA Data Not Valid At ";
	public static final String MISMATCH_NUMBET_OF_SE_DATA_SEGMENT =
		"Mismatch Number Of SE Data Segments At";
	public static final String ISA_SEGMENT_NOT_FOUND =
		"ISA Segment Not Found In Document";
	public static final String IEA_SEGMENT_NOT_FOUND =
		"IEA Segment Not Found In Document";
	public static final String ST_SEGMENT_NOT_FOUND =
		"ST Segment Not Found In Document";
	public static final String GS_SEGMENT_NOT_FOUND =
		"GS Segment Not Found In Document";
	public static final String BEG01_ELEMENT_LENGTH =
		"BEG01 is maditory element of max length 2";
	public static final String BEG01_ELEMENT_NOTVALID =
		"Invalid ID For Element BEG01";
	public static final String BEG01_ELEMENT_TYPE =
		"BEG01 Should Be Of Type ID";
	public static final String BEG02_ELEMENT_NOTVALID =
		"BEG02 is maditory element with either DS or KN value";
	public static final String BEG03_ELEMENT_LENGTH =
		"BEG03 is maditory element of max length 22";
	public static final String BEG05_ELEMENT_LENGTH =
		"BEG05 is maditory element of max length 8";
	public static final String CUR01_ELEMENT_NOTVALID =
		"CUR01 is maditory element with value BT";
	public static final String REF01_ELEMENT_NOTVALID =
		"Invalid Entry For REF01";
	public static final String PER01_ELEMENT_NOTVALID =
		"PER01 is maditory element valid";
	public static final String FOB01_ELEMENT_NOTVALID =
		"FOB01 is maditory element with value PC";
	public static final String AMT01_ELEMENT_NOTVALID =
		"Invalid Value Entry For Element AMT01";
	public static final String AMT02_ELEMENT_LENGTH =
		"AMT02 Exceed the max limit 18";
	public static final String N901_ELEMENT_LENGTH =
		"N901 is maditory element with value ZZ";
	public static final String MSG01_ELEMENT_LENGTH =
		"MSG01 Exceed The max length 264";
	public static final String N101_ELEMENT_NOTVALID = "Invalid Entry For N101";
	public static final String N301_ELEMENT_LENGTH =
		"N301 Exceed The max length 55";
	public static final String PID01_ELEMENT_NOTVALID =
		"PID01 is maditory element with value F";
	public static final String TXTI01_ELEMENT_NOTVALID =
		"TXI01 is maditory element with value TX";
	public static final String SCH01_ELEMENT_LENGTH =
		"SCH01 Exceeds The max length 15";
	public static final String SCH02_ELEMENT_LENGTH =
		"SCH02 Exceeds The max length 2";
	public static final String SCH05_ELEMENT_NOTVALID =
			"SCH05 is maditory element with value 002";
	public static final String SCH06_ELEMENT_LENGTH =
				"SCH06 Exceeds The max length 2";
	public static final String CTT01_ELEMENT_LENGTH =
					"CTT01 Exceeds The max length 6";
	public static final String BEG_SEGMENT_MISSING =
						"Manditory Segment BEG is missing";
	public static final String PO1_SEGMENT_MISSING =
							"Manditory Segment PO1 is missing";


}

Author: Jitesh Talreja

Submitted: 20/04/2009

Description:

This wiki provides the code snippet of Java Mapping for Flat File to IDOC scenario when it is difficult to use File Content Conversion (FCC).

Code has been developed as a Java Project using SAP Netweaver developer studio and then exported as a .jar file.


{ try
   {           Thread.sleep (40000);
    }
catch (InterruptedException ie){}
return a;
}

Thread.sleep will stop the processing of mapping for the given period of time. We need to provide the required time delay in the bracket as shown in code snippet. (40000). The time is in milli second. (40000) will give you the result after 40 sec.
I have used the try catch block to catch the thread exception.
We can use this UDF in between the main nodes to insert the delay. This is a small thing but very useful.

Author: Sergio Cipolla
Submitted: 03 July 2008

When Migrating from SAP R/3 4.7 to ECC 6.0, Integration engine tables (SXMS*) that in 4.7 were client independent, became client dependent in ECC, so the field MANDT is part of the table key.
Technically the client is as well available in 4.7 but it is an attribute of some tables (CLIENT in SXMSPMAST).

During the upgrade procedure, the conversion of these tables (in particular SXMSCLUP and SXMSCLUR, which contain the message payload as raw string) can require much time, for these reason it is necessary to keep them as small as possible in order to minimise the downtime. We estimated that it might take more or less 1 hour to convert 300K messages in SXMSCLUP.

For this reason it is necessary to analise tables in 4.7 to see the number of records of each table, being able to separate records related to messages of different clients, records related to messages older then a specific period.
For messages older then x days it is necessary to group them by their status in order to understand why they were not deleted by the archiving/deletion procedure and how to correct or flag them for archiving/deletion.

Table analyser (transaction TAANA) and SE16 are not enough, because of filtering conditions and join between different tables, additionally you might need to be able to see all these information quickly and daily to keep the evolution of tables under control, for this reason I have developed a report that does exactly this analysis playing around with tables:

  • SXMSPHIST(2)
  • SXMSPMAST(2)
  • SXMSPVERS(2)
  • SXMSPEMAS(2)
  • SXMSPERROR(2)
  • SXMSCLUP
  • SXMSCLUR

This report runs on both R/3 4.7, ECC 6.0 (and XI/PI) 

 *&---------------------------------------------------------------------*
*& Report  Z_SXMB_ANALYZER
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT  z_sxmb_analyzer.

SELECTION-SCREEN BEGIN OF BLOCK tblock1  WITH FRAME TITLE txt001.
PARAMETERS:
  p_show AS CHECKBOX DEFAULT 'X',
  p_count AS CHECKBOX DEFAULT 'X',
  p_sort AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK tblock1.

SELECTION-SCREEN BEGIN OF BLOCK tblock2  WITH FRAME TITLE txt002.
PARAMETERS:
  p_c_old AS CHECKBOX DEFAULT 'X',
  p_older TYPE i DEFAULT 30,
  p_old_st AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK tblock2.

********************************************************************************
INITIALIZATION.
  txt001 = 'Analysis'.
  txt002 = 'Statistic'.

  %_p_show_%_app_% = 'Show Archiving configuration'.
  %_p_count_%_app_% = 'Count msg in all XI tables'.
  %_p_sort_%_app_% = 'Order By Client'.
  %_p_c_old_%_app_% = 'Count msg older then'.
  %_p_older_%_app_% = ' days'.
  %_p_old_st_%_app_% = ' List status for old messages'.

********************************************************************************
START-OF-SELECTION.

  TYPES: BEGIN OF l_count,
    client  TYPE mandt,
    counter TYPE i,
    msgstate TYPE sxmspmstat,
  END OF l_count.

  TYPES: BEGIN OF l_global_result,
    client  TYPE mandt,
    tabname(10) TYPE c,
    counter TYPE i,
    msgstate TYPE sxmspmstat,
  END OF l_global_result.

  TYPES: BEGIN OF l_sxmsmstat,
      icon_id(4) TYPE c,
      msgtxt TYPE text60,
  END OF l_sxmsmstat.

  DATA :
        l_clause TYPE string,
        lt_tabname TYPE STANDARD TABLE OF string,
        l_tabname(10) TYPE c,
        l_counter TYPE i,
        l_string TYPE string.

  DATA :
        l_date TYPE sy-datum,
        l_time TYPE sy-uzeit,
        l_temp(23) TYPE c,
        l_timestamp(14) TYPE c,
        l_tstamp TYPE timestampl,
        l_source TYPE string.


  DATA: lt_total_count TYPE TABLE OF l_global_result.

*Prepare timestamp
  GET TIME.
  l_date = sy-datum.
  l_time = sy-uzeit.

  l_date = l_date - p_older.
  CONVERT TIME l_time DATE l_date INTO TIME STAMP l_tstamp TIME ZONE sy-zonlo.

  WRITE l_tstamp TO l_temp.
  WRITE l_temp(14) TO l_timestamp.

  DATA: l_days TYPE string.
  l_days = p_older.

*Show Archiving Configuration
  IF p_show EQ 'X'.
    l_string = 'Archiving configuration'.
    WRITE: / l_string COLOR COL_POSITIVE.

    DATA :
          lt_sxmsconfvlv TYPE TABLE OF sxmsconfvl,
          l_descr(60) TYPE c,
          l_int TYPE n.

    FIELD-SYMBOLS <fs> TYPE sxmsconfvl.

    SELECT *
    FROM sxmsconfvl
    INTO TABLE lt_sxmsconfvlv
    WHERE area = 'ARCHIVE'
    OR area = 'DELETION'.
    LOOP AT lt_sxmsconfvlv ASSIGNING <fs>.
      l_int = <fs>-value.
      IF <fs>-area ='ARCHIVE' AND <fs>-param = 'PERSIST_DURATION' AND <fs>-subparam = 'ASYNC'.
	l_descr = 'XML Messages Without Errors Awaiting Archiving '.
      ELSEIF <fs>-area = 'DELETION' AND <fs>-param = 'PERSIST_DURATION' AND <fs>-subparam = 'ASYNC'.
	l_descr = 'Asynch. XML Messages Without Errors Awaiting Deletion'.
      ELSEIF <fs>-area = 'DELETION' AND <fs>-param = 'PERSIST_DURATION' AND <fs>-subparam =  'HISTORY'.
	l_descr =  'History Entries for Deleted XML Messages '.
      ELSEIF <fs>-area = 'DELETION' AND <fs>-param = 'PERSIST_DURATION' AND <fs>-subparam = 'SYNC'.
	l_descr =  'Asynch. XML Messages Without Errors Awaiting Deletion '.
      ELSEIF <fs>-area = 'DELETION' AND <fs>-param ='PERSIST_DURATION_ERROR' AND <fs>-subparam = 'SYNC'.
	l_descr  = 'Synch. XML Messages with Errors Awaiting Deletion '.
      ELSE.
        CONTINUE.
      ENDIF.
      WRITE : / l_descr ,': ', l_int , ' (days)'.

    ENDLOOP.
  ENDIF.


*Start Count of messages
  IF p_count EQ 'X'.
    CLEAR lt_tabname.
    REFRESH lt_tabname.
    CLEAR lT_TOTAL_COUNT.
    REFRESH lT_TOTAL_COUNT.

    APPEND 'SXMSPMAST' TO lt_tabname.
    APPEND 'SXMSPVERS' TO lt_tabname.
    APPEND 'SXMSPHIST' TO lt_tabname.

    APPEND 'SXMSPEMAS' TO lt_tabname.
    APPEND 'SXMSPERROR' TO lt_tabname.

    APPEND 'SXMSCLUP' TO lt_tabname.
    APPEND 'SXMSCLUR' TO lt_tabname.

    APPEND 'SXMSPMAST2' TO lt_tabname.
    APPEND 'SXMSPVERS2' TO lt_tabname.
    APPEND 'SXMSPHIST2' TO lt_tabname.

    APPEND 'SXMSPEMAS2' TO lt_tabname.
    APPEND 'SXMSPERRO2' TO lt_tabname.

    l_string = 'Records for all Messages in Integration Engine'.
    WRITE: / l_string COLOR COL_POSITIVE.

    LOOP AT lt_tabname INTO l_tabname.
      CLEAR l_source.
      PERFORM get_sql_source USING l_tabname CHANGING l_source.
      PERFORM count_records USING l_source '' 1.
    ENDLOOP.

    PERFORM print_result.
  ENDIF.

  IF p_c_old EQ 'X'.
    CLEAR lt_tabname.
    REFRESH lt_tabname.
    CLEAR lT_TOTAL_COUNT.
    REFRESH lT_TOTAL_COUNT.

    APPEND 'SXMSPMAST' TO lt_tabname.
    APPEND 'SXMSPVERS' TO lt_tabname.
    APPEND 'SXMSPHIST' TO lt_tabname.
    APPEND 'SXMSPEMAS' TO lt_tabname.
    APPEND 'SXMSPERROR' TO lt_tabname.

    APPEND 'SXMSPMAST2' TO lt_tabname.
    APPEND 'SXMSPVERS2' TO lt_tabname.
    APPEND 'SXMSPHIST2' TO lt_tabname.
    APPEND 'SXMSPEMAS2' TO lt_tabname.
    APPEND 'SXMSPERRO2' TO lt_tabname.
    CLEAR l_string.
    CONCATENATE 'Records for all Messages in Integration Engine older then ' l_days 'days (' l_date ')' INTO l_string IN CHARACTER MODE SEPARATED BY space.
    WRITE: /''.
    WRITE: / l_string COLOR COL_POSITIVE.

    LOOP AT lt_tabname INTO l_tabname.
      PERFORM get_sql_source USING l_tabname CHANGING l_source.
      PERFORM get_sql_clause USING l_tabname l_timestamp CHANGING l_clause.
      PERFORM count_records USING l_source l_clause 1.
    ENDLOOP.
	PERFORM print_result.
  ENDIF.

*List the status for Old Records
  IF p_old_st EQ 'X'.
    CLEAR lt_tabname.
    REFRESH lt_tabname.
    CLEAR lT_TOTAL_COUNT.
    REFRESH lT_TOTAL_COUNT.

    APPEND 'SXMSPMAST' TO lt_tabname.
    APPEND 'SXMSPMAST2' TO lt_tabname.

    CLEAR l_string.
    CONCATENATE 'Status of records for all Messages in Integration Engine older then ' l_days 'days (' l_date ')' INTO l_string SEPARATED BY space.
    WRITE: /''.
    WRITE: / l_string COLOR COL_POSITIVE.

    LOOP AT lt_tabname INTO l_tabname.
      PERFORM get_sql_source USING l_tabname CHANGING l_source.
      PERFORM get_sql_clause USING l_tabname l_timestamp CHANGING l_clause.
      PERFORM count_records USING l_source l_clause 2.
    ENDLOOP.

  ENDIF.

*&---------------------------------------------------------------------*
*&      Form  COUNT_RECORDS
*&---------------------------------------------------------------------*
FORM count_records USING p_source TYPE string
        		 p_clause TYPE string
        		 p_querynum TYPE i.

  DATA:
        lt_tablecount TYPE TABLE OF l_count,
        lw_tablecount TYPE l_count.

  DATA: lw_res LIKE LINE OF lT_TOTAL_COUNT.

  CASE p_querynum.
    WHEN 1.
      IF p_source EQ 'SXMSCLUP' OR p_source EQ 'SXMSCLUR'.
        SELECT COUNT(*) INTO l_counter FROM (p_source).
        lw_res-TABNAME = l_tabname.
        lw_res-CLIENT = '***'.
        lw_res-COUNTER = l_counter.
        APPEND LW_RES TO LT_TOTAL_COUNT.
        clear lw_res.
        CLEAR l_counter.
        RETURN.
      ENDIF.

      IF p_clause IS INITIAL.
        SELECT client COUNT(*) AS counter
             INTO CORRESPONDING FIELDS OF TABLE lt_tablecount
             FROM (p_source)
             GROUP BY client.
        LOOP AT lt_tablecount INTO lw_tablecount.
        lw_res-TABNAME = l_tabname.
        lw_res-CLIENT = lw_tablecount-client.
        lw_res-COUNTER = lw_tablecount-counter.
        APPEND LW_RES TO LT_TOTAL_COUNT.
        clear lw_res.
        ENDLOOP.
      ELSE.
        SELECT client COUNT(*) AS counter
             INTO CORRESPONDING FIELDS OF TABLE lt_tablecount
             FROM (p_source)
            WHERE (p_clause)
             GROUP BY client.
        LOOP AT lt_tablecount INTO lw_tablecount.
        lw_res-TABNAME = l_tabname.
        lw_res-CLIENT = lw_tablecount-client.
        lw_res-COUNTER = lw_tablecount-counter.
        APPEND LW_RES TO LT_TOTAL_COUNT.
        clear lw_res.
        ENDLOOP.
      ENDIF.
    WHEN 2.
      SELECT  client msgstate COUNT(*) AS counter
            INTO CORRESPONDING FIELDS OF TABLE lt_tablecount
            FROM (p_source)
           WHERE (p_clause)
            GROUP BY client msgstate.

      DATA: lw_sxmsmstat TYPE l_sxmsmstat,
            lw_sxmsmstatt TYPE l_sxmsmstat.

      LOOP AT lt_tablecount INTO lw_tablecount.

        IF sy-saprl = '620'.
          CLEAR: lw_sxmsmstatt, lw_sxmsmstat.

          DATA:
            l_icon_id TYPE tv_image,
            l_msgtxt TYPE textpool-entry.

          sy-langu = 'E'.
          CALL FUNCTION 'SXMB_GET_ICON_FOR_MSG_STATE'
            EXPORTING
              im_state = lw_tablecount-msgstate
            IMPORTING
              ex_icon  = l_icon_id
              ex_text  = l_msgtxt.

          l_icon_id+3(1) = '@'.
          lw_sxmsmstat-icon_id = l_icon_id(4).
          lw_sxmsmstatt-msgtxt = l_msgtxt.
        ELSE.
          DATA: l_lab_tabname TYPE string.

          l_lab_tabname = 'sxmsmstat'.
          SELECT SINGLE *
          FROM (l_lab_tabname)
          INTO CORRESPONDING FIELDS OF lw_sxmsmstat
          WHERE msgstate = lw_tablecount-msgstate.

          l_lab_tabname = 'sxmsmstatt'.
          SELECT SINGLE *
          FROM (l_lab_tabname)
          INTO CORRESPONDING FIELDS OF lw_sxmsmstatt
          WHERE msgstate = lw_tablecount-msgstate
          AND langu = 'EN'.

        ENDIF.

        WRITE : /  '[', lw_tablecount-client,'] ',  lw_sxmsmstat-icon_id, ' (', lw_tablecount-msgstate, ')', lw_sxmsmstatt-msgtxt , ': ',lw_tablecount-counter.
      ENDLOOP.

  ENDCASE.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_SOURCE_CONDITION
*&---------------------------------------------------------------------*
FORM get_sql_source USING p_tabname TYPE c
                    CHANGING p_source  TYPE string.


  CLEAR p_source.
  CASE p_tabname.
    WHEN 'SXMSPMAST' OR 'SXMSPVERS' OR 'SXMSPHIST' OR 'SXMSPMAST2' OR 'SXMSPVERS2' OR 'SXMSPHIST2' OR 'SXMSCLUP' OR 'SXMSCLUR'.
      p_source = p_tabname.
    WHEN 'SXMSPEMAS' OR 'SXMSPERROR'.
      CONCATENATE p_tabname 'AS p INNER JOIN sxmspmast AS m ON p~msgguid = m~msgguid AND p~pid = m~pid' INTO p_source SEPARATED BY space.
    WHEN 'SXMSPEMAS2' OR 'SXMSPERRO2'.
      CONCATENATE p_tabname 'AS p INNER JOIN sxmspmast2 AS m ON p~msgguid = m~msgguid AND p~pid = m~pid' INTO p_source SEPARATED BY space.
  ENDCASE.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  GET_SQL_CLAUSE
*&---------------------------------------------------------------------*
FORM get_sql_clause USING p_tabname TYPE c
                          p_timestamp TYPE c
                    CHANGING p_clause TYPE string.

  CLEAR p_clause.
  CASE p_tabname.
    WHEN 'SXMSPMAST' OR  'SXMSPMAST2'.
      CONCATENATE 'EXETIMEST LT '  ' '''  p_timestamp '''' INTO p_clause.
    WHEN 'SXMSPHIST' OR 'SXMSPHIST2'.
      CONCATENATE  'EXEENDTST LT '  ' ''' p_timestamp '''' INTO p_clause.
    WHEN 'SXMSPVERS' OR 'SXMSPVERS2'.
      CONCATENATE 'TIMESTAMP LT '  ' ''' p_timestamp '''' INTO p_clause.
    WHEN 'SXMSPEMAS' OR 'SXMSPERROR' OR 'SXMSPEMAS2' OR 'SXMSPERRO2'.
      CONCATENATE 'm~EXETIMEST LT '  ' '''  p_timestamp '''' INTO p_clause.
  ENDCASE.

ENDFORM.
*&---------------------------------------------------------------------*
*&      Form  PRINT_RESULT
*&---------------------------------------------------------------------*
FORM print_result .

  FIELD-SYMBOLS <fs> LIKE LINE OF lT_TOTAL_COUNT.

  IF p_sort EQ 'X'.
    SORT lT_TOTAL_COUNT BY CLIENT DESCENDING.
  ENDIF.

  LOOP AT lT_TOTAL_COUNT ASSIGNING <fs>.
    WRITE : / <fs>-tabname, '[', <fs>-client,']: ', <fs>-counter.
  ENDLOOP.
ENDFORM.

Author: Peter Glas
Submitted: 08/09/2010
Related Links:

Java code for Parameterized XSLT mappings in PI7.1

PutDynConfMapper: 
package be.i8c.mapping;

import com.sap.aii.mapping.api.AbstractTransformation;
import com.sap.aii.mapping.api.StreamTransformationException;
import com.sap.aii.mapping.api.TransformationInput;
import com.sap.aii.mapping.api.TransformationOutput;

public class PutDynConfMapper
    extends AbstractTransformation {

       public void transform( TransformationInput in, TransformationOutput out)
            throws StreamTransformationException {
          // Copy the Payload
          PayloadCopier.copy(in.getInputPayload().getInputStream(),
               out.getOutputPayload().getOutputStream(),
          this.getTrace());
          // Put the inputparameters
          DynConfMapper.put(in.getInputParameters(), in.getDynamicConfiguration(), this.getTrace());
       }
}

   PayloadCopier:
package be.i8c.mapping;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.api.StreamTransformationException;

public class PayloadCopier {

 private static int bufferSize = 4096;
 private static byte[] buffer = new byte[bufferSize];
 private static int bufferLength = 0;
 
    public static void copy (InputStream in, OutputStream out, AbstractTrace trace)
    throws StreamTransformationException {

     try {
      BufferedInputStream buffIn = new BufferedInputStream(in, bufferSize);
      BufferedOutputStream buffOut = new BufferedOutputStream(out, bufferSize);
      
      while (buffIn.available()>0) {
       bufferLength = buffIn.read(buffer);
       buffOut.write(buffer, 0, bufferLength);
       }
      buffOut.close();
      
      } catch (IOException e){
           throw new StreamTransformationException(e.getMessage());
       }
   }
}

   DynConfMapper:
package be.i8c.mapping;

import com.sap.aii.mapping.api.AbstractTrace;
import com.sap.aii.mapping.api.DynamicConfiguration;
import com.sap.aii.mapping.api.DynamicConfigurationKey;
import com.sap.aii.mapping.api.InputParameters;
import com.sap.aii.mapping.api.OutputParameters;

public class DynConfMapper {
 
  private static DynamicConfigurationKey dynKey = null;
  private static String defaultNS = "urn:i8c:xslt:mappingParams";
  private static String[] paramArray = null;
  private static String paramBinder = "ParameterNames";
  private static String paramNSBinder = "ParameterNamespace";
  private static String paramNames = null;
  private static String paramNamespace = null;
 
private static AbstractTrace trace = null;

 private static String[] getParamNames (InputParameters inParams){
  try {
   paramNames = inParams.getString(paramBinder);
   String[] myParamArray = paramNames.split(" ");
   trace.addDebugMessage(myParamArray.length + " parameter names found.");
   return myParamArray;
   } catch (Exception e) {
    trace.addWarning("A mapping input parameter called " + paramBinder +
      " has not been bound. No parameters can be copied to the DynamicConfiguration.");
    return null;
   }
 }
 
 private static String getParamNS (InputParameters inParams){
   try {
    return inParams.getString(paramNSBinder);
   } catch (Exception e) {
   return defaultNS;
   }
  
 }
 
 public static void put (InputParameters inParams, DynamicConfiguration dynConf, AbstractTrace inTrace) {
   trace = inTrace;
   // Get input parameter names
   paramArray = getParamNames(inParams);
   if(paramArray.equals(null)){ return; }
  

   // Get input parameter NameSpace
   paramNamespace = getParamNS(inParams);
  
   // Put to the DynamicConfiguration the values for the requested parameters
   for (int i=0; i != paramArray.length i++){ 

   if(paramArray[i].equalsIgnoreCase(paramBinder)){continue;}
   if(paramArray[i].equalsIgnoreCase(paramNSBinder)){continue;}

   trace.addDebugMessage("Treating " + paramArray[i]);
   dynKey = DynamicConfigurationKey.create(paramNamespace, paramArray[i]);
   try { // Is it an InputParameter ?
      dynConf.put(dynKey, inParams.getString(paramArray[i]));
   } catch (Exception e){
      trace.addWarning("Cannot read " + paramArray[i] + " from InputParameters. "
        + "A mapping program parameter of this name must be bound in the Operation Mapping");
          }
   }
 }

  
 public static void get (OutputParameters outParams, InputParameters inParams,
   DynamicConfiguration dynConf, AbstractTrace inTrace) {
  
   trace = inTrace;
   // Get input parameter names
   paramArray = getParamNames(inParams);
   if(paramArray.equals(null)){ return; }
  

   // Get input parameter NameSpace
   paramNamespace = getParamNS(inParams);
  
   // Put to the DynamicConfiguration the values for the requested parameters
   for (int i=0; i != paramArray.length; i++){
     if(paramArray[i].equalsIgnoreCase(paramBinder)){continue;}
     if(paramArray[i].equalsIgnoreCase(paramNSBinder)){continue;}

     trace.addDebugMessage("Treating " + paramArray[i]);
     dynKey = DynamicConfigurationKey.create(paramNamespace, paramArray[i]);
     try { // Is it an InputParameter ?
       outParams.setString(paramArray[i], dynConf.get(dynKey));
     } catch (Exception e){
       trace.addWarning("Cannot read " + paramArray[i] +
            " from DynamicConfiguration or there is no export mapping program parameter " +
             "of this name bound in the Operation Mapping");
     }
   }
  }
}  

Author: Sergio Cipolla
Submitted: 14 September 2007

When Performing an initial load of master data via XI using proxy messages it common to have several errors when processing messages in the target system due to wrong data inside the source system. For instance in a business partner initial load is happens quite often to find that some data (e.g postal code, vat code) are missing or invalid, this cause an error in the target system and tipically a negative acknowledgment is sent back to the sender.

 To start solving the issues it is necessary to launch transaction SXMB_MONI, open each failing message one by one and look inside the error header of the acknowledgment which was the reason for the failure (see picture below).

 
This report does exactly this job, it looks for messages in error, finds the related negative acknowledgment, extract the errors descriptions and prints them out, so that it is possible to check quickly the reason for a lot of errors.

*&---------------------------------------------------------------------*
*& Report  ZMASSIVE_PROXY_MONI
*&
*&---------------------------------------------------------------------*
* Read all the proxy messages in errors and return the list of
* Errors in the last acknowledgment
*
* AUTHOR: Sergio Cipolla
*
*&---------------------------------------------------------------------*

********************************************************************************
* BEGIN OF MAIN ****************************************************************
********************************************************************************
REPORT  ZTEST_MONI.
TYPE-POOLS: ixml.
class cl_ixml definition load.

DATA:
 l_date_range type sy-datum.



SELECTION-SCREEN BEGIN OF BLOCK a.
SELECT-OPTIONS : p_dates for l_date_range OBLIGATORY NO-EXTENSION.
SELECTION-SCREEN END OF BLOCK a.

START-OF-SELECTION.

  TYPES: BEGIN OF TYPE_RESULT_STRUCTURE,
           MESSAGE  TYPE SXMSPMAST,
           ACKNOWLEDGMENT  TYPE SXMSPMAST,
           ERRORS TYPE BAPIRET2 OCCURS 0,
         END OF TYPE_RESULT_STRUCTURE.

  TYPES TYPE_RESULT_TABLE TYPE TABLE OF TYPE_RESULT_STRUCTURE.

  DATA :
        LT_RESULTS TYPE TYPE_RESULT_TABLE,
        LW_RESULTS TYPE TYPE_RESULT_STRUCTURE,
        LW_ERRORS TYPE BAPIRET2.

  DATA : l_tmp_date type sy-datum.

  PERFORM READ_PROXY_ERRORS
  TABLES LT_RESULTS
  USING p_dates.
  IF SY-SUBRC <> 0.
    write / 'error!'.
    return.
  ENDIF.

  LOOP AT LT_RESULTS INTO LW_RESULTS.
    write / : 'Source message id:'.
    write : LW_RESULTS-ACKNOWLEDGMENT-REF_TO_REC_MSG.

    CONVERT TIME STAMP LW_RESULTS-MESSAGE-EXETIMEST TIME ZONE sy-zonlo INTO DATE l_tmp_date.

    write / : 'Executed on:'.
    write : l_tmp_date.

    write /: 'Errors:'.
    loop at LW_RESULTS-ERRORS into lw_errors where type <> 'I'.
      write :  lw_errors-message.
    endloop.
    write / '---------------------------------------'.

  ENDLOOP.

END-OF-SELECTION.

********************************************************************************
* END OF MAIN ******************************************************************
********************************************************************************

*&---------------------------------------------------------------------*
*&      Form  parseXML
*&---------------------------------------------------------------------*
*       Parse an XML document
*----------------------------------------------------------------------*
*  -->  p1        string to be parsed
*  <--  p2        document parsed
*----------------------------------------------------------------------*

FORM parseXML
USING pi_xml_string type STRING
CHANGING pc_xml_document TYPE REF TO if_ixml_document.

  DATA: pixml          TYPE REF TO if_ixml,
         pdocument      TYPE REF TO if_ixml_document,
         pstreamfactory TYPE REF TO if_ixml_stream_factory,
         pistream       TYPE REF TO if_ixml_istream,
         pparser        TYPE REF TO if_ixml_parser,
         pnode          TYPE REF TO if_ixml_node,
         ptext          TYPE REF TO if_ixml_text,
         string         TYPE string,
         count          TYPE i,
         index          TYPE i,
         totalsize      TYPE i,
         dsn(40)        TYPE c,
         xstr           TYPE xstring.

*-- create the main factory
  pixml = cl_ixml=>create( ).

*-- create the initial document
  pdocument = pixml->create_document( ).

*-- create the stream factory
  pstreamfactory = pixml->create_stream_factory( ).

*-- create an input stream for the string
  pistream = pstreamfactory->create_istream_string( string = pi_xml_string).

*-- create the parser
  pparser = pixml->create_parser( stream_factory = pstreamfactory
                                  istream        = pistream
                                  document       = pdocument ).

*-- parse the stream
  IF pparser->parse( ) NE 0.

    IF pparser->num_errors( ) NE 0.

      count = pparser->num_errors( ).

      WRITE: count, ' parse errors have occured:'.          "#EC NOTEXT

      DATA: pparseerror TYPE REF TO if_ixml_parse_error,

            i TYPE i.

      index = 0.

      WHILE index < count.

        pparseerror = pparser->get_error( index = index ).

        i = pparseerror->get_line( ).

        WRITE: 'line: ', i.

        i = pparseerror->get_column( ).

        WRITE: 'column: ', i.

        string = pparseerror->get_reason( ).

        WRITE: string.

        index = index + 1.

      ENDWHILE.

    ENDIF.

  ENDIF.



  CALL METHOD pistream->close( ).

  CLEAR pistream.



  pc_xml_document = pdocument.

ENDFORM.                    " parseXML

*&---------------------------------------------------------------------*
*&      Form  transcode_error
*&---------------------------------------------------------------------*
*       Convert an error type in proxy xml format to an error type in
*       BAPI format
*----------------------------------------------------------------------*
*      -->PI_XLM_ERROR_TYPE  error type in proxy xml format
*      <--PE_BAPI_ERROR_TYPE  error type in BAPI format
*----------------------------------------------------------------------*

FORM transcode_error  USING    PI_XLM_ERROR_TYPE TYPE STRING
                      CHANGING PE_BAPI_ERROR_TYPE TYPE BAPIRET2-TYPE.

  DATA : l_xlm_error_type TYPE STRING.

  l_xlm_error_type = PI_XLM_ERROR_TYPE.
  TRANSLATE l_xlm_error_type TO UPPER CASE.

  case l_xlm_error_type.
    when 'HIGH'.
      PE_BAPI_ERROR_TYPE = 'A'.
    when 'ERROR'.
      PE_BAPI_ERROR_TYPE = 'E'.
    when 'WARNING'.
      PE_BAPI_ERROR_TYPE = 'W'.
    when others.
      PE_BAPI_ERROR_TYPE = 'I'.
  endcase.

ENDFORM.                    " transcode_error

*&---------------------------------------------------------------------*
*&      Form  READ_PROXY_ERRORS
*&---------------------------------------------------------------------*
*       Read all the proxy messages in errors and return the list of
*       Errors in the last acknowledgment
*----------------------------------------------------------------------*
*  -->  PC_RESULT
*  -->  P_SEARCH_DATES
* each line of  the table has the following structure:
* 1) MESSAGE, is the message in error and has the structure SXMSPMAST
* 2) ACKNOWLEDGMENT, is the last acknowledgment for the message above
*    and has the structure SXMSPMAST
* 3) ERRORS, is the list of errors for the message and is a table where
*    each line has the structure BAPIRET2
*----------------------------------------------------------------------*

FORM READ_PROXY_ERRORS
TABLES PC_RESULT TYPE TYPE_RESULT_TABLE
USING P_SEARCH_DATES LIKE p_dates .

  DATA :

        LT_MESSAGES TYPE TABLE OF SXMSPMAST,

        LW_MESSAGES TYPE SXMSPMAST,

        LT_ACKNOWLEDGMENT TYPE TABLE OF SXMSPMAST,

        LW_ACKNOWLEDGMENT TYPE SXMSPMAST,

        LW_ERRORS TYPE BAPIRET2,

        LW_RESULTS TYPE TYPE_RESULT_STRUCTURE.



  DATA:

        lo_xms_persist TYPE REF TO cl_xms_persist,

        lo_xms_message TYPE REF TO IF_XMS_MESSAGE,

        lo_xms_errheader TYPE REF TO IF_XMS_PROP,

        lo_xml_document TYPE REF TO if_ixml_document,

        lo_xml_node TYPE REF TO if_ixml_node,

        lo_xml_element TYPE REF TO IF_IXML_ELEMENT,

        lo_xml_node_coll TYPE REF TO IF_IXML_NODE_COLLECTION,

        lo_xml_node_list TYPE REF TO IF_IXML_NODE_LIST,

        lo_xml_document_add TYPE REF TO if_ixml_document,

        lo_xml_iterator type ref to if_ixml_node_iterator,

        lo_xml_node2 TYPE REF TO if_ixml_node,

        lo_xml_iterator2 type ref to if_ixml_node_iterator.

  DATA:

        l_node_name type String,

        l_node_value type String.



  DATA:

         l_tmp_string TYPE STRING,

         l_start_date TYPE TIMESTAMPL,

         l_end_date TYPE TIMESTAMPL.



CONVERT DATE P_SEARCH_DATES-LOW INTO TIME STAMP l_start_date TIME ZONE sy-zonlo.
CONVERT DATE P_SEARCH_DATES-HIGH INTO TIME STAMP l_end_date TIME ZONE sy-zonlo.

*******************************************************************************
* STEP 1: Select the list of messages in error
*******************************************************************************

  SELECT *

    FROM SXMSPMAST

    INTO CORRESPONDING FIELDS OF TABLE LT_MESSAGES

    WHERE MSGSTATE = '017'

    AND EXETIMEST BETWEEN l_start_date AND l_end_date.



  if sy-subrc <> 0.

    RETURN.

  endif.



*******************************************************************************
* STEP 2: Select the list of acknowledgment referring to the error message
*******************************************************************************

  LOOP AT LT_MESSAGES INTO LW_MESSAGES.

    REFRESH LT_ACKNOWLEDGMENT.

    CLEAR LW_RESULTS.



*Select only the last acknowledgment

    SELECT *

      FROM SXMSPMAST

      INTO TABLE LT_ACKNOWLEDGMENT

      UP TO 1 ROWS

      WHERE

        REF_TO_MSG = LW_MESSAGES-MSGGUID

        AND PID ='RECEIVER_BACK'

      ORDER BY EXETIMEST DESCENDING.



    if sy-subrc <> 0.

      RETURN.

    endif.



    READ TABLE LT_ACKNOWLEDGMENT INDEX 1 INTO LW_ACKNOWLEDGMENT.

    CLEAR LW_RESULTS.

    MOVE-CORRESPONDING LW_MESSAGES TO LW_RESULTS-MESSAGE.

    MOVE-CORRESPONDING LW_ACKNOWLEDGMENT TO LW_RESULTS-ACKNOWLEDGMENT.

*******************************************************************************
* STEP 3.0: Take the last acknowledgment and Get the corresponding message
*******************************************************************************

    CREATE OBJECT lo_xms_persist.

    try.

        CALL METHOD lo_xms_persist->READ_MSG_ALL

          EXPORTING

            IM_MSGGUID      = LW_ACKNOWLEDGMENT-MSGGUID

            IM_PID          = LW_ACKNOWLEDGMENT-PID

            IM_VERSION      = LW_ACKNOWLEDGMENT-VERS

            IM_CLIENT       = LW_ACKNOWLEDGMENT-CLIENT

            IM_READ_PAYLOAD = 'X'

          IMPORTING

            EX_MESSAGE      = lo_xms_message.

      catch CX_XMS_SYSERR_PERSIST.

        return.

    endtry.



*******************************************************************************
* STEP 3.1: Get the error header part from the message (as a string)
*******************************************************************************

    CALL METHOD LO_XMS_MESSAGE->GETHEADERBYNAME

      EXPORTING

        NSURI  = 'http://sap.com/xi/XI/Message/30'

        LCNAME = 'Error'

      RECEIVING

        PROP   = lo_xms_errheader.



    if sy-subrc <> 0.

      write /'error'.

      RETURN.

    endif.



    TRY.

        CALL METHOD LO_XMS_ERRHEADER->WRITETOXMLSTRING

*    EXPORTING

*      NSCONTEXT      =

*      EXTERNAL       = '1'

*      PARSING_METHOD = CL_XMS_PARSER=>CO_PARSING_METHOD_UNDEF

          RECEIVING

            VALUE          = l_tmp_string.



      CATCH CX_XMS_SYSTEM_ERROR .

        write /'error'.

        RETURN.

    ENDTRY.

*******************************************************************************
* STEP 3.2: parse the XML error message (main external envelope)
*******************************************************************************

    perform parseXML
    using l_tmp_string
    CHANGING lo_xml_document.

    if sy-subrc <> 0.
      write /'error'.
      return.
    endif.



    CALL METHOD lo_xml_document->GET_ELEMENTS_BY_TAG_NAME

      EXPORTING

        NAME      = 'AdditionalText'

        NAMESPACE = 'SAP'

      RECEIVING

        RVAL      = lo_xml_node_coll.





    CLEAR lo_xml_node.

    lo_xml_node = lo_xml_node_coll->get_Item( '0' ).
    l_tmp_string = lo_xml_node->get_value( ).

*******************************************************************************
* STEP 3.3: parse the XML additional text (contains the real error)
*******************************************************************************

    perform parseXML
      using l_tmp_string
      CHANGING lo_xml_document_add.

    CALL METHOD lo_xml_document_add->GET_ELEMENTS_BY_TAG_NAME
      EXPORTING
        NAME = 'faultDetail'
      RECEIVING
        RVAL = lo_xml_node_coll.

    if sy-subrc <> 0.
      write /'error'.
      return.

    endif.

    lo_xml_iterator = lo_xml_node_coll->create_iterator( ).
    lo_xml_node = lo_xml_iterator->get_next( ).

    while not lo_xml_node is initial.

      CALL METHOD lo_xml_node->GET_CHILDREN
        RECEIVING
          RVAL = lo_xml_node_list.


      lo_xml_iterator2 = lo_xml_node_list->create_iterator( ).
      lo_xml_node2 = lo_xml_iterator2->get_next( ).

      while not lo_xml_node2 is initial.
        l_node_name = lo_xml_node2->get_name( ).
        l_node_value = lo_xml_node2->get_value( ).

        CASE l_node_name.
          WHEN 'severity'.
            perform transcode_error
            using l_node_value
            CHANGING LW_ERRORS-TYPE.
          WHEN 'text'.
            LW_ERRORS-MESSAGE = l_node_value.
        ENDCASE.

        lo_xml_node2 = lo_xml_iterator2->get_next( ).

      endwhile.

      APPEND LW_ERRORS TO LW_RESULTS-ERRORS.

      CLEAR LW_ERRORS.

      lo_xml_node = lo_xml_iterator->get_next( ).

    endwhile.

    APPEND LW_RESULTS TO PC_RESULT.


* clear
    CLEAR lo_xml_node.
    CLEAR lo_xml_node2.
    CLEAR lo_xml_iterator.
    CLEAR lo_xml_iterator2.
    CLEAR lo_xml_node_coll.
    CLEAR lo_xml_document.
    CLEAR lo_xml_document_add.

  ENDLOOP.


ENDFORM.                    " READ_PROXY_ERRORS

Author: David Pietroniro
Submitted: 09/12/2008
Related Links:

Description

In this I will show how to map an item table where each item can have zero or three taxes. The result XML must have a structure where the item number and its taxes must be grouped in one node.
So, the structures that we have are:

And the result structure must be:

Example:

The item table has three items and the item one has the tax_1 and tax_3, the item two has the tax_1, tax_2 and tax_3 and item three doesn't have any tax.

ITEM_TAB

1

2

3

ITEM_EXT

NUMBER

TAX_NAME

VALUE

1

TAX_1

100

1

TAX_3

200

2

TAX_2

300

2

TAX_1

400

2

TAX_3

500

And the result XML must be:

ITEM

NUMBER

1

TAX_VALUE1

100

TAX_VALUE3

200

ITEM

NUMBER

2

TAX_VALUE1

400

TAX_VALUE2

300

TAX_VALUE3

500

ITEM

NUMBER

3

For this was necessary to create the following objects.

Data types:

The item and item extension:

The result:

Message types

For each data type was created a message:

  • MM_OUT for the DT_OUT data type;
  • MM_RESULT for the DT_RESULT data type.

Message mappings

It was created the following message mapping:

And the field mappings:

User-defined advanced function

It was created the following function:

public void my_function(String[] a,String[] b,String[] c,String[] d,String[] e,ResultList result,Container container){
  for (int i=0; i<a.length; i++) {
    boolean found = false;
    int j = 0;

    for (j=0; j<b.length; j++ ) {

      if (a[i].equals(b[j]) && c[j].equals(e[0])) {
        found = true;
        break;
      }
    }
    if (found == true)
      result.addValue(d[j]);
    else
      result.addSuppress();
  }
}

This function has the following importing attributes:

  • a - This is the NUMBER queue from the ITEM_TAB context ;
  • b - This is the NUMBER queue from the ITEM_EXT context;
  • c - This is the TAX_NAME queue;
  • d - This is the VALUE queue;
  • e - This is a constant that corresponds to the tax to be mapped.

So this function returns a queue with the values from the element VALUE considering the item number and the tax name.

Testing

To test the message mapping was created the following instance:

<?xml version="1.0" encoding="UTF-8"?>

<ns0:MSG_OUT xmlns:ns0="http://test.com.br/item">
   <item_tab>
      <number>1</number>
   </item_tab>
   <item_tab>
      <number>2</number>
   </item_tab>
   <item_tab>
      <number>3</number>
   </item_tab>
   <item_ext>
      <number>1</number>
      <tax_name>TAX_1</tax_name>
      <value>100</value>
   </item_ext>
   <item_ext>
      <number>1</number>
      <tax_name>TAX_3</tax_name>
      <value>200</value>
   </item_ext>
   <item_ext>
      <number>2</number>
      <tax_name>TAX_2</tax_name>
      <value>300</value>
   </item_ext>
   <item_ext>
      <number>2</number>
      <tax_name>TAX_1</tax_name>
      <value>400</value>
   </item_ext>
   <item_ext>
      <number>2</number>
      <tax_name>TAX_3</tax_name>
      <value>500</value>
   </item_ext>
</ns0:MSG_OUT>

And the result is:

<?xml version="1.0" encoding="UTF-8"?>
<ns0:MSG_RESULT xmlns:ns0="http://test.com.br/test">
   <item>
      <number>1</number>
      <tax_value1>100</tax_value1>
      <tax_value3>200</tax_value3>
   </item>
   <item>
      <number>2</number>
      <tax_value1>400</tax_value1>
      <tax_value2>300</tax_value2>
      <tax_value3>500</tax_value3>
   </item>
   <item>
      <number>3</number>
   </item>
</ns0:MSG_RESULT>

You can get more information about message mappings in SAP Exchange Infrastructure - Graphical Mapping - Advanced.

Author: David Pietroniro
Submitted: 12/18/2008
Related Links:

Description

 In this I will show a way to fetch the PI monitoring data (accessed via transaction SXMB_MONI) from the various standard tables.

ZSXMB_MONI Function Module

This function module is an improved version of the one created by Pooja Pandey in "Exposing the XI monitoring functionality as a Web Service".
The function is responsible to fetch the data from the standard SAP monitoring tables (including the messages payloads) and export them as a table. I used a remote enabled function module (RFC) because with this option it's possible to call it from others systems and save the fetched data remotely on the caller systems.

Importing Parameters



The importing parameters are:





  • IV_DATE_FROM: The initial execution date;
  • IV_TIME_FROM: The initial execution time;
  • IV_DATE_TO: The final execution date;
  • IV_TIME_TO: The final execution time;
  • IT_FILTER: A filter table based on the ZSXMB_MONI_FILTER structure where is defined the field and the conditions that this field must respect. The field is one or more of the SXI_MSG_SELECT structure and the value is the desired condition. An example of how to fill this table will be showed in the report that's used to recover the monitoring data.

Exporting Parameters



The exporting parameter is:





  • ET_DATA: The table that contains the message data including its payload. This table is based on the structure ZSXMB_MONI_DATA (which include the structures ZSXMB_MONI_KEY - with the key fields for the messages and ZSXMB_MONI_OTHER - that contains the data fields).








 Exceptions








The exceptions are:

  • INVALID_DATES: The date and time passed as importing parameters are invalids (date and time from greater than the date and time to, for example);
  • NO_DATA: There's no PI monitoring messages for the conditions passed in the importing parameters.

Source Code

Function ZSXMB_MONI
FUNCTION zsxmb_moni.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_DATE_FROM) TYPE  DATS
*"     REFERENCE(IV_TIME_FROM) TYPE  TIMS
*"     REFERENCE(IV_DATE_TO) TYPE  DATS
*"     REFERENCE(IV_TIME_TO) TYPE  TIMS
*"     REFERENCE(IT_FILTER) TYPE  ZSXMB_MONI_FILTER_TAB OPTIONAL
*"  EXPORTING
*"     REFERENCE(ET_DATA) TYPE  ZSXMB_MONI_DATA_TAB
*"  EXCEPTIONS
*"      INVALID_DATES
*"      NO_DATA
*"----------------------------------------------------------------------
* Declaration of constants
  CONSTANTS:
    lco_number TYPE int4 VALUE 2147483646,
    lco_filter TYPE c    LENGTH 10 VALUE 'LS_FILTER-',
    lco_1      TYPE i    VALUE 1,
    BEGIN OF lco_pids,
      sign     TYPE sxmsselopt-sign   VALUE 'E',
      option   TYPE sxmsselopt-option VALUE 'EQ',
      central  TYPE sxmsselopt-low    VALUE 'CENTRAL_BACK',
      receiver TYPE sxmsselopt-low    VALUE 'RECEIVER_BACK',
      sender   TYPE sxmsselopt-low    VALUE 'SENDER_BACK',
      adapter  TYPE sxmsselopt-low    VALUE 'PE_ADAPTER',
      process  TYPE sxmsselopt-low    VALUE 'PE_PROCESS',
    END OF lco_pids.
* Declaration of data types.
  TYPES:
* Data type used to fetch the message logs payloads.
    BEGIN OF lty_payload,
      msgguid TYPE sxmsmsglst-msgguid,
      pid     TYPE sxmsmsglst-pid,
      payload TYPE xstring,
    END OF lty_payload,
    lty_t_payload TYPE SORTED TABLE OF lty_payload
      WITH NON-UNIQUE KEY msgguid pid.
* Declaration of data objects.
  DATA:
    lv_timestmp_from TYPE         timestampl,
    lv_timestmp_to   TYPE         timestampl,
    ls_filter        TYPE         sxi_msg_select,
    ls_pids          TYPE LINE OF sxi_msg_select-pids,
    lt_msgtab        TYPE         sxmsmsgtab,
    lr_msgtab        TYPE REF TO  sxmsmsglst,
    lt_msgtab_aux    LIKE         lt_msgtab,
    lr_filter        TYPE REF TO  zsxmb_moni_filter,
    lr_filter_aux    TYPE REF TO  zsxmb_moni_filter,
    lv_times         TYPE         zsxmb_moni_filter-filternum
      VALUE '001',
    lv_fieldname     TYPE         zsxmb_moni_filter-field,
    lr_xms_persist   TYPE REF TO  cl_xms_persist,
    lr_message       TYPE REF TO  if_xms_message,
    lr_resource      TYPE REF TO   if_xms_resource,
    lr_error         TYPE REF TO  cx_root,                   "#EC NEEDED
    lv_version       TYPE         sxmslsqnbr,
    lv_cont          TYPE         i,
    lv_size          TYPE         i,
    lv_data          TYPE         xstring,
    lt_payload       TYPE         lty_t_payload,
    ls_payload       LIKE LINE OF lt_payload,
    lr_payload       TYPE REF TO  lty_payload,
    ls_data          LIKE LINE OF et_data.
* Declaration of field-symbols
  FIELD-SYMBOLS:
    <fs_field> TYPE ANY.

* Validate the dates received via importing parameters
  CONVERT: DATE iv_date_from TIME iv_time_from
    INTO TIME STAMP lv_timestmp_from TIME ZONE sy-zonlo,
    DATE iv_date_to TIME iv_time_to
    INTO TIME STAMP lv_timestmp_to TIME ZONE sy-zonlo.
  IF lv_timestmp_from > lv_timestmp_to.
    RAISE invalid_dates.
  ENDIF.
  FREE: lv_timestmp_from, lv_timestmp_to.

* Determine the number of times that the messages log data
* selection must occurs.
  IF LINES( it_filter ) > 0.
    READ TABLE it_filter INDEX 1 REFERENCE INTO lr_filter_aux.

    LOOP AT it_filter REFERENCE INTO lr_filter.
      CHECK lr_filter->filternum <> lr_filter_aux->filternum.
      lv_times = lv_times + 1.
      lr_filter_aux = lr_filter.
    ENDLOOP.
    FREE lr_filter_aux.
  ENDIF.

  DO lv_times TIMES.
    CLEAR: ls_filter, lt_msgtab_aux.
* Move the fixed filter fields to the filter structure.
    ls_pids-sign   = lco_pids-sign.
    ls_pids-option = lco_pids-option.
    ls_pids-low    = lco_pids-central.
    APPEND ls_pids TO ls_filter-pids.
    ls_pids-low = lco_pids-receiver.
    APPEND ls_pids TO ls_filter-pids.
    ls_pids-low = lco_pids-sender.
    APPEND ls_pids TO ls_filter-pids.
    ls_pids-low = lco_pids-adapter.
    APPEND ls_pids TO ls_filter-pids.
    ls_pids-low = lco_pids-process.
    APPEND ls_pids TO ls_filter-pids.
* Move the importing parameters to the corresponding filter structure
* fields.
    ls_filter-exedate  = iv_date_from.
    ls_filter-exetime  = iv_time_from.
    ls_filter-exe2date = iv_date_to.
    ls_filter-exe2time = iv_time_to.
* Move the others fields from the importing parameters to the
* corresponding fields.
    LOOP AT it_filter REFERENCE INTO lr_filter WHERE filternum = sy-index.
      CONCATENATE lco_filter lr_filter->field INTO lv_fieldname.
      ASSIGN (lv_fieldname) TO <fs_field>.
      IF sy-subrc = 0.
        <fs_field> = lr_filter->value.
      ENDIF.
    ENDLOOP.

* Select the messages log
    CALL FUNCTION 'SXMB_SELECT_MESSAGES_NEW'
      EXPORTING
        im_filter           = ls_filter
        im_number           = lco_number
      IMPORTING
        ex_msgtab           = lt_msgtab_aux
      EXCEPTIONS
        persist_error       = 1
        missing_parameter   = 2
        negative_time_range = 3
        too_many_parameters = 4
        no_timezone         = 5
        OTHERS              = 6.
    IF sy-subrc <> 0.                                       "#EC NEEDED
    ENDIF.
    APPEND LINES OF lt_msgtab_aux TO lt_msgtab.
  ENDDO.
  FREE: ls_filter, ls_pids, lt_msgtab_aux, lv_times, lv_fieldname.

* Fetch the payload data
  CREATE OBJECT lr_xms_persist.
  LOOP AT lt_msgtab REFERENCE INTO lr_msgtab.
    CLEAR: lv_version, ls_payload.

    lv_version = lr_msgtab->vers.
    lv_cont    = lr_msgtab->vers + 1.
    DO lv_cont TIMES.
      TRY.
          lr_xms_persist->read_msg_all(
            EXPORTING
              im_msgguid = lr_msgtab->msgguid
              im_pid     = lr_msgtab->pid
              im_version = lv_version
            IMPORTING
              ex_message = lr_message ).
        CATCH cx_xms_syserr_persist INTO lr_error.
          EXIT.
      ENDTRY.

      lv_size = lr_message->numberofattachments( ).
      IF lv_size IS NOT INITIAL.
        lr_resource =
          lr_message->getattachmentatindex( index = lco_1 ).
        TRY.
            lv_data = lr_resource->getbinarydata( ).
          CATCH: cx_xms_exception INTO lr_error,        "#EC NO_HANDLER
            cx_xms_system_error INTO lr_error.          "#EC NO_HANDLER
        ENDTRY.
        IF lv_data IS NOT INITIAL.
          CONCATENATE lv_data ls_payload-payload
            INTO ls_payload-payload IN BYTE MODE.
        ENDIF.
        lv_version = lv_version + 1.
        CLEAR lv_data.
      ENDIF.
    ENDDO.
    IF ls_payload-payload IS NOT INITIAL.
      ls_payload-msgguid = lr_msgtab->msgguid.
      ls_payload-pid     = lr_msgtab->pid.
      INSERT ls_payload INTO TABLE lt_payload.
    ENDIF.
  ENDLOOP.
  FREE: ls_payload, lv_version, lv_cont, lv_size, lv_data,
    lr_xms_persist, lr_resource.

* Process the retrieved data and return it to the function
* caller.
  LOOP AT lt_msgtab REFERENCE INTO lr_msgtab.
    READ TABLE lt_payload WITH TABLE KEY
      msgguid = lr_msgtab->msgguid
      pid     = lr_msgtab->pid
      REFERENCE INTO lr_payload.

    ls_data-msgguid    = lr_msgtab->msgguid.
    ls_data-pid        = lr_msgtab->pid.
    ls_data-ob_system  = lr_msgtab->ob_system.
    ls_data-ob_ns      = lr_msgtab->ob_ns.
    ls_data-ob_name    = lr_msgtab->ob_name.
    ls_data-ib_system  = lr_msgtab->ib_system.
    ls_data-ib_ns      = lr_msgtab->ib_ns.
    ls_data-ib_name    = lr_msgtab->ib_name.
    ls_data-msgtype    = lr_msgtab->msgtype.
    ls_data-msgstate   = lr_msgtab->msgstate.
    ls_data-exetimest  = lr_msgtab->exetimest.
    ls_data-inittimest = lr_msgtab->inittimest.
    ls_data-sendtimest = lr_msgtab->sendtimest.
    ls_data-adminuser  = lr_msgtab->adminuser.

    IF lr_payload IS BOUND.
      ls_data-payload = lr_payload->payload.
      CLEAR lr_payload.
    ENDIF.

    APPEND ls_data TO et_data.
  ENDLOOP.
  IF et_data IS INITIAL.
    RAISE no_data.
  ENDIF.
ENDFUNCTION.

In the next Wiki I'll describe a report to fetch the data and store these data in a transparent table.

Author: Michelle Crapo

Submitted: 05/28/2009
Related Links:

Finding the correct XML in SXMB_MONI can be a problem.   There are other coding examples, but I thought I'd share my solution.  In this case, the key piece of information on the XML is the shipment number.  (Inbound proxy)  Once I figured out how to do this it was a piece of cake.  If I had several different kinds of XML documents coming into the system, I could have created a generic external table.  (Key and msgid)

This is the first part of the program.  This is for inbound proxies.   During the execution of the proxy class insert the following code (And add things like locking, etc) :

/
  CLEAR: message_guid.
* Get the message ID
  TRY.
      server_context = cl_proxy_access=>get_server_context( ).
      message_id_protocol ?= server_context->get_protocol( if_wsprotocol=>message_id ).
      message_guid = message_id_protocol->get_message_id( ).
    CATCH cx_ai_system_fault.
  ENDTRY.

* Update the shipment table
  CLEAR: work_work_area.

  work_area-shipment = shipment_num.  "From the XML document being processed
  work_area-msgid = message_guid.
  MODIFY External_table FROM Work_area.   "Write the GUID and the key in the XML document to a Z* Table
  COMMIT WORK. /

The second part of this is simply creating a report to display the shipment number and the XML(s) that have moved into the system.   Yes, I should have created an object ALV program.  (I wanted something done very quickly.

/

TABLES: zexternaltable.

SELECTION-SCREEN BEGIN OF BLOCK bl01.
SELECT-OPTIONS:
  s_ship   FOR zexternaltable-shipment.
SELECTION-SCREEN END OF BLOCK bl01.

DATA: v_lin TYPE i,
      internal_tab TYPE STANDARD TABLE OF zexternaltable,
      work_area TYPE zexternaltable,




AT LINE-SELECTION.
  GET CURSOR LINE v_lin.
  SUBTRACT 6 FROM v_lin.
  READ TABLE internal_tab INTO work_area INDEX v_lin.
* Display the XML monitor
  SUBMIT rsxmb_display_msg_vers_new
  WITH msgguid = work_area-msgid
  AND RETURN.


TOP-OF-PAGE.

  ULINE.
  WRITE: / 'Shipment',

          40 'GUID'.
  ULINE.

START-OF-SELECTION.
  IF s_ship IS INITIAL.
    MESSAGE i368(00) WITH 'Enter at least one shipment'.
  ELSE.
    SELECT * FROM zexternaltable INTO TABLE internal_tab
      WHERE shipment IN s_ship.
    IF sy-subrc <> 0.
      WRITE: / 'No records found'.
    ELSE.
loop at internal_tab into work_area.
      SORT i_internaltab BY shipment DESCENDING.


        WRITE: / work_area-shipment HOTSPOT,

                40 work_area-msgid.
      ENDLOOP.
    ENDIF.
  ENDIF.
/

Author: http://www.sdn.sap.com/irj/servlet/prt/portal/prtroot/com.sap.sdn.businesscard.SDNBusinessCard?u=Acdz2ooCJSc%3D* *

Submitted: 05/01/2009
Related Links:

Description

Use Adapter Specific Message Attributes for the target Communication Channel(CC).Check the indicator for filename in the advanced tab of CC

Create a UDF with input as file name and copy/paste this code

/* Using Dynamic Configuration */
DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
//conf.removeAll();
DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","FileName");
//String filename= conf.get(key);
conf.put(key, fileName);
key= null;


return fileName;

In the above example the UDF has value as cache.The output of this UDF is assigned to the root of the xml document.

Objective :

SXMB_MONI is the standard transaction which display all the details of all the XML messages sent through proxy. Now there is no functionality in the standard program through which we can search the XML messages through the message contents.

 
Note : XML message contents are found in between the following TAG:

 
 <>Content</>

Where Content is XML message content

 
Our objective was to add the searching features to SXMB_MONI

 
Features :

We created a copy of the standard program RSXMB_SELECT_MESSAGES to add the searching functionality.

In modified screen we added one Block named 'Search Criteria'. It contains two Input parameters: 'Search String 1' and 'Search String 2'. In this two input parameter you can specify two search conditions. If 'Any' radio button is checked the program will searched all the XML Messages which will satisfy any of the search criteria. If 'Both' radio button is checked then will searched all the XML Messages which will satisfy Both of the search criteria.

Process:  

A local class exists in the standard program named lcl_application which did the selection of the XML messages through the functional module SXMB_SELECT_MESSAGES and store in the output table gt_msgtab_ext and later display the table contents through ALV.  Before sending the final output table to ALV, we have filtered the XML message stored in output table gt_msgtab_ext through our search criteria and then send it to ALV for display. 

Source Code to Search the contents of XML messages:

Selection screen addition

SELECTION-SCREEN BEGIN OF BLOCK search_sel
                 WITH FRAME
                 TITLE text-s16.
PARAMETERS: p_and RADIOBUTTON GROUP g1,
            p_or  RADIOBUTTON GROUP g1,
            p_srch1 TYPE char50,
            p_srch2 TYPE char50.
SELECTION-SCREEN END OF BLOCK search_sel.
 

Logic

IF NOT p_srch1 IS INITIAL.
*  To find out the messages for first search criteria
  PERFORM search_string TABLES    gt_msgtab_ext[]
  gt_msgtab_ext_new[]
  USING     p_srch1.
  IF NOT p_srch2 IS INITIAL.
*  To find out the messages for second search criteria
    PERFORM search_string TABLES    gt_msgtab_ext[]
    gt_msgtab_ext_new2[]
    USING     p_srch2.
*  To get the messages which contains both the search criteria
    IF p_and EQ 'X'.
      LOOP AT gt_msgtab_ext_new INTO gw_msgtab_ext_new.
        READ TABLE gt_msgtab_ext_new2 INTO gw_msgtab_ext_new2
        WITH KEY msgguid = gw_msgtab_ext_new-msgguid.
        IF sy-subrc NE 0.
          DELETE gt_msgtab_ext_new.
          CLEAR: gw_msgtab_ext_new.
        ENDIF.
        CLEAR gw_msgtab_ext_new2.
      ENDLOOP.

*  To get the messages which contains any of the search criteria
    ELSEIF p_or EQ 'X'.
      LOOP AT gt_msgtab_ext_new2 INTO gw_msgtab_ext_new2.
        READ TABLE gt_msgtab_ext_new INTO gw_msgtab_ext_new
        WITH KEY msgguid = gw_msgtab_ext_new2-msgguid.
        IF sy-subrc NE 0.
          APPEND gw_msgtab_ext_new2 TO gt_msgtab_ext_new.
          CLEAR: gw_msgtab_ext_new2.
        ENDIF.
        CLEAR gw_msgtab_ext_new2.
      ENDLOOP.
    ENDIF.
  ENDIF.
*Send the output table to ALV
  CALL METHOD msglist->set_table_for_first_display
    EXPORTING
      is_layout                     = gs_layout
      it_toolbar_excluding          = gt_ui_func
      is_variant                    = alv_variant
      i_save                        = alv_save
    CHANGING
      it_fieldcatalog               = gt_fieldcat
      it_outtab                     = gt_msgtab_ext_new
      it_sort                       = lt_sort
    EXCEPTIONS
      invalid_parameter_combination = 1
      program_error                 = 2
      too_many_lines                = 3
      OTHERS                        = 4.
  IF sy-subrc = 3.
    MESSAGE s100(xms_adm) WITH text-e03.
  ELSEIF sy-subrc <> 0.
    MESSAGE s100(xms_adm) WITH text-e04.
  ENDIF.
ELSE.
  CALL METHOD msglist->set_table_for_first_display
    EXPORTING
      is_layout                     = gs_layout
      it_toolbar_excluding          = gt_ui_func
      is_variant                    = alv_variant
      i_save                        = alv_save
    CHANGING
      it_fieldcatalog               = gt_fieldcat
      it_outtab                     = gt_msgtab_ext
      it_sort                       = lt_sort
    EXCEPTIONS
      invalid_parameter_combination = 1
      program_error                 = 2
      too_many_lines                = 3
      OTHERS                        = 4.
  IF sy-subrc = 3.
    MESSAGE s100(xms_adm) WITH text-e03.
  ELSEIF sy-subrc <> 0.
    MESSAGE s100(xms_adm) WITH text-e04.
  ENDIF.
ENDIF.


****************************************************
*** To search the search criteria in XML message body
*******************************************************
FORM search_string  TABLES    p_gt_msgtab_ext
p_gt_msgtab_ext_new
USING     p_search.
  LOOP AT p_gt_msgtab_ext INTO gw_msgtab_ext.
    clustkey-msgguid = gw_msgtab_ext-msgguid.
    clustkey-pid     = gw_msgtab_ext-pid.
    clustkey-vers    = gw_msgtab_ext-vers.
    gv_versprogr     = 000.
    DO gw_msgtab_ext-vers TIMES.
      gv_versprogr = gv_versprogr + 1.
      TRY.
          CALL METHOD persist->read_persist_tab_all_pub
* call method persist->read_persist_tab_version
          EXPORTING
          im_msgguid = clustkey-msgguid
          im_pid = clustkey-pid
          im_version = gv_versprogr
          IMPORTING
          ex_pmast = gw_sxmspmast
          ex_pvers = gw_sxmspvers
          ex_tprop = gw_sxmspprop1
          ex_tres  = gw_sxmspres1
          ex_txres = gw_sxmspxres1
          ex_tns   = gw_sxmspns1.
        CATCH cx_xms_syserr_persist INTO oref.
          MESSAGE oref TYPE 'S' DISPLAY LIKE 'E'.
          EXIT.
      ENDTRY.
      TRY.
        CALL METHOD persist->built_msg
          EXPORTING
            im_pmast   = gw_sxmspmast
            im_tprop   = gw_sxmspprop1
            im_tres    = gw_sxmspres1
            im_txres   = gw_sxmspxres1
            im_tns     = gw_sxmspns1
          IMPORTING
            ex_message = g_message.
        CLEAR res.
        CALL METHOD g_message->getattachmentatindex
          EXPORTING
            index    = 1
          RECEIVING
            resource = res.
        IF res IS INITIAL.
          CONTINUE.
        ENDIF.
        CALL METHOD res->getbinarydata
          RECEIVING
            data = gv_xstringa.
        DATA partutil TYPE REF TO cl_xms_part_util.
        partutil = cl_xms_part_util=>getinstance( ).
        DATA l_conttypeobj TYPE REF TO cl_xms_contenttype.
        CREATE OBJECT l_conttypeobj.
        l_conttypeobj->valuesfromstring( values = 'T' ).
        CLEAR gv_mimetype.
        gv_mimetype = l_conttypeobj->getmimetype( ).
        CLEAR gv_charset.
        gv_charset = l_conttypeobj->getcharset( ).
        TRY.
            gv_stringa = partutil->convert_xstring_to_string( charset = gv_charset
            in = gv_xstringa ).
            IF gv_stringa CS p_search.
*                gr_msgguid-low = gw_msgtab_ext-msgguid.
*                gr_msgguid-sign = 'I'.
*                gr_msgguid-option = 'EQ'.
*                APPEND gr_msgguid.
              MOVE gw_msgtab_ext TO gw_msgtab_ext_new.
              APPEND gw_msgtab_ext_new TO p_gt_msgtab_ext_new.
              CLEAR: gw_msgtab_ext_new.
              EXIT.
            ENDIF.
          CATCH cx_xms_exception.
* unfortunately this exception is not declared for this method and
*cannot be thrown further
        ENDTRY.
      ENDTRY.
    ENDDO.
    CLEAR: gw_msgtab_ext.
  ENDLOOP.
 

Author: Sergio Cipolla
Submitted: 03 February 2009

Transport targets are used in PI to indicate the correspondance between business systems in different landscapes.
Business Systems that belong to the same landscape and share the same integration server, are part of the same Business System Group.
 
When importing a directory object (e.g. BUSINESS_SYSTEM_DEV) from development (GROUP_DEV) to quality system (GROUP_QAS), the first thing that is done is lookup the SLD to find which is the transport target for that business system in the target group GROUP_QAS.

If the SLD was correctly configured it will return the business system BUSINESS_SYSTEM_QAS, otherwise, if no transport target is found it will not be possible to import the object.

If you have a lot of business systems it is not so easy to check that all transport target are correctly configured, especially if you are doing a system copy or a new system creation.

As far as I know there is no tool to massively check transport targets, so I have developed my own.

The report takes as input the parameters used to connect to the System Landscape Directory and the Business System Group (plus a Business System Name Filter) and is able to display the list of Source or Target Business Systems for all Business Systems in the Group Specified.


 

 
 

 *&---------------------------------------------------------------------*
*& Report  ZTEDGE_PI_CHECK_BS_TARGET
*&
*&---------------------------------------------------------------------*
*& Author: Sergio Cipolla
*&
*&---------------------------------------------------------------------*
REPORT  ztedge_pi_check_bs_target.

SELECTION-SCREEN BEGIN OF BLOCK block1 WITH FRAME TITLE txt01.
PARAMETERS: phost TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: pport TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: pnspace TYPE char30 LOWER CASE OBLIGATORY DEFAULT 'sld/active'.
PARAMETERS: puser TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: ppass TYPE char30 LOWER CASE OBLIGATORY.
SELECTION-SCREEN END OF BLOCK block1.

SELECTION-SCREEN BEGIN OF BLOCK block2 WITH FRAME TITLE txt02.
PARAMETERS: pbsnam TYPE char30.
PARAMETERS: pgroup TYPE char30 LOWER CASE OBLIGATORY.
PARAMETERS: pfrom RADIOBUTTON GROUP g1.
PARAMETERS: pto RADIOBUTTON GROUP g1.
PARAMETERS: plist AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK block2.


*******************************************************************************
** INITIALIZATION
*******************************************************************************
INITIALIZATION.
  txt01 = 'SLD parameters'.
  %_phost_%_app_% = 'Hostname'.
  %_pport_%_app_% = 'Port'.
  %_pnspace_%_app_% = 'Namespace'.
  %_puser_%_app_% = 'User'.
  %_ppass_%_app_% = 'Password'.

  txt02 = 'Business Systems parameters'.
  %_pbsnam_%_app_% = 'Business System Filter'.
  %_pgroup_%_app_% = 'Business System Group'.
  %_pfrom_%_app_% = 'Search Source Business Systems'.
  %_pto_%_app_% = 'Search Target Business Systems'.
  %_plist_%_app_% = 'Display Systems with no Target/Source'.

  phost  = syst-host.
  TRANSLATE phost TO LOWER CASE.

  DATA: l_sysnr TYPE instanz-systemnr,
        l_str_sysnr TYPE string.

  CALL FUNCTION 'GET_SYSTEM_NUMBER'
    IMPORTING
      instancenumber = l_sysnr.
  l_str_sysnr = l_sysnr.
  CONCATENATE '5' l_str_sysnr '00' INTO pport.

  puser      = sy-uname.
  TRANSLATE puser TO LOWER CASE.

*******************************************************************************
** START OF SELECTION
*******************************************************************************
START-OF-SELECTION.

  TYPES: BEGIN OF type_target_ident,
    bs_name TYPE string,
    bs_group TYPE string,
    related_bs_name TYPE string,
    related_bs_group TYPE string,
  END OF type_target_ident.

  TYPES: ttype_target_ident TYPE TABLE OF type_target_ident.

  DATA: lw_target TYPE type_target_ident,
        lt_ttargets TYPE TABLE OF type_target_ident,
        l_systems_found TYPE i VALUE 0.

*Declared Globally as per Note 534857 - ALV: RMC_COMMUNICATION_FAILURE short dump when scrolling
  TYPES: BEGIN OF print_result,
    bs_name TYPE string,
    bs_group TYPE string,
    group1_bs TYPE string,
    group2_bs TYPE string,
    group3_bs TYPE string,
    group4_bs TYPE string,
    group5_bs TYPE string,
    group6_bs TYPE string,
  END OF print_result.


  DATA: gw_print_result TYPE print_result,
        gt_print_result TYPE TABLE OF print_result.

  DATA: my_sld_host     TYPE string,
        my_sld_port     TYPE i,
        my_namespace    TYPE string,
        my_user         TYPE string,
        my_password     TYPE string,
        accessor        TYPE REF TO cl_sld_accessor,
        ex              TYPE REF TO cx_sld_api_exception,
        value           TYPE string,
        filter          TYPE REF TO cl_sld_filter.

  DATA: c_group1       TYPE string,
        c_group2       TYPE string,
        c_group3       TYPE string,
        c_group4       TYPE string,
        c_group5       TYPE string,
        c_group6       TYPE string.


  CLASS cl_sld_util DEFINITION LOAD.
  FORMAT INTENSIFIED OFF.

  DATA: techsys_3party TYPE string VALUE 'SAP_ApplicationSystem'.
  DATA: business_system TYPE string VALUE 'SAP_BusinessSystem'.
  DATA: lt_instances TYPE sld_t_instref.
  DATA: lc_instance TYPE REF TO cl_sld_cim_instance.


  DATA: lt_destinations TYPE sld_s_accessdata_display OCCURS 0,
        lw_destination TYPE sld_s_accessdata_display,
        lt_return TYPE bapiret2 OCCURS 0.

  DATA l_filter TYPE string.
  l_filter = pbsnam.

* Set SLD access parameters:
  my_sld_host  = phost.
  my_sld_port  = pport.
  my_namespace = pnspace.
  my_user      = puser.
  my_password  = ppass.

* Create accessor object to SLD server:
  CREATE OBJECT accessor
    EXPORTING
      host      = my_sld_host
      port      = my_sld_port
      namespace = my_namespace
      user      = my_user
      password  = my_password.

* set trace level for java logging.
  accessor->set_tracelevel( 1 ).

* Test the connection to the SLD server:
  TRY.
      accessor->ping( ).
    CATCH cx_sld_api_exception INTO ex.
      value = ex->get_text( ).
      WRITE: / 'PING failed!' COLOR 6,
          AT / value.
      ULINE.
      RETURN.
  ENDTRY.

* Catch all exceptions potentially triggered by the API:
  TRY.

    CREATE OBJECT filter.
    IF NOT l_filter IS INITIAL.
      filter->add_pattern( pname = 'Name'
                           value = l_filter ).
    ELSE.
      filter->add_pattern( pname = 'Name'
                           value = '*' ).
    ENDIF.

    lt_instances = accessor->enumerate_instances( cname = business_system
                                                  filter = filter ).

    DATA: l_bs_total TYPE i.
    DATA: l_str_bs_total TYPE string.

    DESCRIBE TABLE lt_instances LINES l_bs_total.
    l_str_bs_total = l_bs_total.

    LOOP AT lt_instances INTO lc_instance.

      DATA: l_sap_gui_text TYPE string.
      DATA: l_current TYPE string.
      l_current = sy-tabix.

      CONCATENATE 'Evaluating Business System' l_current 'of' l_str_bs_total INTO l_sap_gui_text SEPARATED BY space.
      CALL FUNCTION 'SAPGUI_PROGRESS_INDICATOR'
        EXPORTING
          percentage = 0
          text       = l_sap_gui_text.

*    TRY.
      CLEAR lw_target.

      DATA: l_string TYPE string.
      DATA: l_classname TYPE string.

      lw_target-bs_name =  lc_instance->get_property( pname = 'Name' ).
      l_classname = lc_instance->get_property( pname = 'CreationClassName' ).

* To avoid usage of inherited classes
      IF l_classname NE business_system.
        CONTINUE.
      ENDIF.

      PERFORM getgroup USING lc_instance '' CHANGING lw_target-bs_group.

      IF NOT pgroup IS INITIAL.
        IF pgroup NE lw_target-bs_group.
          CONTINUE.
        ENDIF.
      ENDIF.

*Get all transport target for the selected system
      DATA: l_role TYPE string.
      IF pto = 'X'.
        l_role = 'Antecedent'.
      ELSE.
        l_role =  'Dependent'.
      ENDIF.

      DATA: lt_instnames TYPE sld_t_string.
      DATA: l_insthandle TYPE string.
      lt_instnames = accessor->associatornames( iref = lc_instance
                                                assocclass  = 'SAP_BusinessSystemPath'
                                                role = l_role ).

      DATA : l_lines TYPE i.
      DESCRIBE TABLE lt_instnames LINES l_lines.
      IF l_lines > 0.
        l_systems_found = l_systems_found + 1.
      ELSE.
        IF plist = 'X'. "List anyway
          APPEND lw_target TO lt_ttargets.
          l_systems_found = l_systems_found + 1.
        ENDIF.
      ENDIF.

      LOOP AT lt_instnames  INTO l_insthandle.

        CLEAR : lw_target-related_bs_name, lw_target-related_bs_group.
        lw_target-related_bs_name = accessor->get_property(
              ihandle = l_insthandle
              pname   = 'Name').

        DATA: l_dummy_inst TYPE REF TO cl_sld_cim_instance.
        DATA: l_assoc_group TYPE string.
        PERFORM getgroup USING l_dummy_inst l_insthandle changing lw_target-related_bs_group.

        PERFORM registergroup USING lw_target-related_bs_group.

        APPEND lw_target TO lt_ttargets.
      ENDLOOP.
    ENDLOOP.
  ENDTRY.

  SORT lt_ttargets BY bs_name bs_group related_bs_group related_bs_name.

  PERFORM print_result TABLES lt_ttargets USING l_systems_found.

  SELECTION-SCREEN BEGIN OF SCREEN 1001.
  SELECTION-SCREEN END OF SCREEN 1001.
  CALL SELECTION-SCREEN 1001.
*&---------------------------------------------------------------------*
*&      Form  getGroup
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->PO_INSTANCE  text
*      -->PE_GROUP     text
*----------------------------------------------------------------------*
FORM getgroup USING pi_instance TYPE REF TO cl_sld_cim_instance
                    pi_handle TYPE string
              CHANGING pe_group TYPE string.

  DATA: lt_ass_handles TYPE sld_t_string.
  DATA: l_ass_handle TYPE string.

  CLEAR pe_group.

  TRY.
      IF pi_handle IS INITIAL.
        lt_ass_handles = accessor->associatornames( iref = pi_instance
                                                  assocclass  = 'SAP_CollectedBusinessSystems' ).
      ELSE.
        lt_ass_handles = accessor->associatornames( ihandle = pi_handle
                                                  assocclass  = 'SAP_CollectedBusinessSystems' ).

      ENDIF.
    CATCH cx_sld_api_exception .
  ENDTRY.

  LOOP AT lt_ass_handles INTO l_ass_handle.
    TRY.
        pe_group = accessor->get_property( ihandle = l_ass_handle
                                          pname = 'Name' ).
      CATCH cx_sld_api_exception .
    ENDTRY.
  ENDLOOP.
ENDFORM.                    "getGroup
*&---------------------------------------------------------------------*
*&      Form  print_result
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LT_TTARGETS  text
*      -->P_L_SYSTEMS_FOUND  text
*----------------------------------------------------------------------*
FORM print_result  TABLES   pt_ttargets TYPE ttype_target_ident
                   USING    pi_systems_found.

  DATA: lw_target TYPE LINE OF ttype_target_ident.
  DATA: l_current_sys TYPE string.
  DATA: l_string TYPE string.

  LOOP AT lt_ttargets INTO lw_target.
    IF l_current_sys NE lw_target-bs_name.
      IF NOT gw_print_result IS INITIAL.
        APPEND gw_print_result TO gt_print_result.
        CLEAR gw_print_result.
      ENDIF.
      l_current_sys = lw_target-bs_name.
      gw_print_result-bs_name = lw_target-bs_name.
      gw_print_result-bs_group = lw_target-bs_group.
    ENDIF.

    CASE lw_target-related_bs_group.
      WHEN c_group1.
        IF gw_print_result-group1_bs IS INITIAL.
          gw_print_result-group1_bs = lw_target-related_bs_name.
        ELSE.
          CONCATENATE gw_print_result-group1_bs ',' lw_target-related_bs_name INTO l_string.
          gw_print_result-group1_bs = l_string.
        ENDIF.
      WHEN c_group2.
        IF gw_print_result-group2_bs IS INITIAL.
          gw_print_result-group2_bs = lw_target-related_bs_name.
        ELSE.
          CONCATENATE gw_print_result-group2_bs ',' lw_target-related_bs_name INTO l_string.
          gw_print_result-group2_bs = l_string.
        ENDIF.
      WHEN c_group3.
        IF gw_print_result-group3_bs IS INITIAL.
          gw_print_result-group3_bs = lw_target-related_bs_name.
        ELSE.
          CONCATENATE gw_print_result-group3_bs ',' lw_target-related_bs_name INTO l_string.
          gw_print_result-group3_bs = l_string.
        ENDIF.
      WHEN c_group4.
        IF gw_print_result-group4_bs IS INITIAL.
          gw_print_result-group4_bs = lw_target-related_bs_name.
        ELSE.
          CONCATENATE gw_print_result-group4_bs ',' lw_target-related_bs_name INTO l_string.
          gw_print_result-group4_bs = l_string.
        ENDIF.
      WHEN c_group5.
        IF gw_print_result-group5_bs IS INITIAL.
          gw_print_result-group5_bs = lw_target-related_bs_name.
        ELSE.
          CONCATENATE gw_print_result-group5_bs ',' lw_target-related_bs_name INTO l_string.
          gw_print_result-group5_bs = l_string.
        ENDIF.
      WHEN c_group6.
        IF gw_print_result-group6_bs IS INITIAL.
          gw_print_result-group6_bs = lw_target-related_bs_name.
        ELSE.
          CONCATENATE gw_print_result-group6_bs ',' lw_target-related_bs_name INTO l_string.
          gw_print_result-group6_bs = l_string.
        ENDIF.
    ENDCASE.
  ENDLOOP.

  IF NOT gw_print_result IS INITIAL.
    APPEND gw_print_result TO gt_print_result.
  ENDIF.
  DATA:
        go_layout     TYPE lvc_s_layo,                  " layout options
        lt_sort       TYPE lvc_t_sort,                  " sorting options
        wa_sort       TYPE LINE OF lvc_t_sort,          " sorting options
        lt_exclude    TYPE ui_functions,                " excluded functions
        wa_exclude    TYPE ui_func,                     " excluded functions
        lt_fieldcatalog TYPE lvc_t_fcat,                " field catalog
        wa_fieldcatalog TYPE LINE OF lvc_t_fcat,        " field catalog
        go_container  TYPE REF TO cl_gui_container,     " container
        go_alv        TYPE REF TO cl_gui_alv_grid.     	" ALV

  l_string = l_systems_found.
  CONCATENATE 'Business Systems found: ' l_string INTO l_string SEPARATED BY space.
  TRY.
*======================= LAYOUT ====================================*
    go_layout-zebra      = 'X'.
    go_layout-grid_title = l_string.
    go_layout-cwidth_opt = 'X'.
*===================================================================*

*========================= SORT ====================================*
*===================================================================*
*==================== FIELD CATALOG ================================*
    wa_fieldcatalog-fieldname = 'BS_NAME'.
    wa_fieldcatalog-reptext  = 'BUSINESS SYSTEM'.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'BS_NAME'.
    wa_fieldcatalog-key = 'X'.
    wa_fieldcatalog-emphasize = 'X'.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'BS_GROUP'.
    wa_fieldcatalog-reptext  = 'GROUP'.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'BS_GROUP'.
    wa_fieldcatalog-no_out = 'X'.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'GROUP1_BS'.
    wa_fieldcatalog-reptext  = c_group1.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'GROUP1_BS'.
    if c_group1 is initial.
      wa_fieldcatalog-no_out = 'X'.
    endif.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'GROUP2_BS'.
    wa_fieldcatalog-reptext  = c_group2.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'GROUP2_BS'.
    if c_group2 is initial.
      wa_fieldcatalog-no_out = 'X'.
    endif.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'GROUP3_BS'.
    wa_fieldcatalog-reptext  = c_group3.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'GROUP3_BS'.
        if c_group3 is initial.
      wa_fieldcatalog-no_out = 'X'.
    endif.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'GROUP4_BS'.
    wa_fieldcatalog-reptext  = c_group4.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'GROUP4_BS'.
        if c_group4 is initial.
      wa_fieldcatalog-no_out = 'X'.
    endif.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'GROUP5_BS'.
    wa_fieldcatalog-reptext  = c_group5.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'GROUP5_BS'.
    if c_group5 is initial.
      wa_fieldcatalog-no_out = 'X'.
    endif.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

    wa_fieldcatalog-fieldname = 'GROUP6_BS'.
    wa_fieldcatalog-reptext  = c_group6.
    wa_fieldcatalog-ref_table = 'PRINT_RESULT'.
    wa_fieldcatalog-ref_field = 'GROUP6_BS'.
    if c_group6 is initial.
      wa_fieldcatalog-no_out = 'X'.
    endif.
    APPEND wa_fieldcatalog TO lt_fieldcatalog.
    CLEAR wa_fieldcatalog.

*===================================================================*
    CREATE OBJECT go_alv
      EXPORTING
        i_parent = cl_gui_container=>screen0.

    CREATE OBJECT go_container
      EXPORTING
        clsid = space.

    go_alv->set_graphics_container(
      EXPORTING
        i_graphics_container = go_container
    ).

    go_alv->set_table_for_first_display(
         EXPORTING
           is_layout            = go_layout
           it_toolbar_excluding = lt_exclude
         CHANGING
           it_outtab        = gt_print_result
           it_sort          = lt_sort
           it_fieldcatalog  = lt_fieldcatalog
    ).

  ENDTRY.
ENDFORM.                    "print_result
*&---------------------------------------------------------------------*
*&      Form  REGISTERGROUP
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*      -->P_LW_TARGET_RELATED_BS_GROUP  text
*----------------------------------------------------------------------*
FORM registergroup  USING p_group TYPE string.

  DATA: l_registered TYPE c.

  IF c_group1 = p_group OR c_group2 = p_group OR c_group3 = p_group
    OR c_group4 = p_group OR c_group5 = p_group OR c_group6 = p_group.
  ELSE.
    IF l_registered IS INITIAL AND c_group1 IS INITIAL.
      c_group1 = p_group.
      l_registered = 'X'.
    ENDIF.
    IF l_registered IS INITIAL AND c_group2 IS INITIAL.
      c_group2 = p_group.
      l_registered = 'X'.
    ENDIF.
    IF l_registered IS INITIAL AND c_group3 IS INITIAL.
      c_group3 = p_group.
      l_registered = 'X'.
    ENDIF.
    IF l_registered IS INITIAL AND c_group4 IS INITIAL.
      c_group4 = p_group.
      l_registered = 'X'.
    ENDIF.
    IF l_registered IS INITIAL AND c_group5 IS INITIAL.
      c_group5 = p_group.
      l_registered = 'X'.
    ENDIF.
    IF l_registered IS INITIAL AND c_group6 IS INITIAL.
      c_group6 = p_group.
      l_registered = 'X'.
    ENDIF.
  ENDIF.

ENDFORM.                    " REGISTERGROUP






Author: Alessandro Guarneri

Submitted: 10 Jan 2010
Related Links:

An implementation of an Axis Handler that can be used in SAP PI SOAP receiver commuincatio channel in order to "tame" the SOAP Fault monster (see related blog for the full story).

Sorry for bad Java code formatting, it's my first wiki page and I can't find a better way at the moment. Just copy and paste into your favourite IDE and format it (CTRL+SHIFT+F will do the magic in Eclipse / NWDS).

package org.guarneri.axis.lab;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.MimeHeader;
import javax.xml.soap.MimeHeaders;
import javax.xml.soap.SOAPException;

import org.apache.axis.AxisFault;
import org.apache.axis.Constants;
import org.apache.axis.Message;
import org.apache.axis.MessageContext;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.components.net.BooleanHolder;
import org.apache.axis.components.net.DefaultSocketFactory;
import org.apache.axis.components.net.SocketFactory;
import org.apache.axis.components.net.SocketFactoryFactory;
import org.apache.axis.encoding.Base64;
import org.apache.axis.handlers.BasicHandler;
import org.apache.axis.message.SOAPHeaderElement;
import org.apache.axis.soap.SOAPConstants;
import org.apache.axis.transport.http.ChunkedInputStream;
import org.apache.axis.transport.http.ChunkedOutputStream;
import org.apache.axis.transport.http.HTTPConstants;
import org.apache.axis.transport.http.SocketHolder;
import org.apache.axis.transport.http.SocketInputStream;
import org.apache.axis.utils.Messages;
import org.apache.axis.utils.TeeOutputStream;
import org.apache.commons.logging.Log;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.sap.aii.axis.transport.io.Recorder;
import com.sap.aii.axis.transport.io.RecorderManager;
import com.sap.engine.lib.xml.parser.DOMParser;
import com.sap.engine.lib.xml.util.DOMSerializer;
import com.sun.org.apache.bcel.internal.classfile.Method;

public class TolerantHttpSender extends BasicHandler {

public TolerantHttpSender() {
}

public void invoke(MessageContext msgContext) throws AxisFault {

hijacking = false;

log.debug(mySIG + "invoke() BEGIN");

// StatusAgent mon = (StatusAgent)getOption("AgentName");
// mon.reportEvent(Status.OK, "TolerantHttpSender_Working_v2.invoke \!",
// options);

if (log.isDebugEnabled())
log.debug(Messages.getMessage("enter00", "HTTPSender::invoke"));
SocketHolder socketHolder = new SocketHolder(null);
try {
BooleanHolder useFullURL = new BooleanHolder(false);
StringBuffer otherHeaders = new StringBuffer();
targetURL = new URL(msgContext.getStrProp("transport.url"));
String host = targetURL.getHost();
int port = targetURL.getPort();

log.debug(mySIG + "writeToSocket()");
InputStream inp = writeToSocket(socketHolder, msgContext,
targetURL, otherHeaders, host, port, msgContext
.getTimeout(), useFullURL);
Hashtable headers = new Hashtable();

log.debug(mySIG + "readHeadersFromSocket()");
inp = readHeadersFromSocket(socketHolder, msgContext, inp, headers);

log.debug(mySIG + "readFromSocket()");
readFromSocket(socketHolder, msgContext, inp, headers);

log.debug(mySIG + "invoke() END");

} catch (Exception e) {
log.debug(e);
try {
if (socketHolder.getSocket() \!= null)
socketHolder.getSocket().close();
} catch (IOException ie) {
}
RuntimeException rt = new RuntimeException(
"TolerantHttpSender error in invoke(): " + e);
throw AxisFault.makeFault(rt);
}
if (log.isDebugEnabled())
log.debug(Messages.getMessage("exit00",
"HTTPDispatchHandler::invoke"));
}

protected void getSocket(SocketHolder sockHolder,
MessageContext msgContext, String protocol, String host, int port,
int timeout, StringBuffer otherHeaders, BooleanHolder useFullURL)
throws Exception {
Hashtable options = getOptions();
if (timeout > 0) {
if (options == null)
options = new Hashtable();
options.put(DefaultSocketFactory.CONNECT_TIMEOUT, Integer
.toString(timeout));
}
SocketFactory factory = SocketFactoryFactory.getFactory(protocol,
options);
if (factory == null)
throw new IOException(Messages.getMessage("noSocketFactory",
protocol));
if (log.isInfoEnabled())
log.info((new StringBuilder()).append("socket factory: ").append(
factory.getClass()).toString());
Socket sock = factory.create(host, port, otherHeaders, useFullURL);
if (timeout > 0)
sock.setSoTimeout(timeout);
sockHolder.setSocket(sock);
}

private InputStream writeToSocket(SocketHolder sockHolder,
MessageContext msgContext, URL tmpURL, StringBuffer otherHeaders,
String host, int port, int timeout, BooleanHolder useFullURL)
throws Exception {
String userID = msgContext.getUsername();
String passwd = msgContext.getPassword();
Recorder recorder = RecorderManager.getInstance().getRecorder();
String action = msgContext.useSOAPAction() ? msgContext
.getSOAPActionURI() : "";
if (action == null)
action = "";
if (userID == null && tmpURL.getUserInfo() \!= null) {
String info = tmpURL.getUserInfo();
int sep = info.indexOf(':');
if (sep >= 0 && sep + 1 < info.length()) {
userID = info.substring(0, sep);
passwd = info.substring(sep + 1);
} else {
userID = info;
}
}
if (userID \!= null) {
StringBuffer tmpBuf = new StringBuffer();
tmpBuf.append(userID).append(":").append(
passwd \!= null ? passwd : "");
otherHeaders.append("Authorization").append(": Basic ").append(
Base64.encode(tmpBuf.toString().getBytes())).append("\r\n");
}
if (msgContext.getMaintainSession()) {
fillHeaders(msgContext, "Cookie", otherHeaders);
fillHeaders(msgContext, "Cookie2", otherHeaders);
}
StringBuffer header2 = new StringBuffer();
String webMethod = null;
boolean posting = true;
Message reqMessage = msgContext.getRequestMessage();
boolean http10 = true;
boolean httpChunkStream = false;
boolean httpContinueExpected = false;
String httpConnection = null;
String httpver = msgContext.getStrProp("axis.transport.version");
if (null == httpver)
httpver = HTTPConstants.HEADER_PROTOCOL_V10;
httpver = httpver.trim();
if (httpver.equals(HTTPConstants.HEADER_PROTOCOL_V11))
http10 = false;
Hashtable userHeaderTable = (Hashtable) msgContext
.getProperty("HTTP-Request-Headers");
if (userHeaderTable \!= null) {
if (null == otherHeaders)
otherHeaders = new StringBuffer(1024);
Iterator e = userHeaderTable.entrySet().iterator();
do {
if (\!e.hasNext())
break;
java.util.Map.Entry me = (java.util.Map.Entry) e.next();
Object keyObj = me.getKey();
if (null \!= keyObj) {
String key = keyObj.toString().trim();
if (key
.equalsIgnoreCase(HTTPConstants.HEADER_TRANSFER_ENCODING)) {
if (\!http10) {
String val = me.getValue().toString();
if (null \!= val
&& val
.trim()
.equalsIgnoreCase(
HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
httpChunkStream = true;
}
} else if (key.equalsIgnoreCase("Connection")) {
if (\!http10) {
String val = me.getValue().toString();
if (val.trim().equalsIgnoreCase(
HTTPConstants.HEADER_CONNECTION_CLOSE))
httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
}
} else {
if (\!http10 && key.equalsIgnoreCase("Expect")) {
String val = me.getValue().toString();
if (null \!= val
&& val.trim().equalsIgnoreCase(
"100-continue"))
httpContinueExpected = true;
}
otherHeaders.append(key).append(": ").append(
me.getValue()).append("\r\n");
}
}
} while (true);
}
if (\!http10)
httpConnection = HTTPConstants.HEADER_CONNECTION_CLOSE;
header2.append(" ");
header2.append(http10 ? "HTTP/1.0" : "HTTP/1.1").append("\r\n");
MimeHeaders mimeHeaders = reqMessage.getMimeHeaders();
if (posting) {
String header\[\] = mimeHeaders.getHeader("Content-Type");
String contentType;
if (header \!= null && header.length > 0)
contentType = mimeHeaders.getHeader("Content-Type")\[0\];
else
contentType = reqMessage.getContentType(msgContext
.getSOAPConstants());
if (contentType == null \|\| contentType.equals(""))
throw new Exception(Messages.getMessage("missingContentType"));
if (msgContext.useSOAPAction()
&& msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS
&& reqMessage.countAttachments() == 0)
contentType = (new StringBuilder()).append(contentType).append(
"; action=\"").append(action).append("\"").toString();
header2.append("Content-Type").append(": ").append(contentType)
.append("\r\n");
}
header2.append(ACCEPT_HEADERS).append("Host").append(": ").append(host)
.append(
port \!= \-1 ? (new StringBuilder()).append(":").append(
port).toString() : "").append("\r\n").append(
"Cache-Control: no-cache\r\nPragma: no-cache\r\n");
if (msgContext.getSOAPConstants() == SOAPConstants.SOAP11_CONSTANTS
\|\| msgContext.getProperty("attachment_encapsulation_format") == "axis.attachment.style.dime")
header2.append("SOAPAction").append(": \"").append(action).append(
"\"\r\n");
if (posting)
if (\!httpChunkStream)
header2.append("Content-Length").append(": ").append(
reqMessage.getContentLength()).append("\r\n");
else
header2.append(CHUNKED_HEADER);
if (mimeHeaders \!= null) {
Iterator i = mimeHeaders.getAllHeaders();
do {
if (\!i.hasNext())
break;
MimeHeader mimeHeader = (MimeHeader) i.next();
String headerName = mimeHeader.getName();
if (\!headerName.equals("Content-Type")
&& \!headerName.equals("SOAPAction"))
header2.append(mimeHeader.getName()).append(": ").append(
mimeHeader.getValue()).append("\r\n");
} while (true);
}
if (null \!= httpConnection) {
header2.append("Connection");
header2.append(": ");
header2.append(httpConnection);
header2.append("\r\n");
}
getSocket(sockHolder, msgContext, targetURL.getProtocol(), host, port,
timeout, otherHeaders, useFullURL);
if (null \!= otherHeaders)
header2.append(otherHeaders.toString());
header2.append("\r\n");
StringBuffer header = new StringBuffer();
if (msgContext.getSOAPConstants() == SOAPConstants.SOAP12_CONSTANTS)
webMethod = msgContext.getStrProp("soap12.webmethod");
if (webMethod == null)
webMethod = "POST";
else
posting = webMethod.equals("POST");
header.append(webMethod).append(" ");
if (useFullURL.value)
header.append(tmpURL.toExternalForm());
else
header.append(tmpURL.getFile() \!= null
&& \!tmpURL.getFile().equals("") ? tmpURL.getFile() : "/");
header.append(header2.toString());
OutputStream out = sockHolder.getSocket().getOutputStream();
if (recorder \!= null)
out = recorder.getOutputStream().set(out);
if (\!posting) {
out.write(header.toString().getBytes("iso-8859-1"));
out.flush();
return null;
}
InputStream inp = null;
if (httpChunkStream \|\| httpContinueExpected)
out.write(header.toString().getBytes("iso-8859-1"));
if (httpContinueExpected) {
out.flush();
Hashtable cheaders = new Hashtable();
inp = readHeadersFromSocket(sockHolder, msgContext, null, cheaders);
int returnCode = \-1;
Integer Irc = (Integer) msgContext
.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
if (null \!= Irc)
returnCode = Irc.intValue();
if (100 == returnCode) {
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);

// AG: handle HTTP 500
} else if (returnCode == 500) {

// AG: Don't do anything, as if everything was runing smoothly\!

} else {
String statusMessage = (String) msgContext
.getProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
AxisFault fault = new AxisFault("HTTP", (new StringBuilder())
.append("(").append(returnCode).append(")").append(
statusMessage).toString(), null, null);
fault.setFaultDetailString(Messages.getMessage("return01",
(new StringBuilder()).append("").append(returnCode)
.toString(), ""));
throw fault;
}
}
ByteArrayOutputStream baos = null;
if (log.isDebugEnabled()) {
log.debug(Messages.getMessage("xmlSent00"));
log.debug("---------------------------------------------------");
baos = new ByteArrayOutputStream();
}
if (httpChunkStream) {
ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(
out);
out = new BufferedOutputStream(chunkedOutputStream, 8192);
try {
if (baos \!= null)
out = new TeeOutputStream(out, baos);
reqMessage.writeTo(out);
} catch (SOAPException e) {
log.error(Messages.getMessage("exception00"), e);
}
out.flush();
chunkedOutputStream.eos();
} else {
out = new BufferedOutputStream(out, 8192);
try {
if (\!httpContinueExpected)
out.write(header.toString().getBytes("iso-8859-1"));
if (baos \!= null)
out = new TeeOutputStream(out, baos);
reqMessage.writeTo(out);
} catch (SOAPException e) {
log.error(Messages.getMessage("exception00"), e);
}
out.flush();
}
if (log.isDebugEnabled())
log.debug((new StringBuilder()).append(header).append(
new String(baos.toByteArray())).toString());
return inp;
}

private void fillHeaders(MessageContext msgContext, String header,
StringBuffer otherHeaders) {
Object ck1 = msgContext.getProperty(header);
if (ck1 \!= null)
if (ck1 instanceof String\[\]) {
String cookies\[\] = (String\[\]) (String\[\]) ck1;
for (int i = 0; i < cookies.length; i++)
addCookie(otherHeaders, header, cookies\[i\]);

} else {
addCookie(otherHeaders, header, (String) ck1);
}
}

private void addCookie(StringBuffer otherHeaders, String header,
String cookie) {
otherHeaders.append(header).append(": ").append(cookie).append("\r\n");
}

private InputStream readHeadersFromSocket(SocketHolder sockHolder,
MessageContext msgContext, InputStream inp, Hashtable headers)
throws IOException {
Recorder recorder = RecorderManager.getInstance().getRecorder();
byte b = 0;
int len = 0;
int colonIndex = \-1;
int returnCode = 0;
if (null == inp)
if (recorder \!= null)
inp = new BufferedInputStream(recorder.getInputStream().set(
sockHolder.getSocket().getInputStream()));
else
inp = new BufferedInputStream(sockHolder.getSocket()
.getInputStream());
if (headers == null)
headers = new Hashtable();
boolean readTooMuch = false;
ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);
do {
if (\!readTooMuch)
b = (byte) inp.read();
if (b == \-1)
break;
readTooMuch = false;
if (b \!= 13 && b \!= 10) {
if (b == 58 && colonIndex == \-1)
colonIndex = len;
len++;
buf.write(b);
continue;
}
if (b == 13)
continue;
if (len == 0)
break;
b = (byte) inp.read();
readTooMuch = true;
if (b \!= 32 && b \!= 9) {
buf.close();
byte hdata\[\] = buf.toByteArray();
buf.reset();
String name;
String value;
if (colonIndex \!= \-1) {
name = new String(hdata, 0, colonIndex, "iso-8859-1");
value = new String(hdata, colonIndex + 1, len - 1
\\- colonIndex, "iso-8859-1");
colonIndex = \-1;
} else {
name = new String(hdata, 0, len, "iso-8859-1");
value = "";
}
if (log.isDebugEnabled())
log.debug((new StringBuilder()).append(name).append(value)
.toString());
if (msgContext.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE) == null) {
int start = name.indexOf(' ') + 1;
String tmp = name.substring(start).trim();
int end = tmp.indexOf(' ');
if (end \!= \-1)
tmp = tmp.substring(0, end);
returnCode = Integer.parseInt(tmp);
msgContext.setProperty(HTTPConstants.MC_HTTP_STATUS_CODE,
new Integer(returnCode));
msgContext.setProperty(
HTTPConstants.MC_HTTP_STATUS_MESSAGE, name
.substring(start + end + 1));
} else if (msgContext.getMaintainSession()) {
String nameLowerCase = name.toLowerCase();
if (nameLowerCase.equalsIgnoreCase("Set-Cookie"))
handleCookie("Cookie", null, value, msgContext);
else if (nameLowerCase.equalsIgnoreCase("Set-Cookie2"))
handleCookie("Cookie2", null, value, msgContext);
else
headers.put(name.toLowerCase(), value);
} else {
headers.put(name.toLowerCase(), value);
}
len = 0;
}
} while (true);
return inp;
}

private InputStream readFromSocket(SocketHolder socketHolder,
MessageContext msgContext, InputStream inp, Hashtable headers)
throws IOException {
String err = new String();
Message outMsg = null;
Integer rc = (Integer) msgContext
.getProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
int returnCode = 0;
if (rc \!= null)
returnCode = rc.intValue();

String contentType = (String) headers.get(HEADER_CONTENT_TYPE_LC);
contentType = null \!= contentType ? contentType.trim() : null;
String location = (String) headers.get(HEADER_LOCATION_LC);
location = null \!= location ? location.trim() : null;

log.info(mySIG + "HTTP Return code: " + returnCode
\\+ " - Content-type: " + contentType);

if (returnCode > 199 && returnCode < 300) {
// 202: Accepted
if (returnCode == 202)
return inp;
} else if (msgContext.getSOAPConstants() \!= SOAPConstants.SOAP12_CONSTANTS
&& (contentType == null \|\| contentType.startsWith("text/html")
\|\| returnCode <= 499 \|\| returnCode >= 600)) {
// 302: Found
// 307: Temporary Redirect
if (location \!= null && (returnCode == 302 \|\| returnCode == 307)) {
inp.close();
socketHolder.getSocket().close();
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
msgContext.setProperty("transport.url", location);
invoke(msgContext);
return inp;
}
if (returnCode == 100) {
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_CODE);
msgContext.removeProperty(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
readHeadersFromSocket(socketHolder, msgContext, inp, headers);
return readFromSocket(socketHolder, msgContext, inp, headers);
}

ByteArrayOutputStream buf = new ByteArrayOutputStream(4097);
byte b;
while (-1 \!= (b = (byte) inp.read()))
buf.write(b);
String statusMessage = msgContext
.getStrProp(HTTPConstants.MC_HTTP_STATUS_MESSAGE);
AxisFault fault = new AxisFault("HTTP", (new StringBuilder())
.append("(").append(returnCode).append(")").append(
statusMessage).toString(), null, null);
fault.setFaultDetailString(Messages.getMessage("return01",
(new StringBuilder()).append("").append(returnCode)
.toString(), buf.toString()));
fault.addFaultDetail(Constants.QNAME_FAULTDETAIL_HTTPERRORCODE,
Integer.toString(returnCode));
throw fault;
}
// AG: bypassiamo il throw exception e facciamo hijacking
else if (returnCode == 500) {
log.debug(mySIG + "Hijacking = true");
hijacking = true;
}

String contentLocation = (String) headers
.get(HEADER_CONTENT_LOCATION_LC);
contentLocation = null \!= contentLocation ? contentLocation.trim()
: null;
String contentLength = (String) headers.get(HEADER_CONTENT_LENGTH_LC);
contentLength = null \!= contentLength ? contentLength.trim() : null;
String transferEncoding = (String) headers
.get(HEADER_TRANSFER_ENCODING_LC);
if (null \!= transferEncoding) {
transferEncoding = transferEncoding.trim().toLowerCase();
if (transferEncoding
.equals(HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED))
inp = new ChunkedInputStream(inp);
}

// \****************************************************************\\*
// SOAP Fault Hijacking
// \****************************************************************\\*
String qos = null;
if (hijacking) {
try {

ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos = hijackSoapFault(socketHolder, msgContext, inp);
outMsg = new Message(baos.toByteArray(), false, contentType,
contentLocation);

// Handling of Synch/Asynch message: in case of Asynch message
// (either ExactlyOnce or
// ExactlyOnceInOrder) the handler raises an exception with the
// fault string, so that the
// message is in error state in RWB and the message audit log
// shows it.
SOAPHeaderElement she = msgContext.getRequestMessage()
.getSOAPEnvelope().getHeaderByName(SAPNS,
"ReliableMessaging");
// If the SOAPHeaderElement can't be found, most likely the
// "Keep XI Headers" flag was not set,
// and we pretend the QoS to be BestEffort (completely arbitrary
// but driven by common sense)
if (she \!= null)
qos = she.getElementsByTagNameNS(SAPNS, "QualityOfService")
.item(0).getFirstChild().getNodeValue();
else
qos = "BestEffort";
} catch (Exception e) {
handleError("Error in main hijacking process", e);
}

if (\!qos.equalsIgnoreCase("BestEffort")) {
throw new AxisFault("Application Error raised by Axis Handler "
\\+ this.getClass().getName()
\\+ " - Error returned by web service provider is: "
\\+ faultString);
}

// outmsg is built "normally" here (no hijacking takes place)
} else {
outMsg = new Message(new SocketInputStream(inp, socketHolder
.getSocket()), false, contentType, contentLocation);
}

MimeHeaders mimeHeaders = outMsg.getMimeHeaders();
String key;
for (Enumeration e = headers.keys(); e.hasMoreElements(); mimeHeaders
.addHeader(key, ((String) headers.get(key)).trim()))
key = (String) e.nextElement();

outMsg.setMessageType("response");
msgContext.setResponseMessage(outMsg);
if (log.isDebugEnabled()) {
if (null == contentLength)
log.debug((new StringBuilder()).append("\n").append(
Messages.getMessage("no00", "Content-Length"))
.toString());
log.debug((new StringBuilder()).append("\n").append(
Messages.getMessage("xmlRecd00")).toString());
log.debug("-----------------------------------------------");
log.debug(outMsg.getSOAPEnvelope().toString());
}
return inp;
}

private ByteArrayOutputStream hijackSoapFault(SocketHolder socketHolder,
MessageContext msgContext, InputStream inp) throws AxisFault {
log.debug(mySIG + "Hijacking - BEGIN");

Document d = null;
try {
SocketInputStream sis = new SocketInputStream(inp, socketHolder
.getSocket());
DOMParser dp = new DOMParser();
log.debug(mySIG + "DOM Parser class: " + dp.getClass().getName());
d = dp.parse(sis);
log.debug(mySIG + "Document class: " + d.getClass().getName());
} catch (Exception e) {
handleError("Couldn't get SOAP Envelope as Document - ", e);
}

// Get SOAP Fault code
Element el = null;
String faultCode = null;
try {
el = (Element) d.getElementsByTagName("faultcode").item(0);
faultCode = el.getFirstChild().getNodeValue();
log.debug(mySIG + "faultcode: " + faultCode);
} catch (Exception e) {
handleError("Couldn't get SOAP faultcode text content", e);
}

// Get SOAP Fault string
el = null;
try {
el = (Element) d.getElementsByTagName("faultstring").item(0);
faultString = el.getFirstChild().getNodeValue();
log.debug(mySIG + "faultstring: " + faultString);
} catch (Exception e) {
handleError("Couldn't get SOAP faultstring text content", e);
}

// Get rid of SOAP Fault from SOAP Body
Element body = null;
try {
body = (Element) d.getElementsByTagNameNS(
"\[http://schemas.xmlsoap.org/soap/envelope/\|http://schemas.xmlsoap.org/soap/envelope/\]", "Body")
.item(0);
body.removeChild(body.getFirstChild());
} catch (Exception e) {
handleError("Couldn't get rid of SOAP Fault from Document", e);
}

// Retrieve fist child of original SOAP Request body
// As a matter of fact, the SystemABC web service provider always responds
// with the a message
// built as <RequestMessage> with "Output" in place of "Input"
// e.g. for the Partner_Binding wsdl,
// INPUT ===> XYZ_Client_Client_In_Input
// OUTPUT ==> XYZ_Client_Client_In_Output

String reqNodeName = null;
String reqNodeNS = null;
try {
Node reqNode = msgContext.getRequestMessage().getSOAPBody()
.getFirstChild();
reqNodeName = reqNode.getLocalName();
reqNodeNS = reqNode.getNamespaceURI();
} catch (Exception e) {
handleError(
"Couldn't get fist child of original SOAP Request body", e);
}
log.debug("Input message node name, got: " + reqNodeName);
String rspNodename = reqNodeName.replaceAll("Input", "Output");

// Building the SOAP response node by adding the two common elements
// ALWAYS forseen by SystemABC:
// Error_Code and Error_Message
try {
Node rsp = body.appendChild(((Document) d).createElementNS(
reqNodeNS, rspNodename));
// rsp.appendChild(d.createElementNS(reqNodeNS,"Error_Code")).appendChild(d.createTextNode(faultCode));
rsp.appendChild(d.createElementNS(reqNodeNS, "Error_Code"))
.appendChild(d.createTextNode("KO"));
rsp.appendChild(d.createElementNS(reqNodeNS, "Error_Message"))
.appendChild(d.createTextNode(faultString));
} catch (Exception e) {
handleError(
"Couldn't build the SOAP response node (Error_Code and Error_Message)",
e);
}

ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
DOMSerializer dser = new DOMSerializer();
dser.setOutputProperty("indent", "no");
dser.write(d, out);
} catch (Exception e) {
handleError("Error when serializing DOM to String", e);
}

log.debug(mySIG + "Hijacking - END");

return out;
}

public void handleCookie(String cookieName, String setCookieName,
String cookie, MessageContext msgContext) {
cookie = cleanupCookie(cookie);
int keyIndex = cookie.indexOf("=");
String key = keyIndex == \-1 ? cookie : cookie.substring(0, keyIndex);
ArrayList cookies = new ArrayList();
Object oldCookies = msgContext.getProperty(cookieName);
boolean alreadyExist = false;
if (oldCookies \!= null)
if (oldCookies instanceof String\[\]) {
String oldCookiesArray\[\] = (String\[\]) (String\[\]) oldCookies;
for (int i = 0; i < oldCookiesArray.length; i++) {
String anOldCookie = oldCookiesArray\[i\];
if (key \!= null && anOldCookie.indexOf(key) == 0) {
anOldCookie = cookie;
alreadyExist = true;
}
cookies.add(anOldCookie);
}

} else {
String oldCookie = (String) oldCookies;
if (key \!= null && oldCookie.indexOf(key) == 0) {
oldCookie = cookie;
alreadyExist = true;
}
cookies.add(oldCookie);
}
if (\!alreadyExist)
cookies.add(cookie);
if (cookies.size() == 1)
msgContext.setProperty(cookieName, cookies.get(0));
else if (cookies.size() > 1)
msgContext.setProperty(cookieName, ((Object) (cookies
.toArray(new String\[cookies.size()\]))));
}

private String cleanupCookie(String cookie) {
cookie = cookie.trim();
int index = cookie.indexOf(';');
if (index \!= \-1)
cookie = cookie.substring(0, index);
return cookie;
}

private void handleError(String s, Throwable t) throws AxisFault {
String err = s + " - due to:" + t + "\n" + getStackTrace(t);
log.error(err);
throw new AxisFault(err, t);
}

public static String getStackTrace(Throwable t) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
t.printStackTrace(pw);
pw.flush();
sw.flush();
return sw.toString();
}

private static final String SAPNS = "\[http://sap.com/xi/XI/Message/30\|http://sap.com/xi/XI/Message/30\]";

private String faultString = null;

protected static Log log = LogFactory.getLog(TolerantHttpSender.class
.getName());
private static final String ACCEPT_HEADERS = (new StringBuilder())
.append(
"Accept: application/soap+xml, application/dime, multipart/related, text/*\r\nUser-Agent: ")
.append(Messages.getMessage("axisUserAgent")).append("\r\n")
.toString();
private static final String CACHE_HEADERS = "Cache-Control: no-cache\r\nPragma: no-cache\r\n";
private static final String CHUNKED_HEADER;
private static final String HEADER_CONTENT_TYPE_LC = "Content-Type"
.toLowerCase();
private static final String HEADER_LOCATION_LC = "Location".toLowerCase();
private static final String HEADER_CONTENT_LOCATION_LC = "Content-Location"
.toLowerCase();
private static final String HEADER_CONTENT_LENGTH_LC = "Content-Length"
.toLowerCase();
private static final String HEADER_TRANSFER_ENCODING_LC;
URL targetURL;

private boolean hijacking = false;
private final String mySIG = "AXIS - ";

static {
// register the class handler to ClassUtils
// ClassUtils.setClassLoader(TolerantHttpSender_Working_v2.class.getName(),
// TolerantHttpSender_Working_v2.class.getClassLoader());

CHUNKED_HEADER = (new StringBuilder()).append(
HTTPConstants.HEADER_TRANSFER_ENCODING).append(": ").append(
HTTPConstants.HEADER_TRANSFER_ENCODING_CHUNKED).append("\r\n")
.toString();
HEADER_TRANSFER_ENCODING_LC = HTTPConstants.HEADER_TRANSFER_ENCODING
.toLowerCase();
}

}

Author: Anupam Chakraborty
Submitted: 21st December 2008

This is a small Tutorial for writing better ABAP Mapping Code for XI.

You can use this piece of code to split a file based on certain field. The input file is placed as below:

This is my first blog and I thought of giving a class which has some more detail.
This class will read the input xml which contains 5 fields.
i.e. GID, FNAME, LNAME, GENDER, DEPT.
and will give a output file splitted using the DEPT.

<?xml version="1.0" encoding="UTF-8" ?>
<ns0:MT_APC_Emp_Out xmlns:ns0="http://www.sap-press.com/xi/training/00">
<EMPLOYEE>
    <GID>101</GID>
    <FNAME>Anupam</FNAME>
    <LNAME>Chakraborty</LNAME>
    <GENDER>M</GENDER>
    <DEPT>SAP</DEPT>
</EMPLOYEE>
<EMPLOYEE>
    <GID>102</GID>
    <FNAME>Arindom</FNAME>
    <LNAME>Chakraborty</LNAME>
    <GENDER>M</GENDER>
    <DEPT>Microsoft</DEPT>
</EMPLOYEE>
<EMPLOYEE>
    <GID>103</GID>
    <FNAME>Paromita</FNAME>
    <LNAME>Chakraborty</LNAME>
    <GENDER>F</GENDER>
    <DEPT>JAVA</DEPT>
</EMPLOYEE>
<EMPLOYEE>
    <GID>104</GID>
    <FNAME>Jilan</FNAME>
    <LNAME>Bhasha</LNAME>
    <GENDER>M</GENDER>
    <DEPT>SAP</DEPT>
</EMPLOYEE>
<EMPLOYEE>
    <GID>105</GID>
    <FNAME>Ashoke</FNAME>
    <LNAME>Chakraborty</LNAME>
    <GENDER>M</GENDER>
    <DEPT>SAP</DEPT>
</EMPLOYEE>
<EMPLOYEE>
    <GID>106</GID>
    <FNAME>Sudipta</FNAME>
    <LNAME>Chakraborty</LNAME>
    <GENDER>F</GENDER>
    <DEPT>Microsoft</DEPT>
</EMPLOYEE>
</ns0:MT_APC_Emp_Out>

Here goes the ABAP CLASS code:

I am sure that there are many other blogs from where you can find the details of how to proceed:
As of now I am writing only the ABAP Code 

if_mapping~execute.
**********************************************************************
* Class name           : ZCL_APC_TEST1                               *
* Class method         : IF_MAPPING~EXECUTE                          *
* Method Title         : Test Scenario                               *
* AUTHOR               : Anupam Chakraborty                          *
**********************************************************************
* DESCRIPTION          : Test Program                                *
**********************************************************************
  DATA:
     dt_node_collection            TYPE REF TO if_ixml_node_collection,
     dt_node_length                TYPE i,
     dt_node_iterator              TYPE REF TO if_ixml_node_iterator,
     dt_node_list_iterator         TYPE REF TO if_ixml_node_iterator,

     dt_subnode                    TYPE REF TO if_ixml_node,
     dt_subnode_list               TYPE REF TO if_ixml_node_list,
     dt_subnode_list_length        TYPE i.

  DATA:
         w_childnode                   TYPE REF TO if_ixml_node,
         w_childnode_name              TYPE string,
         w_childnode_value             TYPE string,

         w_fieldname                   TYPE string,

         w_index                       TYPE i,
         ostring                       TYPE string.

  DATA:
          lif_msg_node                    TYPE REF TO if_ixml_element,
          lif_ns_namespace                TYPE REF TO if_ixml_namespace_decl,
          lif_emp_node                    TYPE REF TO if_ixml_node,
          lif_dept_node                   TYPE REF TO if_ixml_node,
          lif_det_node                    TYPE REF TO if_ixml_node.

  TYPES:
        BEGIN OF ty_employee,
          dept        TYPE string,
          gid         TYPE string,
          fname       TYPE string,
          lname       TYPE string,
          gender      TYPE string,
        END OF ty_employee,
        t_ty_employee   TYPE STANDARD TABLE OF ty_employee.
  DATA:
             i_employee       TYPE t_ty_employee,
             wa_employee      TYPE ty_employee.

  FIELD-SYMBOLS:
            <fs_any> TYPE ANY,
            <fs_emp> TYPE ty_employee.
* Initialize iXML Library
  TYPE-POOLS: ixml.
  CLASS cl_ixml DEFINITION LOAD.

* create main factory
  DATA:lif_ixmlfactory TYPE REF TO if_ixml.
  lif_ixmlfactory = cl_ixml=>create( ).

* create stream factory
  DATA:lif_streamfactory TYPE REF TO if_ixml_stream_factory.
  lif_streamfactory = lif_ixmlfactory->create_stream_factory( ).

* create input stream
  DATA:lif_istream TYPE REF TO if_ixml_istream.
  lif_istream = lif_streamfactory->create_istream_xstring( source ).

* initialize input document
  DATA:lif_idocument TYPE REF TO if_ixml_document.
  lif_idocument = lif_ixmlfactory->create_document( ).

* parse input document
  DATA:lif_iparser TYPE REF TO if_ixml_parser.                    " Parser input
  lif_iparser = lif_ixmlfactory->create_parser(
                                              stream_factory = lif_streamfactory
                                              istream   = lif_istream
                                              document  = lif_idocument
                                              ).
  lif_iparser->parse( ).
* Get the collection of the parent node
  dt_node_collection = lif_idocument->get_elements_by_tag_name( name = 'EMPLOYEE' ).
* Get the size of the parent node
  dt_node_length = dt_node_collection->get_length( ).
* Create the node iterator to traverse the node
  dt_node_iterator = dt_node_collection->create_iterator( ).
* Loop through the parent node now....
  DO dt_node_length TIMES.
*Loop thorugh each child node and get the name of the structure node
    dt_subnode = dt_node_iterator->get_next( ).
*Create a NODE LIST instance to traverse through the child nodes under this node
    dt_subnode_list = dt_subnode->get_children( ).
*Now get the number of nodes in the above NODE LIST structure
    dt_subnode_list_length = dt_subnode_list->get_length( ).
* Loop through the child nodes from where we need to fetch the values
    DO dt_subnode_list_length TIMES.
*Keep the number of index
      w_index = sy-index - 1.
*Get the node object
      w_childnode = dt_subnode_list->get_item( w_index ).
*Get the Name of the node
      w_childnode_name  =  w_childnode->get_name( ).
*Get the Value of the node
      w_childnode_value  = w_childnode->get_value( ).
*Create the name of the place you want to add the value to
      CONCATENATE 'wa_employee-' w_childnode_name INTO w_fieldname.
*Assign the same to a field Symbol. the field symbol point to your required place.
      ASSIGN (w_fieldname) TO <fs_any>.
*Check for SY-SUBRC and then move the value to the Work Area.
      IF sy-subrc EQ 0.
        MOVE w_childnode_value TO <fs_any>.
      ENDIF.
    ENDDO.
*Create the name of the Complete Work Area that we have to append
    APPEND wa_employee TO i_employee.
* Clear the work area
    CLEAR wa_employee.
  ENDDO.
* Sort the internal table on department so that it can be now used to create the output.
  SORT i_employee BY dept ASCENDING.

  DATA:
  lif_odocument        TYPE REF TO if_ixml_document.         " OutputDocument
  lif_odocument = lif_ixmlfactory->create_document( ).

* Create the Message type for the output message.
  CALL METHOD lif_odocument->create_simple_element_ns
    EXPORTING
      name   = 'MT_APC_Emp_Inb'
      prefix = 'ns'
      parent = lif_odocument
    RECEIVING
      rval   = lif_msg_node.
* Create the uri for the header message.
  CALL METHOD lif_odocument->create_namespace_decl
    EXPORTING
      name   = 'ns'
      prefix = 'xmlns'
      uri    = '_http://www.sap-press.com/xi/training/00'
    RECEIVING
      rval   = lif_ns_namespace.
* pass namepsace attribute
  lif_msg_node->set_attribute_node_ns( new_attr = lif_ns_namespace ).
* Loop at the Internal Table to create the external element.
  LOOP AT i_employee INTO wa_employee.
    AT NEW dept.
      CALL METHOD lif_odocument->create_simple_element_ns
        EXPORTING
          name   = 'DEPARTMENT'
          parent = lif_msg_node
          value  = wa_employee-dept
        RECEIVING
          rval   = lif_dept_node.
    ENDAT.
    CALL METHOD lif_odocument->create_simple_element_ns
    EXPORTING
      name   = 'EMPLOYEES'
      parent = lif_dept_node
    RECEIVING
      rval   = lif_emp_node.
    CONCATENATE wa_employee-fname wa_employee-lname INTO ostring SEPARATED BY SPACE.
    CALL METHOD lif_odocument->create_simple_element_ns
      EXPORTING
        name   = 'NAME'
        parent = lif_emp_node
        value  = ostring
      RECEIVING
        rval   = lif_det_node.

    IF wa_employee-gender = 'M'.
      ostring = 'Male'.
    ELSE.
      ostring = 'Female'.
    ENDIF.
    CALL METHOD lif_odocument->create_simple_element_ns
      EXPORTING
        name   = 'GENDER'
        parent = lif_emp_node
        value  = ostring
      RECEIVING
        rval   = lif_det_node.
  ENDLOOP.
* Create the Output Stream Factory
  DATA: lif_ostream TYPE REF TO if_ixml_ostream.
  lif_ostream = lif_streamfactory->create_ostream_xstring( result ).
* Create the Renderer Object.
  DATA lif_renderer TYPE REF TO if_ixml_renderer.
  lif_renderer = lif_ixmlfactory->create_renderer( ostream = lif_ostream
                                            document = lif_odocument
                                            ).
* Implement the renderer
  lif_renderer->render( ).
ENDMETHOD. 

 And then the output goes here...

<?xml version="1.0" encoding="UTF-8"?>
<ns:MT_APC_Emp_Inb xmlns:ns="_http://www.sap-press.com/xi/training/00">
   <DEPARTMENT>
      JAVA
      <EMPLOYEES>
         <NAME>Paromita Chakraborty</NAME>
         <GENDER>Female</GENDER>
      </EMPLOYEES>
   </DEPARTMENT>
   <DEPARTMENT>
      Microsoft
      <EMPLOYEES>
         <NAME>Arindom Chakraborty</NAME>
         <GENDER>Male</GENDER>
      </EMPLOYEES>
      <EMPLOYEES>
         <NAME>Sudipta Chakraborty</NAME>
         <GENDER>Female</GENDER>
      </EMPLOYEES>
   </DEPARTMENT>
   <DEPARTMENT>
      SAP
      <EMPLOYEES>
         <NAME>Jilan Bhasha</NAME>
         <GENDER>Male</GENDER>
      </EMPLOYEES>
      <EMPLOYEES>
         <NAME>Anupam Chakraborty</NAME>
         <GENDER>Male</GENDER>
      </EMPLOYEES>
      <EMPLOYEES>
         <NAME>Ashoke Chakraborty</NAME>
         <GENDER>Male</GENDER>
      </EMPLOYEES>
   </DEPARTMENT>
</ns:MT_APC_Emp_Inb>
 

Below is the code to write UDF for ZeroPaddinginLeft

public String ZeroPaddinginLeft(String a,String b,Container container)
{   
   String result = a;
    int LengthString = a.length();
    int len = Integer.parseInt(b);
    for(int i=LengthString; i< len; i++)
   {
     result = "0" +  result; 
   }
  return result;
}

Author: name as link to Business Card
Submitted: <date>
Related Links:

  • <link>

Description : Userdefined function in sap xi to check the file name.

Below is the code

public String ChkFilename(String a,String b,Container container){

if(a.equals("01") &&(b.equals("A2")\|\|b.equals("A4")\|\|b.equals("41")\|\|b.equals("A3")\|\|b.equals("11")\|\|b.equals("49")))

return "T001Y560.001";

else if (a.equals("01")&&(b.equals("02")\|\|b.equals("12")\|\|b.equals("32")\|\|b.equals("36")\|\|b.equals("51")\|\|b.equals("13")\|\|b.equals("09")\|\|b.equals("22")\|\|b.equals("34")\|\|b.equals("42")\|\|b.equals("82")\|\|b.equals("06")))

return "T001Y561.001";

else

return "T001Y560.001";  
}

Author: name as link to Business Card
Submitted: <date>
Related Links:

  • <link>

Description : Userdefined function in XI to get the index value.

Below is the code.

public void getIndexVal(String[] a,String[] b,String[] c,ResultList result,Container container)
{
int temp = Integer.parseInt(c[0]);
int cnt = 0;
String[] arrErrFlag = new String[100];
for(int i =0;i<a.length;i++)
{
for(int j=0;j<b.length;j++)
{if(i==j)
if(b[j].equals("03"))
arrErrFlag[cnt] = a[i];
cnt++;
}
}
}
if (arrErrFlag[temp] != null)
result.addValue(arrErrFlag[temp]);
else
result.addValue("");
}

Summary

This post describes a user-defined mapping function for SAP XI that performs an RFC lookup using the SAP Mapping Lookup library in a scenario involving purchase orders.

This code builds on previously posted code examples on SDN, including an article by Danny De Roovere (http://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/70d90a91-3cf4-2a10-d189-bfd37d9c3231).

The code presented here relates specifically to a purchase order scenario involving the BAPI_PO_GETITEMS function module. The purpose of the lookup is to retrieve the value of an attribute of a specific order item (e.g., PRICE_UNIT), given the ID of the order (PURCHASEORDER) and the ID of the order item (PO_ITEM).

Besides serving as a reference for using the a RFC lookup using the SAP Mapping Lookup library, this example also provides some insights into how to parse the retrieved XML document for the desired information.

Function Signature

Inputs:             id of document containing list (e.g., PO Number), list item id value (PO item number)

Output:            value of list item attribute (e.g., PRICE_UNIT)

Implementation

Below are the key steps for implementing this lookup function in a mapping

  1. Create the mapping
  2. Create new user-defined function (UDF) in mapping
  3. Provide input parameter information for the UDF
  4. Provide the libraries used in the code
  5. Paste the code
  6. Adjust the code so it runs in your environment and serves your purpose. This includes at least providing changing the SERVICE and CHANNEL_NAME. In addition a different result attribute (in our case PRICE_UNIT) or even an entirely different FUNCTION_MODULE may be specified. The latter may require further adjustments to the rfcXML string!
  7. Test the mapping

Code 


/******************************
*  Purpose: RFC Lookup of document containing list (e.g., Purchase Order), returning value of list item with matching item id
*  Inputs: 1 - id document containing list (e.g., PO Number), 2 - list item id value (PO item number)
*  Output: value of list item (e.g., PRICE_UNIT)
*
*  Authors: Marc Haines, Innograte LLC & Kyle Fortney
*  created September, 2008
*  adapted from How to Lookup Data Via a RFC User Defined Function? - Thanks Danny De Roovere !
*  see https://www.sdn.sap.com/irj/sdn/go/portal/prtroot/docs/library/uuid/70d90a91-3cf4-2a10-d189-bfd37d9c3231
*******************************/

/* Define the following input parameters
   PO_Number (String)
   Item_Number (String)
*/

/* Provide the following imports:
   com.sap.aii.mapping.lookup.*;java.util.Iterator;java.util.Map;java.io.*;javax.xml.parsers.*;org.w3c.dom.*;
*/

// Enable tracing
AbstractTrace trace = container.getTrace();

// Set default values
final String SERVICE = "MY_SAP_SYSTEM", // Name of service defined in XI configuration
CHANNEL_NAME = "cc_rfc_receiver", // Name of communication channel defined for service
SAP_RFC_NAMESPACE = "urn:sap-com:document:sap:rfc:functions", // Namespace for SAP RFC definitions
FUNCTION_MODULE = "BAPI_PO_GETITEMS", // Name of the function module called
LIST_CONTENT_TAG = "PO_ITEMS", // Element that conatains the list items (e.g., PO_ITEMS contains multiple item elements)
LIST_ITEM_ID_TAG = "PO_ITEM", // Element of individual list item that contains the id of the item
LIST_VALUE_TAG = "PRICE_UNIT", // Element of the individual list item that conatains the value desired for output
VALUE_NOT_FOUND = ""; // Default return value in case something goes wrong

// Create document builder to create DOM XML document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
factory.setNamespaceAware(false);
factory.setValidating(false);

try {
        // Create XML document using document builder
        builder = factory.newDocumentBuilder();
} catch (Exception e) {
        trace.addWarning("Error creating DocumentBuilder - " +
                e.getMessage());
        return null;
}


// Define XML for RFC Request
String rfcXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><ns0:" +
        FUNCTION_MODULE + " xmlns:ns0=\"" + SAP_RFC_NAMESPACE +
        "\"><ACCTASSCAT/><CREATED_BY/><DELETED_ITEMS/><DOC_DATE/><DOC_TYPE/><ITEMS_OPEN_FOR_RECEIPT/><ITEM_CAT/><MATERIAL/><MATERIAL_EVG><MATERIAL_EXT/><MATERIAL_VERS/><MATERIAL_GUID/></MATERIAL_EVG><MAT_GRP/><PLANT/><PREQ_NAME/><PURCHASEORDER>" +
        PO_Number + "</PURCHASEORDER><PURCH_ORG/><PUR_GROUP/><PUR_MAT/><PUR_MAT_EVG><MATERIAL_EXT/><MATERIAL_VERS/><MATERIAL_GUID/></PUR_MAT_EVG><SHORT_TEXT/><SUPPL_PLANT/><TRACKINGNO/><VENDOR/><WITH_PO_HEADERS/><PO_HEADERS><item><PO_NUMBER/><CO_CODE/><DOC_CAT/><DOC_TYPE/><CNTRL_IND/><DELETE_IND/><STATUS/><CREATED_ON/><CREATED_BY/><ITEM_INTVL/><LAST_ITEM/><VENDOR/><LANGUAGE/><PMNTTRMS/><DSCNT1_TO/><DSCNT2_TO/><DSCNT3_TO/><CASH_DISC1/><CASH_DISC2/><PURCH_ORG/><PUR_GROUP/><CURRENCY/><EXCH_RATE/><EX_RATE_FX/><DOC_DATE/><VPER_START/><VPER_END/><APPLIC_BY/><QUOT_DEAD/><BINDG_PER/><WARRANTY/><BIDINV_NO/><QUOTATION/><QUOT_DATE/><REF_1/><SALES_PERS/><TELEPHONE/><SUPPL_VEND/><CUSTOMER/><AGREEMENT/><REJ_REASON/><COMPL_DLV/><GR_MESSAGE/><SUPPL_PLNT/><RCVG_VEND/><INCOTERMS1/><INCOTERMS2/><TARGET_VAL/><COLL_NO/><DOC_COND/><PROCEDURE/><UPDATE_GRP/><DIFF_INV/><EXPORT_NO/><OUR_REF/><LOGSYSTEM/><SUBITEMINT/><MAST_COND/><REL_GROUP/><REL_STRAT/><REL_IND/><REL_STATUS/><SUBJ_TO_R/><TAXR_CNTRY/><SCHED_IND/><VEND_NAME/><CURRENCY_ISO/><EXCH_RATE_CM/><HOLD/></item></PO_HEADERS><PO_ITEMS><item><PO_NUMBER/><PO_ITEM/><ADDRESS/><MATERIAL/><PUR_MAT/><INFO_REC/><ITEM_CAT/><ACCTASSCAT/><AGREEMENT/><AGMT_ITEM/><STORE_LOC/><MAT_GRP/><SHORT_TEXT/><DISTRIB/><PART_INV/><KANBAN_IND/><PLANT/><ALLOC_TBL/><AT_ITEM/><UNIT/><NET_PRICE/><PRICE_UNIT/><CONV_NUM1/><CONV_DEN1/><ORDERPR_UN/><PCKG_NO/><PROMOTION/><ACKN_REQD/><TRACKINGNO/><PLAN_DEL/><RET_ITEM/><AT_RELEV/><VEND_MAT/><MANUF_PROF/><MANU_MAT/><MFR_NO/><MFR_NO_EXT/><PO_PRICE/><SHIPPING/><ITEM_CAT_EXT/><PO_UNIT_ISO/><ORDERPR_UN_ISO/><PREQ_NAME/><DISP_QUAN/><QUAL_INSP/><NO_MORE_GR/><DELETE_IND/><NO_ROUNDING/><TAX_CODE/><MATERIAL_EXTERNAL/><MATERIAL_GUID/><MATERIAL_VERSION/><PUR_MAT_EXTERNAL/><PUR_MAT_GUID/><PUR_MAT_VERSION/><VAL_TYPE/><PR_CLOSED/><ACKNOWL_NO/></item></PO_ITEMS><RETURN><item><TYPE/><CODE/><MESSAGE/><LOG_NO/><LOG_MSG_NO/><MESSAGE_V1/><MESSAGE_V2/><MESSAGE_V3/><MESSAGE_V4/></item></RETURN></ns0:" +
        FUNCTION_MODULE + ">";

// Prepare and perform RFC Lookup ...
RfcAccessor accessor;
Payload result;


try {
        //  Determine a communication channel (Business system + Communication channel)
        Channel channel = LookupService.getChannel(SERVICE, CHANNEL_NAME);

        //  Get a RFC accessor for the channel.
        accessor = LookupService.getRfcAccessor(channel);

        //  Create an XML input stream that represents the RFC request message.
        InputStream is = new ByteArrayInputStream(rfcXML.getBytes());

        //  Create the XML Payload
        XmlPayload payload = LookupService.getXmlPayload(is);

        //  Execute the lookup.
        result = accessor.call(payload);

        if (result == null) {
                trace.addWarning("result of RFC call is null");
        }

} catch (LookupException e) {
        trace.addWarning("Error during lookup - " + e);
}

// Parsing RFC Response Document
Document docResponse = null;
InputStream in = result.getContent();
String returnValue = VALUE_NOT_FOUND;
NodeList poItems = null;

try {
        docResponse = builder.parse(in);
        if (docResponse == null) {
                trace.addWarning("docResponse is null");
        }
        // Get the list of PO items from RFC structure (item nodes, child nodes of PO_ITEMS)
        // Important: getElementsByTagName returns a *node list*.
        //            So the first - even if there is only one - item needs to be picked - item(0)!
        //            Only when having the PO_ITEMS *node* the getChildNodes() function can be used to get the PO items.
        poItems = docResponse.getElementsByTagName(
                LIST_CONTENT_TAG).item(0).getChildNodes();

        // Iterate over PO items (item nodes in RFC structure) until item with right item number is found
        for (int i = 0; i < poItems.getLength(); i++) {
                Element e = (Element) poItems.item(i);
                // Get the PO_ITEM value for the current item
                String poItem =
                        e.getElementsByTagName(LIST_ITEM_ID_TAG).item(0).getFirstChild().getNodeValue();

                // Test if value of PO_ITEM from current node matches input parameter Item_Number
                if (poItem.equals(Item_Number)) {
                        // Assign text value PRICE_UNITof desired tag to result
                        returnValue = e.getElementsByTagName(LIST_VALUE_TAG).item(
                                0).getFirstChild().getNodeValue();
                }
        }
}
catch (Exception e) {
        trace.addWarning("Error when parsing RFC Response - " + e.getMessage());
}

try {

        // Free resources, close the accessor..
        if (accessor != null) {
                try {
                        accessor.close();
                } catch (LookupException e) {
                        trace.addWarning( "Error while closing accessor " + e.getMessage());
                }
        }
} catch (Exception e) {
        trace.addWarning("Result value not found in DOM - " + e);
}

// return the result obtained above
return returnValue;







Author: name as link to Business Card
Submitted: 05/01/2009
Related Links:

Description

Use Adapter Specific Message Attributes for the target Communication Channel(CC).Check the indicator for filename in the advanced tab of CC

Create a UDF with input as file name and copy/paste this code

/* Using Dynamic Configuration */
DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
//conf.removeAll();
DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/File","FileName");
//String filename= conf.get(key);
conf.put(key, fileName);
key= null;


return fileName;

In the above example the UDF has value as cache.The output of this UDF is assigned to the root of the xml document.

Author: Zahid Murtaza
Submitted: <26-Jun-2008>
Related Links:

Hello All..

Followin code will allow to write the payload data to an FTP location.

Please follow the guidlines for adapter module creation, as in link above. This snippet only discusses the class method "Process" in adapter module.

The following class work as follow:
It reads the payload.
Lets assume that we are expecting an XML in payload with three tags "Order" "Authocode" and "Status".
It simply checks the existence of these strings-- no xml parsing related stuff.
If any one of these is missing, write the file to FTP Location.
The code also describes how to use module paramters.
you would require the library sun.net.ftp.FtpClient to implement FTP related operations

package
 changeLoad;
/**

* @author Zahid

*

* To change the template for this generated type comment go to

* Window&gt;Preferences&gt;Java&gt;Code Generation&gt;Code and Comments

*/
import
 java.io.*;
import
 sun.net.ftp.FtpClient;
import
 java.util.Hashtable;
import
 javax.ejb.CreateException;
import
 javax.ejb.SessionBean;
import
 javax.ejb.SessionContext;
import
 com.sap.aii.af.mp.module.*;
import com.sap.aii.af.ra.ms.api.*; 
/**
*
 @ejbHome <{com.sap.aii.af.mp.module.ModuleHome}>
*
 @ejbLocal <{com.sap.aii.af.mp.module.ModuleLocal}>
*
 @ejbLocalHome <{com.sap.aii.af.mp.module.ModuleLocalHome}>
*
 @ejbRemote <{com.sap.aii.af.mp.module.ModuleRemote}>
* @stateless*/
public class ChangeErrorLoad implements SessionBean, Module {
private SessionContext myContext;
public void ejbRemove() {}
public void ejbActivate() {}
public void ejbPassivate() {}
public void setSessionContext(SessionContext context) {myContext = context;
}
public void ejbCreate() throws CreateException {}
public ModuleData process(ModuleContext moduleContext,
ModuleData inputModuleData)
throws ModuleException {String returnMsg;
byte[] out = null;
byte[] file = null;
int OK;
// FTP related Declarations
FtpClient m_client;
String host = "172.0.0.1";String user =
"user";
String password = "pwd";String m_sLocalFile =
"";
String m_sHostFile = "";String sDir =
"";
String fileName = null;String messageId = null; 

//Check Load
try {Object dataObject =
null;
Message xiMessage = null; 
int result = 0;ByteArrayOutputStream outXML = null;String Message_Text;
dataObject = inputModuleData.getPrincipalData();
xiMessage = (Message) dataObject;
Hashtable mp = (Hashtable)
inputModuleData.getSupplementalData
("module.parameters"); 
if (mp != null) fileName = (String) mp.get("FileName");messageId = xiMessage.getMessageId();
 
//Prepare File name which has message id appended to it



 
m_sHostFile =
"/ftp/ReadError/"+fileName+"_"+messageId+"_Error.txt";


 
//Get XML Payload 
XMLPayload payloadData = xiMessage.getDocument();
//Get text form for string processing
Message_Text = payloadData.getText();
int length = Message_Text.length();
if ((Message_Text.indexOf("order") > 0)
&& (Message_Text.indexOf("authcode") > 0)&& (Message_Text.indexOf("status") > 0)) {OK = 1;
}
else {
try {m_client = new FtpClient(host);m_client.login(user, password);
m_client.ascii();
 
OutputStream os = m_client.put(m_sHostFile);
//Get text into byte for file writing
 
file = Message_Text.getBytes();
int filesize = file.length;os.write(file,0,filesize);
os.close();
 
} catch (Exception ex) {System.out.println("Error: " + ex);}
}
} catch (Exception e) {
// raise exception, when an error occurred
ModuleException me = new ModuleException(e);throw me;}
return inputModuleData;}
}

Author: Ravi Kanth Talagana
Submitted: Dec 10 2008
Related Links:

  • <link>

Description:

When you use the standard 'IF' function in the message mapping, only the first value gets mapped to the target field.

If you want to check for a condition and then map a queue/array of values to the target, use the following code.

Name your function as IF.

The parameters to be passed are

1) trueorfalse (string type array)

2) value (string type array)

Chose the radio-button as QUEUE.

&nbsp;&nbsp; //write your code here
&nbsp;
for( int i=0;i<trueorfalse.length;i++)
{
if (trueorfalse[i].equals("true"))
{
for( int j=0;j<value.length;j++)
{
result.addValue(value[j]);
}
}
else
{
&nbsp;throw new RuntimeException("This field is Mandatory for this customer");
}
}

Author: Harikrishna Adepu

Submitted: 18 Nov 2008
Related Links:

  •  

Description

         Sometimes the requirement is such that we need to throw an exception if a field that is defined as optional with the occurrence 0..1 is not populated in XI Graphical Mapping. The below snippet can be used to achieve this scenario.

This can be used as a UDF in XI Graphical Mapping and will throw the exception "This field is Mandatory" if the source field does not have any input values.

String retValue = null;
if(a == null || (a != null && a.length() == 0)) {
throw new RuntimeException("This field is Mandatory");
} else {
retValue = a;
}
return retValue;
 

  • No labels