SAP ABAP开发详解与高端应用 (第6页)

第 186 页 / 共 377 页

*"----------------------------------------------------------------------

*"*"Local interface:

*" IMPORTING

*" VALUE(INPUT_METHOD) LIKE BDWFAP_PAR-INPUTMETHD

*" VALUE(MASS_PROCESSING) LIKE BDWFAP_PAR-MASS_PROC

*" EXPORTING

*" VALUE(WORKFLOW_RESULT) LIKE BDWF_PARAM-RESULT

*" VALUE(APPLICATION_VARIABLE) LIKE BDWF_PARAM-APPL_VAR

*" VALUE(IN_UPDATE_TASK) LIKE BDWFAP_PAR-UPDATETASK

*" VALUE(CALL_TRANSACTION_DONE) LIKE BDWFAP_PAR-CALLTRANS

*" TABLES

*" IDOC_CONTRL STRUCTURE EDIDC

*" IDOC_DATA STRUCTURE EDIDD

*" IDOC_STATUS STRUCTURE BDIDOCSTAT

*" RETURN_VARIABLES STRUCTURE BDWFRETVAR

*" SERIALIZATION_INFO STRUCTURE BDI_SER

*" EXCEPTIONS

*" WRONG_FUNCTION_CALLED

*"----------------------------------------------------------------------

* 声明常量

INCLUDE MBDCONWF.

* 声明表结构

TABLES : ZTTEST_T.

* 声明段结构

DATA : SGTEST LIKE ZSGTEST.

* 声明操作结果

DATA WK_SUBRC LIKE SY-SUBRC VALUE 0.

WORKFLOW_RESULT = C_WF_RESULT_OK.

LOOP AT IDOC_CONTRL.

* 判断信息类型

IF IDOC_CONTRL-MESTYP NE 'ZLTYPTEST'.

RAISE WRONG_FUNCTION_CALLED.

ENDIF.

* 读取IDoc数据

LOOP AT IDOC_DATA .

* 赋值数据

SGTEST = IDOC_DATA-SDATA.

MOVE-CORRESPONDING SGTEST TO ZTTEST_T.

* 更新数据库

INSERT INTO ZTTEST_T VALUES ZTTEST_T.

* 失败的场合

IF SY-SUBRC <> 0.

WK_SUBRC = 1.

ENDIF.

17 8

SGTEST
WK_SUBRC

第 187 页 / 共 377 页

ENDLOOP.

* IDoc处理成功

IF WK_SUBRC EQ 0.

IDOC_STATUS-DOCNUM = IDOC_CONTRL-DOCNUM.

IDOC_STATUS-STATUS = '53'.

IDOC_STATUS-MSGTY = 'I'.

IDOC_STATUS-MSGID = 'ZTESTMSG'.

IDOC_STATUS-MSGNO = '006'.

APPEND IDOC_STATUS.

CLEAR IDOC_STATUS.

* IDoc处理失败

ELSE.

IDOC_STATUS-DOCNUM = IDOC_CONTRL-DOCNUM.

IDOC_STATUS-STATUS = '51'.

IDOC_STATUS-MSGTY = 'E'.

IDOC_STATUS-MSGID = 'ZTESTMSG'.

IDOC_STATUS-MSGNO = '005'.

IDOC_STATUS-MSGV1 = SGTEST-ZZCLASS.

IDOC_STATUS-MSGV2 = SGTEST-ZZYEAR.

APPEND IDOC_STATUS.

CLEAR IDOC_STATUS.

WORKFLOW_RESULT = C_WF_RESULT_ERROR.

RETURN_VARIABLES-WF_PARAM = 'Error_Idocs'.

RETURN_VARIABLES-DOC_NUMBER = IDOC_CONTRL-DOCNUM.

APPEND RETURN_VARIABLES.

CLEAR RETURN_VARIABLES.

ENDIF.

ENDLOOP.

ENDFUNCTION.

关联信息对象(事务码SE91),如图3-122所示。

图3-122

179

IDOC_STATUS -DOCNU
IDOC_STATUS -STATUS
IDOC_STATUS -MSGTY
IDOC_STATUS -MSGID
IDOC_STATUS -MSGNO
IDOC_STATUS -DOCNU
IDOC_STATUS -STATUS
IDOC_STATUS -MSGTY
IDOC_STATUS -MSGID
IDOC_STATUS -MSGNO
IDOC_STATUS -MSGV1
IDOC_STATUS -MSGV2
IDOC_STATUS
-ZZCLASS
-ZZYEAR.
RETURN_VARIABLES- WF_PARAM
RETURN_VARIABLES- DOC_NUMBER

第 188 页 / 共 377 页

步骤三:将函数分配给逻辑信息。

运行事务WE57,单击标准工具栏中的 按钮,转换视图为变更模式,如图3-123所示。

图3-123

单击 按钮,新建条目如图3-124所示。

图3-124

单击标准工具栏中的保存按钮 ,如图3-125所示。

图3-125

单击上图中的 按钮,将分配结果保存。

步骤四:将函数定义为入站函数。

运行事务BD51,单击标准工具栏中的 按钮,转换视图为变更模式,如图3-126所示。

图3-126

18 0

第 189 页 / 共 377 页

单击 按钮,新建入站函数如图3-127所示。

图3-127

单击标准工具栏中的保存按钮 ,如图3-128所示。

图3-128

单击上图中的 按钮,将添加结果保存。

步骤五:创建该IDoc的入站处理代码。

运行事务WE42,单击标准工具栏中的 按钮,转换视图为变更模式,如图3-129所示。

图3-129

单击 按钮,新建入站过程代码如图3-130所示。

图3-130

181

第 190 页 / 共 377 页

单击标准工具栏中的保存按钮 ,如图3-131所示。

图3-131

单击上图中的 按钮,输入入站函数,如图3-132所示。

图3-132

单击标准工具栏中的保存按钮 ,如图3-133所示。

图3-133

18 2

第 191 页 / 共 377 页

单击上图中的 按钮,保存后单击标准工具栏中的返回按钮 ,如图3-134所示。

图3-134

双击上图中的树形菜单 ,添加消息类型。单击 按钮,新建条目如图3-135

所示。

图3-135

单击标准工具栏上的保存按钮 。

步骤六:生成新的伙伴参数文件。

运行事务代码BD64,选中已生成的模型,按照以下路径生成伙伴参数文件,如图3-136

