Skip to Content
Technical Articles
Author's profile photo Yohei Fukuhara

SAP Cloud SDKのRfmRequestでRFCを試す(BAPIも)

SAP Cloud SDK for JavaでRfmRequestを使ってRFCを試してみました。メモ程度の簡単な内容ですが投稿します。

基本的なRFCのやり方は別記事「How to call function modules using SAP Cloud SDK for Java」を参照ください。

環境

  • SAP Cloud SDK for Java: 3.19.1
  • NetWeaver ABAP 7.53 SP0
  • Java Buildpack version: sap java build pack 1.25.0

開発内容

ABAP側RFM

いろいろなパラメータを試して見るべく、リモート呼出可能な汎用モジュールを登録。

FUNCTION y_348221_test01_rfc .
*"----------------------------------------------------------------------
*"*"ローカルインタフェース:
*"  IMPORTING
*"     VALUE(IV_NUM) TYPE  I DEFAULT 1
*"     VALUE(IS_TEST) TYPE  YS348221_TEST00 OPTIONAL
*"     VALUE(IT_TEST) TYPE  YT348221_TEST00 OPTIONAL
*"  EXPORTING
*"     VALUE(EV_NUM) TYPE  I
*"     VALUE(ES_TEST) TYPE  YS348221_TEST00
*"     VALUE(ET_TEST) TYPE  YT348221_TEST00
*"  TABLES
*"      ET_RETURN STRUCTURE  BAPIRET2 OPTIONAL
*"  CHANGING
*"     VALUE(CV_NUM) TYPE  I DEFAULT 10
*"     VALUE(CS_TEST) TYPE  YS348221_TEST00 OPTIONAL
*"     VALUE(CT_TEST) TYPE  YT348221_TEST00 OPTIONAL
*"----------------------------------------------------------------------

  ev_num = iv_num + 1.
  cv_num = cv_num + 1.

  es_test = is_test.
  es_test-yyint4 = es_test-yyint4 + 1.
  es_test-yydate = sy-datum.
  es_test-yytime = sy-uzeit.

  cs_test-yyint4 = cs_test-yyint4 + 1.
  cs_test-yydate = sy-datum + 10.
  cs_test-yytime = sy-uzeit + 10.

  APPEND es_test TO et_test.
  APPEND cs_test TO ct_test.

  DATA lt_return TYPE bapiret2_t.

  MESSAGE e001(00) WITH 'error v1' 'error v2' 'error v3' 'error v4' INTO DATA(lv_dummy).

  CALL FUNCTION 'ISU_CRM_IL_BAPIRET2_FILL'
    CHANGING
      ct_msg = lt_return.

  MESSAGE i001(00) WITH 'info v1' 'info v2' 'info v3' 'info v4' INTO lv_dummy.

  CALL FUNCTION 'ISU_CRM_IL_BAPIRET2_FILL'
    CHANGING
      ct_msg = lt_return.

  MESSAGE s001(00) WITH 'success v1' 'success v2' 'success v3' 'success v4' INTO lv_dummy.

  CALL FUNCTION 'ISU_CRM_IL_BAPIRET2_FILL'
    CHANGING
      ct_msg = lt_return.

  et_return[] = lt_return.

ENDFUNCTION.

参照する型YS348221_TEST00は構造で、いろいろなデータ型を含めたのですが、3つくらいしか試していません。時間がなかったからです。

型YT348221_TEST00は構造YT348221_TEST00のテーブルデータ型です。

 

Java開発

Java側のサーブレットはこんなコード。

package com.sap.cloud.sdk;

