Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Fukuhara
Product and Topic Expert
Product and Topic Expert
1,745
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);