所示。

图3-136

183

第 192 页 / 共 377 页

输入合作伙伴系统(接收方逻辑系统名称),如图3-137所示,单击运行 按钮。

图3-137

显示成功信息如图3-138所示。

图3-138

6.测试系统间IDoc连接

(1)在发送端发送IDoc信息

步骤一:运行程序ZIDOC_SEND,运行结果如图3-139所示。

图3-139

单击运行按钮 ,效果如图3-140所示。

18 4

第 193 页 / 共 377 页

图3-140

步骤二:查看发送成绩结果。

发送完成后,运行事务WE02查看发送消息,如图3-141所示。

图3-141

单击运行按钮 ,如图3-142所示。

图3-142

185

第 194 页 / 共 377 页

(2)在接收端接收

步骤一:查看接收消息。

在接受方服务器运行事务WE02,查看接受消息,如图3-143所示。

图3-143

步骤二:查看接收成绩。

在接受方服务器运行事务SE16,查看表信息,如图3-144所示。

图3-144

3.3.3 SAP系统与其他系统间数据传输

IDoc传输支持C、.Net、Java等各种技术,但需要相关的第三方软件,如Java在SAP的

IDoc操作中需要sapidoc.jar,且在连接操作时需要sapidocjco.jar,这里不做具体介绍。

18 6

第 195 页 / 共 377 页

3.4 RFC应用

在系统间通信过程中,需区分发送系统和接收系统。RFC 调用请求从发送系统(调用系

统)中传至接收系统(被调用系统,也称远程系统或目标系统),发送请求的系统在通信过程

中又称为 RFC 客户端,通信另一方则称为 RFC 服务器。RFC 客户端发起远程函数调用以执

行RFC服务器提供的功能。

其中,调用系统和被调用系统均可以是SAP系统和非SAP系统,此外还可以在SAP系

统内部将特定应用服务器指定为目标系统。

根据通信方向和系统类型,共有以下3种RFC通信:

■ 两个独立的SAP系统之间的通信。

■ SAP系统作为调用系统,与外部远程系统(非SAP ABAP系统)通信。

■ 外部系统作为调用系统,与SAP系统通信。

SAP调用远程函数的能力是通过RFC接口系统(RFC interface system)实现的。根据调用

方向的不同(SAP系统调用其他模块或其他系统调用SAP模块),RFC接口提供以下两种服务:

■ ABAP程序的调用接口。

■ 非SAP ABAP程序的调用接口。

3.4.1 同步RFC方式的远程函数调用

同步RFC要求远程系统在调用时可用,调用程序的处理暂停,并等待远程函数调用的返

回结果再继续。

对于表类型参数,只有扁平结构内表可以被传输,其他类型参数可以用于传输纵深类型

以及 STRING 类型的数据,将内表通过 tables 参数进行传输将获取较快的传输速度,因为系

统内部通过二进制格式进行传输而不是XML格式。

1.同步RFC调用示例

DATA: gtd_bapi TYPE zscarr OCCURS 0.

DATA: gth_bapi TYPE zscarr.

DATA: datas TYPE zscarr-countryfr.

DATA: mess TYPE c LENGTH 80.

*- 筛选数据

SELECT a~countryfr a~cityfrom a~cityto a~fltime a~distance b~carrname a~distance a~distid

INTO CORRESPONDING FIELDS OF TABLE gtd_bapi

FROM spfli AS a INNER JOIN scarr AS b ON a~carrid = b~carrid .

*- 调用RFC

CALL FUNCTION 'ZTEST_RFC'

DESTINATION 'SAP_JAVA_TEST'

TABLES

p_table = gtd_bapi

*--- 这里异常不是函数自己定义的,是系统的

EXCEPTIONS

system_failure = 1 MESSAGE mess

187

gtd_bapi
gth_bapi
datas
mess
zscarr
zscarr
countryfr a cityfrom a
CORRESPONDING
spfli
carrname a
gtd_bapi
carrid
DESTINATION '
p_table
system_failure

第 196 页 / 共 377 页

communication_failure = 2 MESSAGE mess

resource_failure = 3.

*- 不成功则退出

IF sy-subrc <> 0.

WRITE: / mess.

EXIT.

ENDIF.

*- 打印调用后结果

WRITE: / '----------------------'.

LOOP AT gtd_bapi INTO gth_bapi.

WRITE: / gth_bapi-countryfr.

ENDLOOP.

如果远程函数处理时出现交互对话过程,将在当前调用程序的会话中先进行远程对话处

理,处理结束后再继续调用程序,在远程系统为SAP ABAP系统的情况下,可以对功能模块

进行正常的调试,即进入(step in)远程模块,系统在当前会话中进行远程调试,完成后再回

到调用程序的调试界面。

2.同步调用的异常处理

同步调用RFC时,系统自动处理标准异常communication_failure和system_failure。

若在系统中没有正确维护远程目标,或到远程系统的连接不能建立,系统将触发

communication_failure异常。

若连接成功,但指定的远程函数不存在于目标系统中,系统将触发system_failure。

若发生异常,不会引起中断(Short Dumpt),与该异常相关的中断的首行说明内容被传递

到message附加项指定的变量mess中,变量类型为扁平的字符结构。

■ 确保远程目标在SM59中被维护。

■ 确保功能模块存在于该目标系统中。

3.4.2 异步RFC方式的远程函数调用

1.同步RFC调用示例

DATA: gtd_bapi TYPE zscarr OCCURS 0.

DATA: gth_bapi TYPE zscarr.

DATA: lwk_finished TYPE i VALUE 0.

DATA: mess TYPE c LENGTH 80.

DATA: lwk_task TYPE c LENGTH 8 VALUE 'Tttttt'.

*- 筛选数据

SELECT a~countryfr a~cityfrom a~cityto a~fltime a~distance b~carrname a~distance a~distid

INTO CORRESPONDING FIELDS OF TABLE gtd_bapi

FROM spfli AS a INNER JOIN scarr AS b ON a~carrid = b~carrid.

*- 调用RFC

*-- The asynchronous RFC does not support communication with external systems or programs in other

programming languages.

CALL FUNCTION 'ZTEST_RFC'

STARTING NEW TASK 'Tt'

18 8

communication_failure
resource_failure
gtd_bapi I
/ gth_bapi- countryfr
gth_bapi
lwk_finished
mess
lwk_task
LENGTH
LENGTH
countryfr a cityfrom a
CORRESPONDING
spfli
carrname a
gtd_bapi
carrid

