SAP --RFC--> PI --SOAP-->Salesforce
在调用Salesforce的upsert时,一次最多只能包含200个对象,所以当PI接收到超过200个对象的数据时,需要把一个message分成多个messages,即1 --> n。Operation Mapping包括三个步骤:
- message mapping,从源数据结构映射到Salesforce的upsert结构
- Java mapping,从value mapping中取出有效的sessionID和serverURL,在dynamic configuration里设置相应的值
- XSLT mapping,生成多个SOAP request,每个request里的upsert包括最多200个objects,其中要注意output的结构和正确的namespace
<message>
<message1>
<soapenv:Envelope>
...
</soapenv:Envelope>
<soapenv:Envelope>
...
</soapenv:Envelope>
</message1>
<message>
上面的例子会被adapter正确的解释成2个messages。
如果XSLT生成的结构像下面这样:
<message>
<message1>
<soapenv:Envelope>
...
</soapenv:Envelope>
</message1>
<message1>
<soapenv:Envelope>
...
</soapenv:Envelope>
</message1>
<message>
那么在monitoring里会得到下面的错误:
<SAP:Category>XIServer</SAP:Category>
<SAP:Code area="MAPPING">MISSING_INTERFACE</SAP:Code>
<SAP:P1>2</SAP:P1>
<SAP:P2 />
<SAP:P3 />
<SAP:P4 />
<SAP:AdditionalText />
<SAP:Stack>No interface specified for parameter 2</SAP:Stack>
在测试时还需注意,如果是在Repository(design time)里测试operation mapping或message mapping,source input里需要构造
<message> <message1> ...</message1><message>这样的结构,但是在directory里或RWB(runtime)里测试时,payload里都不应该出现<message> <message1> ...</message1></message>这样的结构,否则会得到类似下面的错误:
sap.aii.mappingtool.tf7.IllegalInstanceException: Cannot create target element /ns0:Messages. Values missing in queue context.第3步的XSLT:
<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:urn="urn:enterprise.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://pi.cceag.de/SFDC" xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
<xsl:output indent="yes" method="xml"/>
<xsl:template match="/">
<ns0:Messages>
<ns0:Message1>
<xsl:for-each select="//sObjects[position() mod 200 = 1]">
<soapenv:Envelope>
<xsl:call-template name="header"/>
<soapenv:Body>
<urn:upsert>
<externalIDFieldName>
<xsl:value-of select="//upsert/externalIDFieldName"/>
</externalIDFieldName>
<xsl:for-each select=". | following-sibling::sObjects[position() < 200]">
<xsl:call-template name="sObjects" />
</xsl:for-each>
</urn:upsert>
</soapenv:Body>
</soapenv:Envelope>
</xsl:for-each>
</ns0:Message1>
</ns0:Messages>
</xsl:template>
<xsl:template match="soapenv:Header" name="header">
<xsl:copy-of select="/soapenv:Envelope/soapenv:Header"/>
</xsl:template>
<xsl:template match="sObjects" name="sObjects">
<urn:sObjects xsi:type="Account">
<xsl:for-each select="./*">
<xsl:element name="{local-name()}">
<xsl:value-of select="./text()" />
</xsl:element>
</xsl:for-each>
</urn:sObjects>
</xsl:template>
</xsl:stylesheet>
没有评论:
发表评论