import com.google.gson.Gson;
import com.sap.cloud.sdk.cloudplatform.connectivity.Destination;
import com.sap.cloud.sdk.cloudplatform.connectivity.DestinationAccessor;
import com.sap.cloud.sdk.s4hana.connectivity.exception.RequestExecutionException;
import com.sap.cloud.sdk.s4hana.connectivity.rfc.Fields;
import com.sap.cloud.sdk.s4hana.connectivity.rfc.Table;
import com.sap.cloud.sdk.s4hana.connectivity.rfc.RfmRequest;
import com.sap.cloud.sdk.s4hana.connectivity.rfc.RfmRequestResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/rfc")
public class RfcServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;
    private static final Logger logger = LoggerFactory.getLogger(RfcServlet.class);
    private static final Destination destinationRfc =
            DestinationAccessor.getDestination("Erp1809Rfc");

    @Override
    protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
            throws IOException {

        logger.info("Start get method: " + request.getRequestURI());
        Fields inStructure = new Fields();
        inStructure.field("YYINT4", "I", 12);
        Fields exStructure = new Fields();
        Fields chStructure = new Fields();
        chStructure.field("YYINT4", "I", 4);

        try {
            RfmRequest rfmRequest = new RfmRequest("Y_348221_TEST01_RFC", false)
                    .withExporting("IV_NUM", "I", 10)
                    .withExportingFields("IS_TEST", "YS348221_TEST00", inStructure)
                    .withImporting("EV_NUM", "I", 0)
                    .withImportingFields("ES_TEST", "YS348221_TEST00", exStructure)
                    .withImportingTable("ET_TEST", "YT348221_TEST00").end()
                    .withChanging("CV_NUM", "I", 0)
                    .withChangingFields("CS_TEST", "YS348221_TEST00", chStructure)
                    .withTableAsReturn("ET_RETURN", "BAPIRET2")
                    .ignoringErrors();  //ignoringErrorsをしておかないとエラーでExceptionに行く

            Table<RfmRequest> exTable = rfmRequest.withExportingTable("IT_TEST", "YS348221_TEST00");
            exTable.row().field("YYINT4", "I", 9)
                         .field("YYCHAR10", "C", "ABC");
            Table<RfmRequest> chTable = rfmRequest.withChangingTable("CT_TEST", "YS348221_TEST00");
            chTable.row().field("YYINT4", "I", 14)
                    .field("YYCHAR10", "C", "ABCDE");

            final RfmRequestResult rfmTest = rfmRequest.execute(destinationRfc);

            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write("IV_NUM: " + String.valueOf(rfmTest.get("IV_NUM")) + "\n");
            response.getWriter().write("EV_NUM: " + String.valueOf(rfmTest.get("EV_NUM")) + "\n");
            response.getWriter().write("CV_NUM: " + String.valueOf(rfmTest.get("CV_NUM")) + "\n");
            response.getWriter().write("IS_TEST: " + rfmTest.get("IS_TEST").toString() + "\n");
            response.getWriter().write("ES_TEST: " + rfmTest.get("ES_TEST").toString() + "\n");
            response.getWriter().write("CS_TEST: " + rfmTest.get("CS_TEST").toString() + "\n");
            response.getWriter().write("IS_TEST-YYINT4: " + String.valueOf(rfmTest.get("IS_TEST").getAsObject().get("YYINT4")) + "\n");
            response.getWriter().write("ES_TEST-YYINT4: " + String.valueOf(rfmTest.get("ES_TEST").getAsObject().get("YYINT4")) + "\n");
            response.getWriter().write("CS_TEST-YYINT4: " + String.valueOf(rfmTest.get("CS_TEST").getAsObject().get("YYINT4")) + "\n");
            response.getWriter().write("IT_TEST: " + rfmTest.get("IT_TEST").getAsCollection().toString() + "\n");
            response.getWriter().write("ET_TEST: " + rfmTest.get("ET_TEST").getAsCollection().toString() + "\n");
            response.getWriter().write("CT_TEST: " + rfmTest.get("CT_TEST").getAsCollection().toString() + "\n");
            response.getWriter().write("Error Message: " + rfmTest.getErrorMessages().toString() + "\n");
            response.getWriter().write("Information Message: " + rfmTest.getInformationMessages().toString() + "\n");
            response.getWriter().write("Success Message: " + rfmTest.getSuccessMessages().toString() + "\n");

        } catch (RequestExecutionException e) {
            response.setContentType("application/json");
            response.setCharacterEncoding("UTF-8");
            response.getWriter().write(new Gson().toJson(e));
            e.printStackTrace();
        }
    }
}

実行結果

呼び出したときのブラウザに表示される結果はこんな感じです。