第 197 页 / 共 377 页

DESTINATION 'NONE'

PERFORMING back ON END OF TASK

TABLES

p_table · = gtd_bapi

EXCEPTIONS

system_failure = 1 MESSAGE mess

communication_failure = 2 MESSAGE mess.

*- 不成功则退出

IF sy-subrc <> 0.

WRITE: / mess.

EXIT.

ENDIF.

*- 打印调用之前的数据

WRITE: / 'before----------------------'.

LOOP AT gtd_bapi INTO gth_bapi.

WRITE: / gth_bapi-countryfr.

ENDLOOP.

*- 等待直到调用处理完毕

WAIT UNTIL lwk_finished = 1 UP TO 10 SECONDS.

*- 打印调用处理后的数据

WRITE: / 'after----------------------'.

LOOP AT gtd_bapi INTO gth_bapi.

WRITE: / gth_bapi-countryfr.

ENDLOOP.

*&---------------------------------------------------------------------*

*& Form fm_callback

*&---------------------------------------------------------------------*

* text

*----------------------------------------------------------------------*

* -->T 任务名称

*----------------------------------------------------------------------*

FORM back USING t.

RECEIVE RESULTS FROM FUNCTION 'ZTEST_RFC' KEEPING TASK

TABLES

p_table = gtd_bapi

EXCEPTIONS

system_failure = 1 message mess

communication_failure = 2 message mess.

.

lwk_finished = 1.

ENDFORM. "fm_callback

STARTING NEW TASK 指明异步调用模式,函数模块在新的工作过程中执行,也可以在

后台模式处理异步 RFC 调用过程,在后台处理时,每个异步 RFC 调用也将占据一个对话工

189

DESTINATION
PERFORMING b
p_table ·
system_failure
communication_failure
mess
mess
/
gtd_bapi
/ gth_bapi -countryfr
/
gtd_bapi
/ gth_bapi -countryfr
p_table
system_failure
communication_failure
lwk_finished
mess
mess

第 198 页 / 共 377 页

作过程。

异步RFC调用过程只能使用TABLES、EXPORTING(对应功能模块设定中的Import参

数)和EXCEPTIONS参数。调用程序并不等待该模块的返回结果,因而不能指定IMPORTING

参数,即不能直接接收从被调用功能中返回的信息。调用的同时只能接收系统标准异常,对

于功能模块中抛出的其他特点异常则不能直接接收。

2.异步远程对话处理和调试

异步 RFC 调用过程也支持远程对话处理,在异步 RFC 调用时,系统总是打开新的工作

进程,因而如果被调用功能模块包含对话程序(屏幕调用处理),则在该功能模块执行时,调

用系统中将出现新的外部会话窗口,若调用功能时打开的会话数达到 6 个,则试图打开新窗

口时触发system_failure。

异步RFC调用时,对远程函数进行step in的调试过程,调用程序本身的调试会话不会进

入远程调用函数内部,系统也打开新的会话,单独增加一个窗口,进行目标系统中远程调用

函数的调试,将断点放在远程调用函数的 CALL FUNCTION语句处,在异步RFC 模式下进

行调试。

3.异步RFC调用时接收结果

通过语句中的附加项PERFORMING return_form on end of task 实现异步调用结果搜集,

子程序必须存在于调用程序中,如果回调子程序中包含任何使当前程序执行中断的语句,call

screen、submit、commit work、wait、RFC调用及W或I类型的消息等,则不能成功返回结果。

通过语句子程序中Receive results from function从远程调用函数中接收结果。主程序运行

期间,远程调用函数在其他工作过程中运行,因此系统变量sy-subrc和程序变量不会被更新,

主程序将文本发送至输出列表的缓冲区中。

通过语句WAIT UNTIL log_exp [UP TO sec SECONDS]用于异步RFC调用中等待结果的

返回,该项必须与performing附加项配合使用,否则没有意义。

当满足log_exp条件后,程序继续执行,否则程序将挂起,并等待异步RFC调用的返回

结果。当功能模块调用结束时,系统将自动执行回调子程序,在其中接收返回结果并设定相

关的逻辑条件变量值,子程序结束后将回到wait until语句,在多个异步RFC调用存在的情况

下,等待过程将反复重复,直到等待条件被满足,或不再有其他开发的异步RFC调用。

4.保持远程上下文

在receive语句中,通过keeping task附加项可以使已经加载的远程上下文保持至调用程

序结束,直到远程连接终止为止。

远程调用函数中的交互对话处理都将保持至调用程序结束。通过 performing 接收结果的

异步RFC调用不能进行内存滚动区的切换或进入内部模式,因为将导致异步返回结果无法传

递给调用程序,可以通过submit或call transaction语句进行内存滚动区的切换。

3.4.3 并行RFC方式的远程函数调用

并行RFC方式的远程函数调用实际是异步RFC调用的应用之一。异步RFC调用实现并

行处理:

■ 异步RFC调用适用于多个SAP ABAP系统间的并行处理(不支持SAP系统和其他系

统间的并行过程)。

19 0

第 199 页 / 共 377 页

■ 在同一 SAP 系统内部使用异步 RFC 调用,将部分处理负载转移到其他的应用服务器

方法时,将RFC目标指定为其他应用服务器。

■ 若不显示指定异步RFC调用目标,在同一应用服务器内,可以通过本地异步RFC 调

用实现多个工作过程的并行处理。

注:事务SM59 可将SAP 系统中的应用服务器分配成不同的 RFC 分组,异步调用时,

通过DESTINATION子句中的IN GROUP附加项指定一个已定义的RFC分组。若不显示指定

RFC 分组,还可以使用关键字 DEFAULT,系统从全部可用的应用服务器中选择一个处理。

该项只能在当前SAP系统作为RFC目标时使用。

1.并行处理的前提条件

逻辑独立的工作单元,并行处理并不适合需要顺序进行的数据处理。

ABAP要求函数模块必须设定为远程支持,被调用的函数模块不能包含使目标BACK的

远程功能调用,调用程序不能在异步调用之后生成新的内部会话(即不能在 call function

starting new task语句后使用submit 或 call transaction语句),不能通过call function starting new

task destination in group 语句启动外部程序。

系统中的服务器至少有3个对话工作进程,否则触发RESOURCE_FAILURE异常

