Despite all of the advances in Web service and proxy technologies over the course of the past few years, I still find that many customers prefer to use the tried-and-true ALE/IDoc technology stack. Consequently, a frequent administrative headache is the upload of IDoc metadata using Transaction IDX2. In this blog, I will demonstrate a simple report program that can be used to automate this task.
What is IDoc metadata, anyway?
If you haven't worked with the PI IDoc adapter before, then a brief introduction is in order. As you know, all messages that flow through the PI Integration Engine pipeline are encoded using XML. Thus, besides providing raw connectivity, adapters such as the IDoc adapter also must perform the necessary transformations of messages so that they can be routed through the pipeline. In the case of the IDoc adapter, the raw IDoc data (you can see how the IDoc data is encoded by looking at the signature of function module IDOC_INBOUND_ASYNCHRONOUS) must be transformed into XML. Since the raw IDoc data does not provide information about segment field names, etc., this metadata must be imported at configuration time in order to enable the IDoc adapter to perform the XML transformation in an efficient manner.
From a configuration perspective, all this happens in two transactions:
- In Transaction IDX1, you create an IDoc Adapter Port which essentially provides the IDoc adapter with an RFC destination that can be used to introspect the IDoc metadata from the backend SAP ALE system.
- In Transaction IDX2, you can import IDoc types using the aforementioned IDoc adapter port. Here, you can import standard IDoc types, custom IDoc types, or even extended types.
If you're dealing with a handful of IDocs, then perhaps this isn't such a concern. However, if you're dealing with 10s or 100s of IDocs and a multitude of PI systems, then this process can become tedious in a hurry.
Automating the Upload Process
Now, technically speaking, the IDoc adapter is smart enough to utilize the IDoc port definition to dynamically load and cache IDoc metadata on the fly. However, what it won't do is detect changes to custom IDocs/extensions. Furthermore, if you have scenarios during cutover which block RFC communications, not having the IDoc metadata in context can lead to unexpected results. The report below can be used to automate the initial upload process or execute a kill-and-fill to pull in the latest and greatest changes. In reading through the comments, you can see that it essentially takes two inputs: the IDoc adapter port defined in IDX1 and a CSV file from your frontend workstation that defines the IDoc types to import. Here, you just need to create a two-column CSV file containing the IDoc type in column 1 and the extension type (if any) in column 2.
REPORT zidx_idoc_load_metadata. *&---------------------------------------------------------------------* *& Local Class Definitions * *&---------------------------------------------------------------------* CLASS lcl_report DEFINITION CREATE PRIVATE. PUBLIC SECTION. CLASS-METHODS: "Used in the selection screen definition: get_frontend_filename CHANGING ch_file TYPE string, "Public static method for running the report: execute IMPORTING im_idoc_types_file TYPE string im_idoc_port TYPE idx_port. PRIVATE SECTION. "Class-Local Type Declarations: TYPES: BEGIN OF ty_idoc_type, idoc_type TYPE string, ext_type TYPE string, END OF ty_idoc_type, ty_idoc_type_tab TYPE STANDARD TABLE OF ty_idoc_type. "Instance Attribute Declarations: DATA: idoc_port TYPE idx_port, idoc_types TYPE ty_idoc_type_tab. "Private helper methods: METHODS: constructor IMPORTING im_idoc_port TYPE idx_port, upload_idoc_types IMPORTING im_idoc_types_file TYPE string RAISING cx_sy_file_io, import_idoc_metadata, remove_idoc_metadata IMPORTING im_idoc_type TYPE string. ENDCLASS. CLASS lcl_report IMPLEMENTATION. METHOD get_frontend_filename. "Local Data Declarations: DATA: lt_files TYPE filetable, lv_retcode TYPE i, lv_user_action TYPE i. FIELD-SYMBOLS: <lfs_file> LIKE LINE OF lt_files. "Present the user with a dialog box to select the name "of the file they want to upload: CALL METHOD cl_gui_frontend_services=>file_open_dialog EXPORTING default_extension = 'csv' file_filter = '.csv' CHANGING file_table = lt_files rc = lv_retcode user_action = lv_user_action EXCEPTIONS file_open_dialog_failed = 1 cntl_error = 2 error_no_gui = 3 not_supported_by_gui = 4 others = 5. IF sy-subrc EQ 0. IF lv_user_action NE cl_gui_frontend_services=>action_cancel. READ TABLE lt_files INDEX 1 ASSIGNING <lfs_file>. IF sy-subrc EQ 0. ch_file = <lfs_file>-filename. ENDIF. ENDIF. ELSE. MESSAGE 'Could not determine target filename!' TYPE 'I'. RETURN. ENDIF. ENDMETHOD. " METHOD get_frontend_filename METHOD execute. "Method-Local Data Declarations: DATA: lo_report TYPE REF TO lcl_report, lo_exception TYPE REF TO cx_root, lv_message TYPE string. TRY. "Create an instance of the report driver class: CREATE OBJECT lo_report EXPORTING im_idoc_port = im_idoc_port. "Upload the set of IDoc types to load into the IDoc adapter; "This file should be a CSV file on the local workstation: CALL METHOD lo_report->upload_idoc_types EXPORTING im_idoc_types_file = im_idoc_types_file. "Import the set of IDoc types: CALL METHOD lo_report->import_idoc_metadata( ). CATCH cx_root INTO lo_exception. lv_message = lo_exception->get_text( ). MESSAGE lv_message TYPE 'I'. ENDTRY. ENDMETHOD. " METHOD execute METHOD constructor. me->idoc_port = im_idoc_port. ENDMETHOD. " METHOD constructor METHOD upload_idoc_types. "Method-Local Data Declarations: DATA: lt_csv_file TYPE string_table, lv_idoc_type TYPE edipidoctp, lv_ext_type TYPE edipcimtyp. FIELD-SYMBOLS: <lfs_csv_record> LIKE LINE OF lt_csv_file, <lfs_idoc_type> LIKE LINE OF me->idoc_types. "Upload the selected file from the user's workstation: CALL METHOD cl_gui_frontend_services=>gui_upload EXPORTING filename = im_idoc_types_file CHANGING data_tab = lt_csv_file EXCEPTIONS file_open_error = 1 file_read_error = 2 no_batch = 3 gui_refuse_filetransfer = 4 invalid_type = 5 no_authority = 6 unknown_error = 7 bad_data_format = 8 header_not_allowed = 9 separator_not_allowed = 10 header_too_long = 11 unknown_dp_error = 12 access_denied = 13 dp_out_of_memory = 14 disk_full = 15 dp_timeout = 16 not_supported_by_gui = 17 error_no_gui = 18 others = 19. IF sy-subrc NE 0. RAISE EXCEPTION TYPE cx_sy_file_io EXPORTING filename = im_idoc_types_file. ENDIF. "Copy the CSV file into the IDoc types table: LOOP AT lt_csv_file ASSIGNING <lfs_csv_record>. SPLIT <lfs_csv_record> AT ',' INTO: lv_idoc_type lv_ext_type. APPEND INITIAL LINE TO me->idoc_types ASSIGNING <lfs_idoc_type>. <lfs_idoc_type>-idoc_type = lv_idoc_type. <lfs_idoc_type>-ext_type = lv_ext_type. ENDLOOP. ENDMETHOD. " METHOD upload_idoc_types METHOD import_idoc_metadata. "Method-Local Data Declarations: DATA: lv_count TYPE i. FIELD-SYMBOLS: <lfs_idoc_type> LIKE LINE OF me->idoc_types. "Process each of the selected IDoc types in turn: LOOP AT me->idoc_types ASSIGNING <lfs_idoc_type>. "Check to see if the metadata already exists: SELECT COUNT(*) INTO lv_count FROM idxsload WHERE port EQ me->idoc_port AND idoctyp EQ <lfs_idoc_type>-idoc_type AND cimtyp EQ <lfs_idoc_type>-ext_type. IF lv_count GT 0. "If it does, go ahead and remove it: CALL METHOD remove_idoc_metadata( <lfs_idoc_type>-idoc_type ). ENDIF. "Now, import the IDoc metadata using IDX_FILL_STRUCTURE: SUBMIT idx_fill_structure WITH port = me->idoc_port WITH idoctyp = <lfs_idoc_type>-idoc_type WITH cimtyp = <lfs_idoc_type>-ext_type AND RETURN. ENDLOOP. ENDMETHOD. " METHOD import_idoc_metadata METHOD remove_idoc_metadata. "Remove the IDoc metadata using IDX_RESET_METADATA: SUBMIT idx_reset_metadata WITH port = me->idoc_port WITH idoctyp = im_idoc_type AND RETURN. ENDMETHOD. " METHOD remove_idoc_metadata ENDCLASS. *&---------------------------------------------------------------------* *& Selection Screen Definition * *&---------------------------------------------------------------------* PARAMETERS: p_idxprt TYPE idx_port OBLIGATORY, p_ifile TYPE string LOWER CASE OBLIGATORY. *&---------------------------------------------------------------------* *& AT SELECTION-SCREEN Event Module * *&---------------------------------------------------------------------* AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_ifile. CALL METHOD lcl_report=>get_frontend_filename CHANGING ch_file = p_ifile. *&---------------------------------------------------------------------* *& START-OF-SELECTION Event Module * *&---------------------------------------------------------------------* START-OF-SELECTION. CALL METHOD lcl_report=>execute EXPORTING im_idoc_port = p_idxprt im_idoc_types_file = p_ifile.