IV_NUM: GsonResultPrimitive(jsonPrimitive=10)
EV_NUM: GsonResultPrimitive(jsonPrimitive=11)
CV_NUM: GsonResultPrimitive(jsonPrimitive=1)
IS_TEST: GsonResultObject(jsonObject={"YYINT4":12,"YYCHAR10":"","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":null,"YYTIME":"19700101 000000"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a))
ES_TEST: GsonResultObject(jsonObject={"YYINT4":13,"YYCHAR10":"","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":"20200511 000000","YYTIME":"19700101 085007"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a))
CS_TEST: GsonResultObject(jsonObject={"YYINT4":5,"YYCHAR10":"","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":"20200521 000000","YYTIME":"19700101 085017"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a))
IS_TEST-YYINT4: GsonResultPrimitive(jsonPrimitive=12)
ES_TEST-YYINT4: GsonResultPrimitive(jsonPrimitive=13)
CS_TEST-YYINT4: GsonResultPrimitive(jsonPrimitive=5)
IT_TEST: DefaultResultCollection(resultElements=[GsonResultObject(jsonObject={"YYINT4":9,"YYCHAR10":"ABC","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":null,"YYTIME":"19700101 000000"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a))])
ET_TEST: DefaultResultCollection(resultElements=[GsonResultObject(jsonObject={"YYINT4":13,"YYCHAR10":"","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":"20200511 000000","YYTIME":"19700101 085007"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a))])
CT_TEST: DefaultResultCollection(resultElements=[GsonResultObject(jsonObject={"YYINT4":14,"YYCHAR10":"ABCDE","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":null,"YYTIME":"19700101 000000"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a)), GsonResultObject(jsonObject={"YYINT4":5,"YYCHAR10":"","YYQUAN":0.00,"YYUNIT":"","YYCURR":0.00,"YYCUKY":"","YYDATE":"20200521 000000","YYTIME":"19700101 085017"}, resultElementFactory=GsonResultElementFactory(gsonBuilder=com.google.gson.GsonBuilder@2d7d1b5a))])
Error Message: [RemoteFunctionMessage(messageType=E, messageClass=00, messageNumber=001, messageText=error v1error v2error v3error v4)]
Information Message: [RemoteFunctionMessage(messageType=I, messageClass=00, messageNumber=001, messageText=info v1info v2info v3info v4)]
Success Message: [RemoteFunctionMessage(messageType=S, messageClass=00, messageNumber=001, messageText=success v1success v2success v3success v4)]

 

ちなみに、こんな書き方で値だけを取り出すことができます。

response.getWriter().write(rfmTest.get("RFCSI_EXPORT").getAsObject().get("RFCKERNRL").asString());

また、私がよくやる書き方のこいつをやるとエラーがよく起きます。原因をわすれてしまったのですが、構造/テーブル型のパラメータがある場合にエラーとなっている記憶があります。

response.getWriter().write(new Gson().toJson(rfmTest));

BAPIの場合(2020/7/16追加)

RFMではなく、BAPIの場合は、使うクラスこそ変わるものの使い方は大差ないです。

以下は、順にユーザロック解除、ユーザ変更BAPIを呼び出す場合です。

        final BapiRequestResult bapiResult = new BapiRequest("BAPI_USER_UNLOCK", false)
                .withExporting("USERNAME", "C", userId)  //userID becomes upper case in BAPI
                .withTableAsReturn("RETURN", "BAPIRET2")
                .execute(destinationRfc);

        logger.debug("-----------BAPI Result---------");
        logger.info(bapiResult.toString());
        logger.debug(bapiResult.getSuccessMessages().get(0).getMessageText());
        final BapiRequestResult bapiResult = new BapiRequest("BAPI_USER_CHANGE", false) //commit triggered inside bapi
                .withExporting("USERNAME", "C", userId)  //userID becomes upper case in BAPI
                .withExportingFields("PASSWORD", "BAPIPWD", password)
                .withExportingFields("PASSWORDX", "BAPIPWDX", passwordChange)
                //.withExporting("GENERATE_PWD", "C", "X")  //
                .withTableAsReturn("RETURN", "BAPIRET2")
                .execute(destinationRfc);

Assigned Tags

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