2.并行RFC调用示例

TYPES: BEGIN OF TASK_TYPE,

NAME TYPE STRING,

DEST TYPE STRING,

END OF TASK_TYPE.

DATA: SND_JOBS TYPE I,

RCV_JOBS TYPE I,

EXC_FLAG TYPE I,

INFO TYPE RFCSI,

MESS TYPE C LENGTH 80,

INDX TYPE C LENGTH 4,

NAME TYPE C LENGTH 8,

TASK_LIST TYPE STANDARD TABLE OF TASK_TYPE,

TASK_WA TYPE TASK_TYPE.

DO 10 TIMES.

INDX = SY-INDEX.

CONCATENATE 'Task' INDX INTO NAME.

CALL FUNCTION 'RFC_SYSTEM_INFO'

STARTING NEW TASK NAME

DESTINATION IN GROUP DEFAULT

PERFORMING RFC_INFO ON END OF TASK

EXCEPTIONS

SYSTEM_FAILURE = 1 MESSAGE MESS

COMMUNICATION_FAILURE = 2 MESSAGE MESS

RESOURCE_FAILURE = 3.

191

TASK_TYPE,
STRING
TRING
NAME
DEST
SND_JOBS
RCV_JOBS T
EXC_FLAG
INFO T
MESS
INDX
NAME
TASK_LIST
TASK_WA
LENGTH
ENGTH
LENGTH
INDX
DESTINATION
PERFORMING RFC_INFO
SYSTEM_FAILURE
COMMUNICATION_FAILURE
RESOURCE_FAILURE
MESS
MESS

第 200 页 / 共 377 页

CASE SY-SUBRC.

WHEN 0.

SND_JOBS = SND_JOBS + 1.

WHEN 1 OR 2.

MESSAGE MESS TYPE 'I'.

WHEN 3.

IF SND_JOBS >= 1 AND

EXC_FLAG = 0.

EXC_FLAG = 1.

WAIT UNTIL RCV_JOBS >= SND_JOBS

UP TO 5 SECONDS.

ENDIF.

IF SY-SUBRC = 0.

EXC_FLAG = 0.

ELSE.

MESSAGE 'Resource failure' TYPE 'I'.

ENDIF.

WHEN OTHERS.

MESSAGE 'Other error' TYPE 'I'.

ENDCASE.

ENDDO.

WAIT UNTIL RCV_JOBS >= SND_JOBS.

LOOP AT TASK_LIST INTO TASK_WA.

WRITE: / TASK_WA-NAME, TASK_WA-DEST.

ENDLOOP.

*&---------------------------------------------------------------------*

*& Form rfc_info

*&---------------------------------------------------------------------*

FORM RFC_INFO USING NAME.

TASK_WA-NAME = NAME.

RCV_JOBS = RCV_JOBS + 1.

RECEIVE RESULTS FROM FUNCTION 'RFC_SYSTEM_INFO'

IMPORTING

RFCSI_EXPORT = INFO

EXCEPTIONS

SYSTEM_FAILURE = 1 MESSAGE MESS

COMMUNICATION_FAILURE = 2 MESSAGE MESS.

IF SY-SUBRC = 0.

TASK_WA-DEST = INFO-RFCDEST.

ELSE.

TASK_WA-DEST = MESS.

19 2

SND_JOBS
EXC_FLA
EXC_FLA
TIL RCV_JOBS >= SND_JOBS
SY- SUB
EXC_FLA
TASK_LIST TASK_WA
/ TASK_WA -NAM
TASK_WA-N NAME
RCV_JOBS = RCV_JOBS +
SULTS
SYSTEM_FAILURE
COMMUNICATION_FAILURE
IF SY -SUBRC
TASK_WA-
TASK_WA-
MESS
MESS

第 201 页 / 共 377 页

ENDIF.

APPEND TASK_WA TO TASK_LIST.

ENDFORM. "rfc_info

注:WAIT UNTILL LOG_EXP UP TO N SECONDS,程序中断时间最长是N秒。

3.4.4 事务RFC方式的远程函数调用

同步、异步RFC过程中,每一个RFC调用在远程系统中构成一个独立的LUW,而事务

性RFC 调用可以将多个逻辑上相关的远程调用绑定至同一个LUW上。在该 LUW内,按顺

序调用,要么执行所有数据库操作,要么完全回滚来取消全部数据库更新操作,保证RFC调

用过程的完整性和数据一致性。

事务性RFC调用处理保证在程序到达COMMIT WORK语句时执行所有计划的更新,并

且事务性RFC调用仅运行一次,该调用具有安全、可靠的特点。

1.事务RFC调用语法

(1)7.0以前的事务RFC

语法: CALL FUNCTION func IN BACKGROUND TASK

[DESTINATION dest]

[EXPORTING p1 = a1 p2 = a2... ]

[TABLES t1 = itab1 t2 = itab2 ...]

[AS SEPARATE UNIT]

(2)7.0以后的事务RFC

语法: CALL FUNCTION func IN BACKGROUND UNIT oref

[EXPORTING p1 = a1 p2 = a2... ]

[TABLES t1 = itab1 t2 = itab2 ...]

其中oref必须引用一个接口IF_BGRFC_UNIT实现类的对象(异常类捕捉CX_BGRFC_

INVALID_UNIT),在相邻两个COMMIT WORK之间出现的所有相同目标的异步调用都属于

同一个LUW。事务性RFC不需要等待每个单独的更新过程完成,调用程序就可以继续进行,

直到事务结束,若调用发送时,远程系统不可用,调用将设为后台作业运行,不能从调用模

块接收返回结果,不允许调用者进行与远程系统的交互性对话及测试。

不能直接或通过RECEIVE RESULTS FROM FUNCTION语句接收远程函数的返回结果,

函数的接口不应指定任何EXPORT类型参数,否则在CALL FUNCTION语句中的IMPORTING

参数将导致编译错误,事务性RFC运行的功能模块中不适合进行回调(调用远程目标BACK)。

2.事务RFC调用示例

DATA: gtd_bapi TYPE zscarr OCCURS 0.

DATA: gth_bapi TYPE zscarr.

DATA: lwk_finished TYPE i VALUE 0.

DATA: mess TYPE c LENGTH 80.

*- 筛选数据

193

gtd_bapi
gth_bapi
lwk_finished
mess
zscarr
zscarr

