Skip to Content
User Experience Insights
Author's profile photo Qiyan Wang

Custom ABAP Operatorを用いてSAP Data IntelligenceからABAPシステムのカスタマコードを呼び出す方法紹介

1.はじめに

このブログではSAP Data Intelligenceに接続されているSAP ABAPシステム間で、SAP Data Intelligenceパイプラインを用いたSAP ABAPシステムのデータ相互連携、並びにABAPシステム内で実装されたカスタマコード(汎用モジュール・BAPIなど)を呼び出す方法を紹介したいと思います。

2. ABAP前提条件

システムに必要なバージョン:SAP S/4HANA 1909およびSAP S/4HANA CE 1911では、ABAPパイプラインエンジンが標準機能に含まれています。 古いリリース(SAP NetWeaver 7.0以降)の場合、ABAPパイプラインエンジンを取得するには、DMISアドオン(DMIS 2018SP02以降またはDMIS2011 SP17以降)をインストールする必要があります。

詳しい条件を下記のブログを参照してください。

https://blogs.sap.com/2021/12/27/abap%e3%82%b7%e3%82%b9%e3%83%86%e3%83%a0%e3%81%a8sap-data-intelligence%e9%80%a3%e6%90%ba%e6%96%b9%e6%b3%95%e7%b4%b9%e4%bb%8b/

3. Custom ABAP Operator概要と実装方法

Custom ABAP OperatorではRFCを経由してABAPシステムで実装した拡張実装BAdIを呼び出し、データの連携を実現しております。拡張実装BAdI内ではカスタマコードを実装することが可能で、こちらの機能を利用する事によりデータの取得、データに更新及びBAPIなどを実行することが可能です。

実装に必要な手順は以下となります。

  • SAP Data Intelligenceから接続設定
      1. SAP Data IntelligenceのConnection ManagementでSAP S/4HANAとの接続設定を行います。
      2. SAP Data IntelligenceのLaunchpadで、Connection Managementを選択し、ボタン(+)をクリックします。
      3. 下記のように接続先SAP S/4HANAのホスト名などを設定し、ボタン(SAVE)を押します。
  • ABAPシステム側BAdI実装( こちらでは2種類のBAdI実装方法を紹介させて頂きます。)
    • レポートを実行する
      • この方法で作成されたBAdIでは基本パラメータやロジックが自動で実装されているため、マニュアルで設定が必要な作業を削減できます。
      1. トランザクションコードse38でレポートDHAPE_CREATE_OPERATOR_CLASS を実行し、クラスを作成します。
      2. その後、トランザクションコードse38でレポートDHAPE_CREATE_OPER_BADI_IMPL を実行し、BAdIを拡張します。
    • マニュアルでBAdIを実装します
      1. トランザクションコードse19で下記のように拡張スポットに”ES_DHAPE_ENGINE”を入力し、ボタン(登録)を押します。
      2. 拡張実装名を入力します。
      3. 拡張実装のBAdI実装と実装クラスの名前を登録します。BAdI定義はBADI_DHAPE_ENGINE_OPERATORを選択します。
      4. 次にフィルタ値を下記のように登録します。SAP Data Intelligence側でCustom ABAP Operatorを設定する場合はこのフィルタの値を選択します。
      5. 次に実装クラスのメソッドを実装します。まずはNEW_PROCESSメソッドを実装し、その中にローカルクラスを定義し、作成します。
      6. Custom ABAP Operatorで実行されたカスタマコードがこの中で作成します。このクラスはcl_dhape_graph_proc_abstractから継承されます。このクラス内ではメソッドの呼び出されるタイミングは異なります。必要に応じてカスタマコードを実装することが可能です。
        • ON_START:パイプラインが開始される前に1回呼び出されます。
        • ON_RESUME:パイプラインが開始、または再開される前に最低1回呼び出されます。
        • STEP:頻繁に呼び出されます。
        • ON_SUSPEND:パイプラインが停止、または一時停止された後に最低1回呼び出されます。
        • ON_STOP:パイプラインが停止した後に1回呼び出されます。
      7. 次にGET_INFOメソッドを実装します。このメソッドではOperatorに関するメタデータを表示します。Name:フィルタの値と一致しなければなりません。SAP Data Intelligence側のCustom ABAP Operatorを設定する際に使用します。Description: SAP Data Intelligence側のCustom ABAP Operatorを設定する際に、Custom ABAP Operatorの説明及びパイプラインで使用するOperatorの名前です。Inports/outports: SAP Data Intelligence側のCustom ABAP OperatorのInport/Outport名前とtypeが一致している必要があります。
  • SAP Data Intelligence側のパイプラインを作成

    SAP Data Intelligence側のCustom ABAP Operatorのinport/outportを作成します。

    Connection Managementで設定した接続をABAP Connectionに設定し、ABAP Operatorの検索ヘルプを選択すると、使用可能なSAP ABAP システムのOperatorが表示されます。

