• [SAP ABAP开发技术总结]IDoc


    18.4.     IDoc

    IDoc是基于文档,用作异步传输数据的载体,类似于XML

    18.4.1.           数据段类型和数据段定义(WE31

    数据段是IDoc结构组件,是IDoc的构成的单元。它由Segment type(数据段类型)Segm. definition(数据段定义)两部分组成,其中Segment type的名称与SAP版本无关,但Segm. definition名称是与SAP版本有关的,外部系统就是根据Segm. definition名称来确定当前数据段的版本的:

    image335

    SAP提供的标准数据段类型定义中,Segment type名称以“E1”开头,而Segm. definition名称则以“E2”开头(如果为用户自定的数据段,则数据段类型名应以“Z1”开头,数据段定义名称应以“Z2”开头),且后面跟上版本号(如上面的006),如数据段类型E1FIKPF对应多个版本的数据段定义(包括最初版本在内共7个版本):

    image336

    双击006版本,即可查看数据段类型F1FIKPF的最新具体定义,如上上图所示

     

    IDoc数据段中各个字段的数据类型均为字符类型(如上上图中的Export leng),在出站时已将原数据类型都转换为字符型了。另外,在ABAP程序中,访问IDoc中的具体某个字段时,需要通过Segment type(数据段类型)名而不是Segm. definition(数据段定义)名,如:E1FIKPF-BUKRS,而不是E2FIKPF006-BUKRS之类的。

     

    IDoc Type中的数据段类型实质会在数据字典中的创建相应的结构,如上图数据段类型E1FIKPF

    image337

    18.4.2.           IDoc定义(WE30

    IDoc类型中定义了数据段以及数据段的层级和次序

    image338

    标准SAP系统提供的IDoc类型称为基本类型(Basic type),该类型可以通过IDoc扩展(Extention)进行调整,即在SAP IDoc类型结构的基础上增加新的数据段或者在数据段中增加新字段

    image339

    如果是自己完全创建一个新的类型不扩展任何类型则选择Basic Type”,否则如果是要从已存在类型来扩展出新的类型时需要选择Extension”,并且需要指定basic type

    image340

    18.4.3.           自定义IDoc发送与接收实例

    该实例使用800发送端向810接收端发送Idoc进行实验

    18.4.3.1.       发送端800outbound)配置

    1、创建segmentWE31

    segment类似于创建XML的节点及节点属性,即定义XML文档中的节点及节点属性

    image341

    image342

    2、创建IDOC TypeWE30

    创建IDOC Type,定义结点间的相互逻辑关系

    先输入YPOIDOC,然后点击创建,紧跟着选择create new

    image343

    在主界面中,先点击创建按钮,将YPOHEAD添加,设置Mandatory seg打勾,min 1 max 1,代表我们每个IDOC仅包含一张采购订单

    image344

    然后在YPOHEAD下添加YPOITEM,同样的Mandatory seg打勾,min 1 max 99999

     image345

    image346

    3、创建Message TypeWE81

     先切换到编辑状态,然后点击New Entries,输入YPO_MESS_TYPE即可。

    image347

    4、关联Message TypeIDOC TypeWE82

    image348

    5、创建接收端RFC DestinationSM59 

    创建一个到接收端810物理连接,由于是该实例是在同一个SAP系统内部进行实验,所以“连接类型”选择的是ABAP Connection连接,名为ZTO810

    image349

    image350

    6、创建到收端的端口(WE21 

    注:这里讲的端口不是单纯的指定Socket端口号,而是指连接到RFC目标系统的统称,包括IP、端口等信息,实质上是在SM59创建的物理连接基础之上创建的另一种逻辑名而已

    基于上面第5步创建的RFC Destionation,创建端口Port,类型选TRANSACTIONAL RFC,名为TO810PORTRFC destination则填写ZTO810

    image351 image352

    7、创建发送端Logical System并分配(SALE 

    为发送端800创建逻辑系统 Z800LS

    image353 image354

    并将逻辑系统分配到发送端800

    image355 image356

    注:这里不需要为本端(Client 800)在本端创建发送端逻辑系统的合作和伴配置文件,但需要在接收端810中配置

    8、创建接收端Logical SystemSALE 

    为接收端810创建逻辑系统 Z810LS,这将在下一步创建到接收端的合作伙伴配置文件Partner profileWE20)时用到:

    image357

    但与上面创建发送端逻辑系统不一样的是,在发送端系统800中是不需要将它分配给Client 810,而分配操作是在接收端810中进行的,这一分配操作请参考后面接收端(Inbound)配置章节

    9、创建接收端合作和伴配置文件Partner profileWE20 

    合作和伴配置文件将Message Type消息类型receiver port RFC目标端口IDoc类型关联起来

    创建一个patner noZ810LS的合作和伴配置文件,该配置文件描述了将IDoc发往何处

    image358

    上图中合作伙伴编号填上一步创建的接收端逻辑系统,类型选择LSTy.选择是“用户”类型,代理人为本系统(发送端800)中的用户,如果在Idoc发送过程中出现什么问题,会向此用户发送邮件。当上面信息填好后点击保存保存之后才可以对Outbound parmtrs进行设置

    然后点击outbound下方的加号创建一个outbound parameterMessage TypeYPO_MESS_TYPEreceiver portTO810PORToutput mode选择Transfer idoc immed.Basic Type填写YPOIDOC保存即可

    image359

    10、通过ABAP程序发送IDOC 

    程序的思路就是,把每个IDOC节点按字符串形式逐个添加,而字符串的添加次序自然也体现了IDOC节点间的逻辑关系。代码如下:


    DATA: ls_pohead TYPE ypohead,"IDoc数据段:头
          ls_poitem
    TYPE ypoitem,"IDoc数据段:Item
          ls_edidc
    TYPE edidc,"IDoc的控制记录
          lt_edidc
    TYPE TABLE OF edidc,
          lt_edidd
    TYPE TABLE OF edidd WITH HEADER LINE."IDoc的数据记录
    CLEAR ls_edidc.
    *系统根据下面4行即可与WE20(合作和伴配置文件)设置关联起来
    ls_edidc
    -mestyp = 'YPO_MESS_TYPE'. "Message Type
    ls_edidc
    -idoctp = 'YPOIDOC'. "IDOC Type
    ls_edidc
    -rcvprn = 'Z810LS'. "partner Number of Recipient接收方合作伙伴
    ls_edidc
    -rcvprt = 'LS'.     "partner Type of Receiver接收方类型为逻辑系统

    *添加IDOC节点
    CLEAR lt_edidd.
    lt_edidd
    -segnam = 'YPOHEAD'."头节点
    lt_edidd
    -dtint2 = 0.
    CLEAR ls_pohead.
    ls_pohead
    -ebeln = '4001122334'."采购单号
    ls_pohead
    -bukrs = '1000'."公司代码
    ls_pohead
    -bedat = '20090630'."日期
    lt_edidd
    -sdata = ls_pohead. "节点内容ls_pohead结构中的数据最后被拼接成字符串再赋值给lt_edidd-sdata,最大长度不能超过1000
    APPEND lt_edidd.

    CLEAR lt_edidd.
    lt_edidd
    -segnam = 'YPOITEM'."Item节点
    lt_edidd
    -dtint2 = 0.
    CLEAR ls_poitem.
    ls_poitem
    -ebeln = '4001122334'."采购单号
    ls_poitem
    -ebelp = '0001'."Item行号
    ls_poitem
    -matnr = '000000000000004527'."物料号
    ls_poitem
    -menge = '3'."数量
    ls_poitem
    -meins = 'ST'."单位
    lt_edidd
    -sdata = ls_poitem.
    APPEND lt_edidd.

    CLEAR lt_edidd.
    lt_edidd
    -segnam = 'YPOITEM'."Item节点
    lt_edidd
    -dtint2 = 0.
    CLEAR ls_poitem.
    ls_poitem
    -ebeln = '4001122334'."采购单号
    ls_poitem
    -ebelp = '0002'."Item行号
    ls_poitem
    -matnr = '000000000000009289'."物料号
    ls_poitem
    -menge = '5'."数量
    ls_poitem
    -meins = 'M'."单位
    lt_edidd
    -sdata = ls_poitem.
    APPEND lt_edidd.
    CALL FUNCTION
    'MASTER_IDOC_DISTRIBUTE'"发送IDoc
     
    EXPORTING
        master_idoc_control           
    = ls_edidc "IDoc控制记录
     
    TABLES
        communication_idoc_control    
    = lt_edidc "接收:用来接收IDoc发送情况
        master_idoc_data              
    = lt_edidd "IDoc数据记录
     
    EXCEPTIONS"
        error_in_idoc_control         
    = 1
        error_writing_idoc_status     
    = 2
        error_in_idoc_data            
    = 3
        sending_logical_system_unknown
    = 4
       
    OTHERS                         = 5.
    IF sy-subrc <> 0.
     
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
             
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.

    ELSE.
     
    COMMIT WORK.
     
    WRITE: 'Idoc sent:'.
     
    LOOP AT lt_edidc INTO ls_edidc.
       
    NEW-LINE.
       
    WRITE: 'Idoc number is', ls_edidc-docnum,
              
    '; receiver partner is', ls_edidc-rcvprn,
              
    '; sender partner',ls_edidc-sndprn.
     
    ENDLOOP.
    ENDIF.

    image360

    image361

    选中消息,并点击“处理”按钮后,该消息就会发往目的客户端810,状态从准备发送到成功发送:

    image362

    发送的数据可以选择数据记录节点来查看:

    image363

    image364

    以上都是在发送端800进行的,下面登录到接收端810去看看IDoc接收情况:

    image365

    由于在接收端810未配置到发送端800的合作伙伴配置文件,所以出错。下面章节在接收端810中进行发送端800的相关配置

    18.4.3.2.       接收端810Inbound)配置

    由于该实例是在同一服务器的同一实例中进行的,又由于SegmentIDoc TypeMessage Type这些都是跨Client的,所以上面1234步就不需要在810端再次配置了,这些是共享的(但如果不是在同一服务器上,则需要像上面那样进行配置

    1、创建发送端RFC DestinationSM59 

    创建到发送端810物理连接

    image366

    image367

    2、创建发送端的端口(WE21

    基于上面创建的RFC Destionation,创建端口Port,类型选TRANSACTIONAL RFC,名为FRM800PORTRFC destination则填写上面创建的RFC远程目标ZFROM800

    image368 image369

    3、将接收端Logical System分配到Client 810SALE 

    如果是在不同的服务器中,则接收端需要像在发送端那样:发送端逻辑系统Z800LS与接收端逻辑系统Z810LS都需要被创建,并且还需要将接收端逻辑系统Z810LS分配到Client 810,并且还需要以发送端逻辑系统Z800LS为基础创建发送端合作伙伴配置文件

    由于是在同一服务器的同一实例中,所以在发送端中创建的发送端逻辑系统Z800LS与接收端逻辑系统Z810LS在此端是通用共享,这里不需要再次创建(outbound中已经创建了这两个逻辑系统了),但(outbound章节中并未分配到具体的ClientZ810LS逻辑系统没有分配到相应的Client,这一步操作需要在接收端完成,所以需要在此进行分配:

    image370

    4、创建入站处理函数 

    创建一个functionY_IDOC_PO_PROCESS.

    IDOC设置完毕之后,SAP可以自动调用该Funtion Module处理IDOC,所以这个函数的参数接口是有规范的,可以从IDOC_INPUT_BBP_IV这些标准函数拷贝参数接口部分:

    "ypoheadypoitem为上面定义的IDoc类型
    DATA: ls_chead TYPE ypohead,
          ls_citem
    TYPE ypoitem.
     
    CLEAR idoc_contrl.
     
    READ TABLE idoc_contrl INDEX 1.
     
    IF idoc_contrl-mestyp <> 'YPO_MESS_TYPE'.
       
    RAISE wrong_function_called.
     
    ENDIF.
     
    LOOP AT idoc_contrl.
       
    LOOP AT idoc_data WHERE docnum = idoc_contrl-docnum.
         
    CASE idoc_data-segnam.
           
    WHEN 'YPOHEAD'.
             
    "直接将字符赋值给结构,赋值过程中会按照结构中的字段长度来划分各字段
              ls_chead
    = idoc_data-sdata.
             
    WRITE: / 'Head',ls_chead.
           
    WHEN 'YPOITEM'.
              ls_citem
    = idoc_data-sdata.
             
    WRITE: / 'Item',ls_citem.
           
    WHEN OTHERS.
         
    ENDCASE.
       
    ENDLOOP.
       
    "根据数据处理情况设置当前IDoc处理的状态
       
    IF 1 = 0.
         
    CLEAR idoc_status.
          idoc_status
    -docnum = idoc_contrl-docnum."当前正处理的IDoc
          idoc_status
    -status = '53'. "IDOC处理成功
         
    APPEND idoc_status.
       
    ELSE.
         
    CLEAR idoc_status.
          idoc_status
    -docnum = idoc_contrl-docnum.
          idoc_status
    -status = '51'. "IDOC不成功
          idoc_status
    -msgty = 'E'. "错误信息
          idoc_status
    -msgid = 'YMSG'.
          idoc_status
    -msgno = '001'.
         
    APPEND idoc_status.
       
    ENDIF.
     
    ENDLOOP.
    ENDFUNCTION.

    5注册入站处理函数BD51 

    填入函数名Y_IDOC_PO_PROCESSInput Type1

    image371

    6、将入站函数与IDOC Type/Message Type关联(WE57

    Function Module输入Y_IDOC_PO_PROCESS,其下的Type填写FIDOC Type下的Basic Type填写YPOIDOCMessage Type填写YPO_MESS_TYPEDirection填写2(Inbound)

    image372

    7、创建入站处理代码Inbound Process CodeWE42

    Process Code输入YPC_PO,在Option ALE下选择Processing with ALE service,在Processing Type下选择function module,保存后,在随后的窗口中,输入Inbound ModuleY_IDOC_PO_PROCESS

    image373 image374

    8、创建发送端合作和伴配置文件Partner profileWE20 

    由于在发送端800中已创建了发送端逻辑系统Z800LS ,所以在此端不需要在创建(发送端逻辑系统Z800LS),只是需要以此为基础创建和伴配置文件,保存后,点击加号增加进站参数:

    image375 image376

    image377

    9、测试 BD87

    在接收端810使用BD87,登录进去后,会看到发送端发送过来的IDoc,但由于先前还没有配置发送伙伴配置文件,所以失败了:

    image365[1]

    现在在入站处理理函数中设置断点:

    image378

    再执行BD87事务,继续处理出错的消息,最后发现处理成功:

    image379

    image380

    调试程序时,发现数据也传递过来了:

    image381

  • 相关阅读:
    Java学习-008-判断文件类型实例
    Java学习-007-Log4J 日志记录配置文件详解及实例源代码
    Java学习-006-三种数据库连接 MySQL、Oracle、sqlserver
    Java学习-005-初学常用的几个经典循环控制源代码
    Selenium2学习-009-WebUI自动化实战实例-007-Selenium 8种元素定位实战实例源代码(百度首页搜索录入框及登录链接)
    TestNG学习-002-annotaton 注解概述及其执行顺序
    C#设计模式之一单例模式(Singleton Pattern)【创建型】
    C#设计模式之二十三解释器模式(Interpreter Pattern)【行为型】
    C#设计模式之二十二备忘录模式(Memento Pattern)【行为型】
    C#设计模式之二十一访问者模式(Visitor Pattern)【行为型】
  • 原文地址:https://www.cnblogs.com/jiangzhengjun/p/4265551.html
Copyright © 2020-2023  润新知