第 202 页 / 共 377 页

SELECT a~countryfr a~cityfrom a~cityto a~fltime a~distance b~carrname a~distance a~distid

INTO CORRESPONDING FIELDS OF TABLE gtd_bapi

FROM spfli AS a INNER JOIN scarr AS b ON a~carrid = b~carrid.

*- 调用RFC

CALL FUNCTION ' ZTEST_RFC '

IN BACKGROUND TASK

DESTINATION 'SAP_JAVA_TEST'

AS SEPARATE UNIT

TABLES

p_table = gtd_bapi

EXCEPTIONS

system_failure = 1 MESSAGE mess

communication_failure = 2 MESSAGE mess

resource_failure = 3.

*- 不成功则退出

IF sy-subrc <> 0.

WRITE: / mess.

EXIT.

ENDIF.

*- 加一些区别的数据

gth_bapi-countryfr = 'LJ'.

APPEND gth_bapi TO gtd_bapi.

*- 调用RFC

CALL FUNCTION 'ZBAPI_TEMP'

IN BACKGROUND TASK

DESTINATION 'SAP_JAVA_TEST'

AS SEPARATE UNIT

TABLES

bapi_table = gtd_bapi

EXCEPTIONS

system_failure = 1 MESSAGE mess

communication_failure = 2 MESSAGE mess

resource_failure = 3.

*- 不成功则退出

IF sy-subrc <> 0.

WRITE: / mess.

EXIT.

ENDIF.

*- 这里一定要提交

COMMIT WORK.

在调用示例中直到COMMIT WORK 语句才开始与远程系统进行联系,函数ZTEST_RFC

是一个适合进行事务性RFC调用的远程函数模块,只进行远程系统中的数据库更新,不需要

返回任何数据。

3.事务ID

每一个事务性RFC调用均通过一个独特的事务ID(Transactional ID,TID),TID存在于

19 4

spfl
carrname a
gtd_bapi
carrid carrid
DESTINATION
SEPARATE
p_table
system_failure
communication_failure
resource_failure
mess
mess
sy- subrc <>
gth_bapi-co untryfr
th_bapi
DESTINATION
SEPARATE
bapi_table
system_failure
communication_failure
resource_failure
mess
mess
sy- subrc <>

第 203 页 / 共 377 页

数据库表ARFCSSTATE和ARFCSDATA中,ARFCSSTATE记录LUW执行状态,ARFCSDATA

包含事务性RFC调用的输入数据。

作业执行过程中,从事务性 RFC 表中读取相关数据,与相应的事务性 RFC 进行通信,

远程LUW成功执行,则相应的条目在表中删除。因此,若LUW运行成功,则无法重新执行,

因而保证了仅执行一次。

若COMMIT WORK同时触发了本地更新操作,则事务性RFC调用在本地更新成功完成

之后才开始运行。

4.设定作业开始时间

如果希望在特定时间启动LUW,可以通过函数模块START_OF_BACKGROUPTASK设

置作业开始的时间,必须在 LUW内部且在第一个 CALL…IN BACKGROUNDTASK语句之

后和COMMIT WORK语句之前调用该函数模块。

对于某个调用需要创建独立的事务,不参与其他目标的事务性 RFC 调用的任何一个

LUW,可以通过AS SEPARATE UNTIAL附加项实现,各个LUW处理都是独立进行的,执

行次序无法被保证。

5.出错处理机制

发生错误时,事务性RFC调用将启动重试机制或者回滚。通过COMMIT WORK执行远

程调用时,不能建立到目标系统的连接,将在ARFCSSTATE表中记录当前状态,系统通过报

表 RSARFCSE 根据当前的 TID 重新计划后台作业,准备进行下一次调用。默认时间间隔为

15分钟,尝试至30次为止。

在RFC配置时(事物代码SM59),通过以下路径进行尝试次数和时间间隔的设定如图3-145

所示。

图3-145

设定界面如图3-146所示。

图3-146

若经过最大尝试次数,仍然无法连接,系统将停止调用报表 RSARFCSE,并将

ARFCSDATA并状态更新为CPICERR,默认为8天,将表中的响应条目删除,事物SM59可

195

第 204 页 / 共 377 页

以手动启动该条目。

执行出错时,A类型的消息或者RAISE 语句抛出异常,则ARFCSSTATE表将记录出错

状态,整个RFC中的操作将取消,SM58查看该错误并修改错误后,通过SM58重新启动出

错的远程调用函数。

在远程调用函数中,功能模块RESTART_OF_BACKGROUNDTASK启动重试功能。

6.检查事务性RFC调用状态

每个LUW都用唯一的TID进行标识,有以下两种方法检查TID状态:

■ ABAP程序:在CALL… IN BACKGROUND TASK之后和COMMIT WORK之前调

用函数“ID_OF_BACKGROUNDTASK”,获得 TID 后,用 FM“STATUS_OF_

BACKGROUNDTASK”确定事务性RFC的状态。

■ 联机确认:通过SM58显示并维护事务性RFC的LUW状态。

3.4.5 队列RFC方式的远程函数调用

确保事务性RFC调用中的LUW都按照其创建次序执行,需要使用队列RFC创建LUW

序列。队列RFC是事务性RFC的增强版本,用于SAP-SAP及SAP-非SAP系统间的连接。

多个函数发送至目标系统中的三种可能情况(实际的连接过程仍然通过事务性RFC来实现,

可以增加入站、出站队列)包括普通事务性RFC、含出站队列的队列RFC和含出入站队列的

队列RFC,其中出站队列在队列RFC中是必须的。

出站调度器用于控制其他逻辑目标系统中的 LUW 执行,入站调度器控制本地系统中的

队列RFC执行(目标NONE或IN BACKGROUND TASK实现为指定目标RFC),事务SMQS

可以配置出战的队列RFC序列,事务SMQR可以配置入站的队列RFC序列,需要在普通事

务性RFC调用之前使用函数模块TRFC_SET_QUEUE_NAME来指明后续的事务性RFC所要

插入的出战队列,通过函数 TRFC_SET_QIN_PROPERTIES来完成入站队列。

队列RFC调用示例如下:

DATA: gtd_bapi TYPE zscarr OCCURS 0.

DATA: gth_bapi TYPE zscarr.

DATA: lwk_finished TYPE i VALUE 0.

DATA: mess TYPE c LENGTH 80.

*- 筛选数据