4. サンプル

こちらではSAP Data IntelligenceからABAP側のBAPIを使用し、受注伝票の受注数量を変更します。

全体的な流れでは、SAP Data Intelligence上に存在するファイル内で更新したい伝票番号と明細、及び変更したい数量が含まれます。

そのデータをABAP側に渡して数量の更新を行います。更新のステータス及び更新後の受注伝票のデータをSAP Data Intelligence側に返してSAP Data Intelligence側のファイルを格納します。

  • 設定:
    • 必要のデータをファイルから読み込む(Read file)
    • 呼び出す用Operator設定(Custom ABAP Operator)

    • 返した結果をファイルに書き込む(Write file)

  • ファイル内容:
    • 0000000022/000010/450
  • サンプルコード:ローカルクラスの内容(カスタマコード)
    • CLASS lcl_process DEFINITION INHERITING FROM cl_dhape_graph_proc_abstract.
      
        PUBLIC SECTION.
          METHODS: if_dhape_graph_process~on_start  REDEFINITION.
          METHODS: if_dhape_graph_process~on_resume REDEFINITION.
          METHODS: if_dhape_graph_process~step      REDEFINITION.
      
          DATA:
            mo_util TYPE REF TO cl_dhape_util_factory,
            mo_in   TYPE REF TO if_dhape_graph_channel_reader,
            mo_out  TYPE REF TO if_dhape_graph_channel_writer.
      
      ENDCLASS.
      
      CLASS lcl_process IMPLEMENTATION.
      
        METHOD if_dhape_graph_process~on_start.
      *    mo_out->write_copy(  'abap operator 処理起動' ) .
          "This method is called when the graph is submitted.
          "Note that you can only check things here but you cannot initialize variables.
        ENDMETHOD.
      
        METHOD if_dhape_graph_process~on_resume.
          "This method is called before the graph is started.
      
          "Read parameters from the config here
      *    mv_myparameter = to_upper( if_dhape_graph_process~get_conf_value( '/Config/myparameter' ) ).
      
          "Do initialization here.
          mo_util     = cl_dhape_util_factory=>new( ).
          mo_in       = get_port( 'in' )->get_reader( ).
          mo_out      = get_port( 'out' )->get_writer( ).
        ENDMETHOD.
      
        METHOD if_dhape_graph_process~step.
          "This method caled in a loop as long as the graph is alive
          rv_progress = abap_false.
          CHECK mv_alive = abap_true.
          DATA : ldf_string TYPE string,
                 ldf_result TYPE string.
      
          IF mo_in->has_data( ).
            CHECK mo_out->is_blocked( ) <> abap_true.
      
            mo_in->read_copy( IMPORTING ea_data = ldf_string ).
      
            DATA: salesdocument    TYPE vbeln,
                  order_header_in  TYPE  bapisdh1,
                  order_header_inx TYPE  bapisdh1x,
                  order_item_in    TYPE  TABLE OF bapisditm,
                  order_item_inx   TYPE  TABLE OF bapisditmx,
                  order_item_inl   LIKE LINE OF order_item_in,
                  order_item_inxl  LIKE LINE OF  order_item_inx,
                  return1          TYPE  TABLE OF bapiret2,
                  returnmessage    TYPE bapiret2,
                  schedule_lines   TYPE TABLE OF bapischdl,
                  schedule_linesx  TYPE  TABLE OF bapischdlx,
                  schedule_linesl  LIKE LINE OF schedule_lines,
                  schedule_linesxl LIKE  LINE OF schedule_linesx,
                  ldf_vbeln        TYPE vbeln,
                  ldf_string2      TYPE string,
                  ldf_string3      TYPE string,
                  message          TYPE string.
      
            SPLIT ldf_string AT '/' INTO ldf_vbeln  ldf_string2 ldf_string3.
            order_header_inx-updateflag = 'U'.
      
            order_item_inl-itm_number     =  ldf_string2 .
            APPEND order_item_inl TO order_item_in.
      
            order_item_inxl-itm_number     =  ldf_string2 .
            order_item_inxl-updateflag     =  'U'.
            APPEND order_item_inxl TO order_item_inx..
      
            schedule_linesl-itm_number = ldf_string2 .
            schedule_linesl-sched_line = '0001'.
            schedule_linesl-req_qty    = ldf_string3.
            APPEND schedule_linesl TO schedule_lines.
      
            schedule_linesxl-itm_number = ldf_string2.
            schedule_linesxl-sched_line = '0001'.
            schedule_linesxl-updateflag = 'U'.
            schedule_linesxl-req_qty    = 'X'.
      
            APPEND schedule_linesxl TO schedule_linesx..
      
      
            CALL FUNCTION 'BAPI_SALESORDER_CHANGE'
              EXPORTING
                salesdocument    = ldf_vbeln
                order_header_inx = order_header_inx
              TABLES
                return           = return1
                order_item_in    = order_item_in
                order_item_inx   = order_item_inx
                schedule_lines   = schedule_lines
                schedule_linesx  = schedule_linesx.
      
            IF sy-subrc = '0'.
      
              CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
                EXPORTING
                  wait = 'X'.
            ELSE.
              CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
      
            ENDIF.
            READ TABLE return1 INTO returnmessage INDEX LINES( return1 ).
      
            CALL FUNCTION 'Z_GET'
              EXPORTING
                salesorder_vbeln     = ldf_vbeln
              IMPORTING
                salesorder_data_json = message.
            mo_out->write_copy(  returnmessage-message && message   ) .
      
            rv_progress          = abap_true.
          ELSEIF mo_in->is_closed( ).
            mo_out->close( ).
            rv_progress = abap_true.
          ENDIF.
        ENDMETHOD.
      
      ENDCLASS.
      
      
  • 実行結果:更新の結果及び受注伝票のデータがSAP Data Intelligence側へ返されて、ファイルに書き込ました。

5. Tips

以下はBAdIを実装する際に注意が必要な点になります。

  • BAdIをレポートで自動拡張する際に、フィルタの値がcom.sap.abap.はじめになっていますが、これはSAP ABAP Operatorを使用するときの値である為、Custom ABAP Operatorを使用する場合は、custom.com.sap.abap.のはじめの値を変更しなければなりません。それと同時にGET INFOメソッドのRS_INFOパラメータのname項目の値も変更が必要です。
  • 入力出力パラメータが複数の場合、NEW_PROCESSメソッドのRS_INFOパラメータのInports(あるいはExport)が下記のように記入する必要があります。
  • Inportパラメータを受ける際には一点注意する必要があります。基本Operatorの処理ロジックはSTEPに実装されています。データの受信に関わらず呼び出される場合があるため、inportデータをロジックに読み込みする前に、inportデータが存在するかどうかのチェックが必要です。もしチェック(check mo_in->has_data( ))されない場合、もしくはinportにデータがないとき下記のダンプが発生します。また、複数のinportのデータが同じタイミングで受信されない場合、すべてのポートにデータが受信されるまで待つか、あるいはデータを個別に読み取り、Operator内に保存して、すべてのデータが利用可能になった後に次の手順を実行する必要があります。 実行中、Operator変数はメモリに残りますので、そこに安全に保存/キャッシュできます。

6.まとめ

こちらのブログではCustom ABAP Operatorの使用方法について簡単に紹介頂きました。

Custom ABAP Operatorを活用することにより、SAP S/4HANAとSAP Data Intelligenceの間でのデータの連携や更新をすることができます。また、必要に応じてSAP S/4HANAの様々モジュールを呼び出すことができる為、非常に役立つ機能だと思います。ぜひ皆様にもご活用いただけることを願っております。

 

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.