SELECT a~countryfr a~cityfrom a~cityto a~fltime a~distance b~carrname a~distance a~distid

INTO CORRESPONDING FIELDS OF TABLE gtd_bapi

FROM spfli AS a INNER JOIN scarr AS b ON a~carrid = b~carrid.

*- 设置队列

CALL FUNCTION 'TRFC_SET_QUEUE_NAME'

EXPORTING

qname = 'Q1'

* NOSEND = ' '

* TRFC_IF_SYSFAIL = ' '

* CALL_EVENT = ' '

* EXCEPTIONS

* INVALID_QUEUE_NAME = 1

19 6

gtd_bapi
gth_bapi
lwk_finished
mess LENGTH
zscarr
zscarr
I
spfli
cityfrom a~ cityto a
CORRESPONDING
gtd_bapi
carrid carrid
qname

第 205 页 / 共 377 页

* OTHERS = 2

.

*- 调用RFC

CALL FUNCTION 'ZTEST_RFC'

IN BACKGROUND TASK

DESTINATION 'SAP_JAVA_TEST'

TABLES

p_table = gtd_bapi

EXCEPTIONS

system_failure = 1 MESSAGE mess

communication_failure = 2 MESSAGE mess

resource_failure = 3.

*- 不成功则退出

IF sy-subrc <> 0.

WRITE: / mess.

EXIT.

ENDIF.

*- 提交

COMMIT WORK.

(1)本地远程函数调用和回调

通过DESTNATION附加项的两个特殊目标NONE和BACK,可以进行远程函数本地远

程调用和回调。调用本地系统中的远程功能模块,即调用当前系统内部的远程函数,CALL

FUNCTION语句格式决定以远程调用或非远程调用方式运行。

本地调用时call function 语句没有destination、starting new task、in background task/unit

出现,不在单独的内存滚动区中运行,若当调用没有指定某些必选exporting参数时,会引发

系统异常终止。

(2)远程回调

■ 在服务器执行远程功能时,该服务器可以调用客户中随调用程序载入内存的功能模

块,称为回调。

■ 通过特殊目标BACK可以触发回调机制。

语法: CALL FUNCTION rfm_name

DESTINATION ‘BACK’

■ 只有同步调用时,才可以在服务器中的被调用功能模块中使用BACK功能。

注:各种RFC调用总结如下:

■ 同步 RFC 调用需要等待 RFM 返回结果;异步 RFC 不需要,但需要通过 RECEVICE

语句在回调子程序中接收结果。事务性RFM不能接收RFM返回值。

■ 同步/异步RFC调用,服务器系统必须在调用时可用;事务性RFC无此限制。

■ 同步/异步RFC调用过程,允许用户与远程系统进行交互对话;事务性RFC不允许。

■ 同步/异步RFC调用过程,参数值将直接传输至支持远程调用的功能模块;事务性RFC

的参数值暂时存储在数据库中。

197

DESTINATION
p_table
system_failure
communication_failure
resource_failure
mess
mess
sy- subrc <>

第 206 页 / 共 377 页

■ 对于异步 RFC,只适用于 SAP 系统内部或之间的调用,不能通过 T 类型目标连接至

外部系统。

■ 事务性RFC、队列RFC支持状态查询。

3.4.6 外部系统RFC方式的远程调用

在与其他语言的程序进行通信时,SAP 将为各种语言及相关的操作系统提供 RFC 库及

SAP连接器,以实现RFC接口,如:

■ 为C和C++提供的RFC SDK。

■ 为Java提供的Java连接器JCo。

■ 为.NET提供的.NET连接器NCo。

■ SAP调用远程功能的能力是通过RFC接口系统(RFC interface system)实现的。

下面的示例通过RFC传递参数并调用Java端Web Service返回数据。

做成远程调用函数(Remote Function Module)的步骤如下:

步骤一:做成函数接口使用的结构体。

银行数据传入用结构体如图3-147所示。

图3-147

文件名传出用结构体如图3-148所示。

图3-148

19 8

第 207 页 / 共 377 页

步骤二:做成函数。

函数组(Function Group)如图3-149所示。

图3-149

远程函数属性(Attributes)标签页配置如图3-150所示。

图3-150

远程函数传入(Import)标签页配置如图3-151所示。

图3-151

199

第 208 页 / 共 377 页

远程函数传出(Export)标签页配置如图3-152所示。

图3-152

远程函数传入传出(Changing)标签页配置如图3-153所示。

图3-153

远程函数传入传出(Tables)标签页配置如图3-154所示。

图3-154

远程函数异常(Exceptions)标签页配置如图3-155所示。

图3-155

远程函数原代码编辑如图3-156所示。

图3-156

20 0

第 209 页 / 共 377 页

编辑测试程序源码如下:

*----------------------------------------------------------------------*

*

* Program ID :ZRFC_JAVA

* Program Description :通过RFM调用JAVA

* Create User :BCUSER

* Create Date :2011/02/20

*

*----------------------------------------------------------------------*

* Function Overview

* 通过逻辑文件选择某机器上的路径,读取上面的文件

* 并把结果返回给R/3

*.

*----------------------------------------------------------------------*

* Change List :

* change NO. Change Date Change User Change Detail

* 0000001 2011/02/20 BCUSER 创建程序

*----------------------------------------------------------------------*

REPORT ZRFC_JAVA

NO STANDARD PAGE HEADING

LINE-SIZE 132

LINE-COUNT 65(2)

MESSAGE-ID ZTESTMSG.

*----------------------------------------------------------------------*

* CONSTANTS

*----------------------------------------------------------------------*

CONSTANTS: CNS_LOC_L TYPE C VALUE 'L'.

*----------------------------------------------------------------------*

* DATA

*----------------------------------------------------------------------*

DATA: STR_FILE TYPE ZIMPORT_FILE.

DATA TBL_BANK TYPE TABLE OF ZBANK_DATA.

DATA H_TBL_BANK TYPE ZBANK_DATA.

*----------------------------------------------------------------------*

* PARAMETERS

*----------------------------------------------------------------------*

PARAMETERS: P_TYPE TYPE DXFILE-FILETYPE OBLIGATORY. "文件类型

PARAMETERS: P_FILE TYPE DXFILE-FILENAME OBLIGATORY. "文件

*----------------------------------------------------------------------*

* INITIALIZATION

*----------------------------------------------------------------------*

201

STR_FILE
TBL_BANK
H_TBL_BANK
P_TYPE
P_FILE
DXFILE -FILETYPE OBLIGATORY
DXFILE- FILENAME OBLIGATORY

第 210 页 / 共 377 页

INITIALIZATION.

* 数据初始化

PERFORM DATA_INIT.

*----------------------------------------------------------------------*

* AT SELECTION SCREEN OUTPUT

*----------------------------------------------------------------------*

AT SELECTION-SCREEN OUTPUT.

* 选择画面显示属性设定

PERFORM SCREEN_ATTR_SET.

*----------------------------------------------------------------------*

* AT SELECTION SCREEN ON VALUE-REQUEST

*----------------------------------------------------------------------*

AT SELECTION-SCREEN ON VALUE-REQUEST FOR P_FILE.

* 选择画面项目选择

PERFORM FILE_INPUT_SELECT.

*----------------------------------------------------------------------*

*START-OF-SELECTION

*----------------------------------------------------------------------*

START-OF-SELECTION.

* 报表数据初始化

PERFORM REPORT_DATA_INIT.

* 报表数据选择

PERFORM REPORT_DATA_SELECT.

* 报表数据打印

PERFORM REPORT_DATA_EXE.

*----------------------------------------------------------------------*

* TOP-OF-PAGE

*----------------------------------------------------------------------*

TOP-OF-PAGE.

* 报表页眉编辑

PERFORM REPORT_HEADER_EDIT.

*&---------------------------------------------------------------------*

*& Form DATA_INIT

*&---------------------------------------------------------------------*

* 数据初始化

*----------------------------------------------------------------------*

20 2

第 211 页 / 共 377 页

FORM DATA_INIT .

MOVE CNS_LOC_L TO P_TYPE .

ENDFORM. " DATA_INIT

*&---------------------------------------------------------------------*

*& Form SCREEN_ATTR_SET

*&---------------------------------------------------------------------*

* 选择画面显示属性设定

*----------------------------------------------------------------------*

FORM SCREEN_ATTR_SET .

LOOP AT SCREEN.

IF SCREEN-NAME = 'P_TYPE'.

MOVE 0 TO SCREEN-INPUT.

MODIFY SCREEN.

ENDIF.

ENDLOOP.

ENDFORM. " SCREEN_ATTR_SET

*&---------------------------------------------------------------------*

*& Form FILE_INPUT_SELECT

*&---------------------------------------------------------------------*

* 选择画面项目选择

*----------------------------------------------------------------------*

FORM FILE_INPUT_SELECT .

CALL FUNCTION 'F4_DXFILENAME_4_DYNP'

EXPORTING

DYNPFIELD_FILETYPE = 'P_TYPE'

DYNPFIELD_FILENAME = 'P_FILE'

DYNAME = 'ZRFC_JAVA'

DYNUMB = '1000'

LOCATION = 'A'

SERVER = ''.

ENDFORM. " FILE_INPUT_SELECT

*&---------------------------------------------------------------------*

*& Form REPORT_DATA_INIT

*&---------------------------------------------------------------------*

* 报表数据初始化

*----------------------------------------------------------------------*

FORM REPORT_DATA_INIT .

CLEAR: TBL_BANK[],H_TBL_BANK.

ENDFORM. " REPORT_DATA_INIT

*&---------------------------------------------------------------------*

*& Form REPORT_DATA_SELECT

*&---------------------------------------------------------------------*

* 报表数据选择

*----------------------------------------------------------------------*

FORM REPORT_DATA_SELECT .

DATA L_FILE TYPE FILENAME-FILEINTERN.

203

DYNPFIELD_FILETYPE
DYNPFIELD_FILENAME
DYNAME
DYNUMB
LOCATION
SERVER

第 212 页 / 共 377 页

L_FILE = P_FILE.

CALL FUNCTION 'FILE_GET_NAME'

EXPORTING

* CLIENT = SY-MANDT

LOGICAL_FILENAME = L_FILE "伦理文件

* OPERATING_SYSTEM = SY-OPSYS

* PARAMETER_1 = ' '

* PARAMETER_2 = ' '

* PARAMETER_3 = ' '

* USE_PRESENTATION_SERVER = ' '

* WITH_FILE_EXTENSION = ' '

* USE_BUFFER = ' '

* ELEMINATE_BLANKS = 'X'

IMPORTING

* EMERGENCY_FLAG = EMERGENCY_FLAG

* FILE_FORMAT = FILE_FORMAT

FILE_NAME = STR_FILE-FILENAME "物理文件

EXCEPTIONS

FILE_NOT_FOUND = 1

.

CALL FUNCTION 'ZGET_BANK_DATA'

DESTINATION 'Z_TEST_DESTINATION'

EXPORTING

FILENAME = STR_FILE

TABLES

BANKDATA = TBL_BANK.

ENDFORM. " REPORT_DATA_SELECT

*&---------------------------------------------------------------------*

*& Form REPORT_DATA_EXE

*&---------------------------------------------------------------------*

* 报表数据打印

*----------------------------------------------------------------------*

FORM REPORT_DATA_EXE .

LOOP AT TBL_BANK INTO H_TBL_BANK.

WRITE: /2 H_TBL_BANK-BANKS,"国家

7 H_TBL_BANK-BANKL,"银行代码

18 H_TBL_BANK-BANKA,"银行名称

38 H_TBL_BANK-PROVZ,"地区 (州、省、县)

43 H_TBL_BANK-STRAS,"住宅号及街道

63 H_TBL_BANK-ORT01,"城市

73 H_TBL_BANK-BRNCH,"分行

93 H_TBL_BANK-SWIFT,"关于国际付款的 SWIFT 码

100 H_TBL_BANK-BGRUP."银行组 (银行网)

20 4

L_FILE
FILE_NAME
FILE_NOT_FOUND
DESTINATION
FILENAME
/2 H_TBL_BANK -BANKS
H_TBL_BANK -BANKL
H_TBL_BANK -BANKA
H_TBL_BANK -PROVZ
H_TBL_BANK -STRAS,
H_TBL_BANK -ORT01,
H_TBL_BANK -BRNCH
H_TBL_BANK -SWIFT,
1 H_TBL_BANK -BGRUP

第 213 页 / 共 377 页

ENDLOOP.

ENDFORM. " REPORT_DATA_EXE

*&---------------------------------------------------------------------*

*& Form REPORT_HEADER_EDIT

*&---------------------------------------------------------------------*

* 报表页眉编辑

*----------------------------------------------------------------------*

FORM REPORT_HEADER_EDIT .

WRITE: 35 '银行文件数据一览',

/2 '国家',

7 '银行代码',

18 '银行名称',

38 '地区',

43 '住宅号及街道',

63 '城市',

73 '分行',

93 'SWIFT 码',

100 '组'.

ENDFORM. " REPORT_HEADER_EDIT

伦理文件路径设定如图3-157所示。

图3-157

文件内容编辑如图3-158所示。

图3-158

205

/2

第 214 页 / 共 377 页

步骤三:配置RFC。

RFC技术设定标签页设定如图3-159~图3-161所示。

图3-159

图3-160

图3-161

RFC登录标签页设定如图3-162所示。

图3-162

20 6

第 215 页 / 共 377 页

RFC Unicode标签页设定如图3-163所示。

图3-163

RFC特殊属性标签页设定如图3-164和图3-165所示。

图3-164

图3-165

207

第 216 页 / 共 377 页

步骤四:编辑JAVA程序。

下载SAP JAVA CONNECTORS软件(sapjco.jar)及动态连接库sapjcorfc.dll,安装Java

开发工具 Eclipse,双击快捷图标或按照安装路径启动 Java 编辑工具,启动结果如图 3-166

所示

图3-166

按照以下路径创建Java工程,如图3-167所示。

图3-167

20 8

第 217 页 / 共 377 页

设定工程属性如图3-168所示。

图3-168

单击 按钮,编译环境设置如图3-169所示。

图3-169

209

第 218 页 / 共 377 页

选择Libraries标签页,在配置库中添加JCo组件,如图3-170所示。

图3-170

单击 按钮,如图3-171所示。

图3-171

21 0

第 219 页 / 共 377 页

单击对话框中的 按钮,再单击 按钮,创建工程结果如图3-172所示。

图3-172

按照以下路径创建Java包,如图3-173所示。

图3-173

211

第 220 页 / 共 377 页

包名设定如图3-174所示。

图3-174

单击 按钮,按照以下路径为包添加Java类,如图3-175所示。

图3-175

21 2

第 221 页 / 共 377 页

Java类属性设定如图3-176所示。

图3-176

单击 按钮,编辑代码如下:

package TestRFC;

import java.io.BufferedReader;

import java.io.File;

import java.io.IOException;

import java.util.regex.Pattern;

import com.sap.mw.jco.*;

import com.sap.mw.jco.JCO.Function;

public class SAPServer extends JCO.Server {

public SAPServer(JCO.Repository repo) {

super("192.168.61.251", "sapgw00", "Z_JAVA_TEST", repo);

}

protected void handleRequest(Function arg0) throws Exception {

//取得传入参数

JCO.ParameterList importfile = arg0.getImportParameterList();

//取得传入文件名

String fileName = importfile.getStructur(e "FILENAME").getString("FILENAME").toString

();

213

package TestRFC;
import java.io.BufferedReader
import java.io.File;
import java.io.IOException;
import java.util.regex.Pattern;
import com.sap.mw.jco.*;
import com.sap.mw.jco.JCO.Function;
public class SAPServer extends JCO.Server {
public SAPServer(JCO.Repository repo) {
super("192.168.61.251", "sapgw00", "Z_JAVA_TEST", repo);
}
protected void handleRequest(Function arg0) throws Exception {
//取得传入参数
JCO.ParameterList importfile = arg0.getImportParameterList();
//取得传入文件名
String fileName = importfile.getStructur(e "FILENAME").getString("FILENAME").toString

第 222 页 / 共 377 页

//编辑传入文件名

fileName = fileName.replaceAll("\\\\", "\\\\\\\\");

File file = new File(fileName);

JCO.Table banks = arg0.getTableParameterList().getTable(

"BANKDATA");

//编辑传出表格

try {

BufferedReader br = new BufferedReader(new java.io.FileReader(file));

String line = br.readLine();

while (line != null) {

Pattern comma = Pattern.compile(",");

String[] bank = comma.split(line);

banks.appendRow();

banks.setValue(bank[0], "BANKS"); //银行国家代码

banks.setValue(bank[1], "BANKL"); //银行代码

banks.setValue(bank[2], "BANKA"); //银行名称

banks.setValue(bank[3], "PROVZ"); //地区 (州、省、县)

banks.setValue(bank[4], "STRAS"); //住宅号及街道

banks.setValue(bank[5], "ORT01"); //城市

banks.setValue(bank[6], "BRNCH"); //分行

banks.setValue(bank[7], "SWIFT"); //关于国际付款的 SWIFT 码

banks.setValue(bank[8], "BGRUP"); //银行组 (银行网)

System.out.println(line);

line = br.readLine();

}

br.close();

} catch (IOException e) {

e.printStackTrace();

return;

}

//this.stop();

}

}

按照以上步骤创建类SAPLogon,编辑代码如下:

package TestRFC;

import com.sap.mw.jco.JCO;

public class SAPLogon {

public JCO.Client mConnection;

public JCO.Repository mRepository;

21 4

//编辑传入文件名
fileName = fileName.replaceAll("\\\\", "\\\\\\\\");
File file = new File(fileName);
JCO.Table banks = arg0.getTableParameterList().getTable(
"BANKDATA");
//编辑传出表格
try {
BufferedReader br = new BufferedReader(new java.io.FileReader(file));
String line = br.readLine()
while (line != null) {
Pattern comma = Pattern.compile(",");
String[] bank = comma.split(line);
banks.appendRow();
banks.setValue(bank[0], "BANKS"); //银行国家代码
banks.setValue(bank[1], "BANKL"); //银行代码
banks.setValue(bank[2], "BANKA"); //银行名称
banks.setValue(bank[3], "PROVZ"); //地区 (州、省、县)
banks.setValue(bank[4], "STRAS"); //住宅号及街道
banks.setValue(bank[5], "ORT01"); //城市
banks.setValue(bank[6], "BRNCH"); //分行
banks.setValue(bank[7], "SWIFT"); //关于国际付款的 SWIFT 码
banks.setValue(bank[8], "BGRUP"); //银行组 (银行网)
System.out.println(line);
line = br.readLine();
}
br.close();
e.printStackTrace();
return;
}
返回ABAP参考资料列表