Contact Us 1-800-596-4880

MuleSoft Enterprise Java Connector for SAP

Enterprise Edition This connector requires a separate license. Please contact MuleSoft if you want to evaluate or use this connector.

Introduction

The Mule SAP Transport uses SAP Java Connector (JCo) libraries, thus enabling your Mule application to:

  1. Execute BAPI functions over sRFC (synchronous RFC), tRFC (transactional RFC) and qRFC (queued RFC)

  2. Act as a JCo Server to be called as a BAPI over sRFC, tRFC and qRFC

  3. Send IDocs over tRFC and qRFC

  4. Receive IDocs over tRFC and qRFC

  5. Transform all SAP objects (JCoFunction & IDocs) to/from XML

sap transport image 01

Installation

Throughout this document, we refer to MuleSoft ESB informally as Mule ESB or simply Mule.

The SAP transport needs JCo libraries to operate. The following section explains how to setup Mule ESB so that you can use the SAP transport in your Mule applications:

This procedure assumes that you already have a Mule instance installed on your host machine. If not, navigate here, then follow the instructions for downloading and installing Mule.

Throughout this document, we use $MULE_HOME to refer to the directory where Mule is installed.
  1. Download the SAP JCo and IDoc libraries from the SAP site: http://service.sap.com/connectors (To do this, you need a SAP User ID).

  2. Make the the SAP jars available to your Mule application and/or Mule ESB instance. JCo relies on a native library, which requires additional installation steps.

  3. If you plan to use SAP as an Inbound Endpoint (that is, Mule is called as a BAPI or receives IDocs), you must perform additional configuration within the services file at the OS level.

About the SAP JCo and IDoc Library Versions The SAP Transport requires:

  • SAP JCo Library 3.0.7 (sapjco-3.0.7.jar)

  • SAP IDoc Libraries 3.0.6 (sapidoc-3.0.6.jar)

The SAP JCo libraries are OS dependent, so make sure to download the SAP libraries that correspond to the OS and hardware architecture of the host server on which Mule is running.

Making Jars Available to Your Mule ESB Application

Follow the instructions provided by SAP to install the JCo libraries, but remember that certain jar files must be located in your application CLASSPATH, and the dynamic link library (dll/so) must reside in your LD_LIBRARY_PATH.

Next, include the transport jar file (mule-transport-sap-{version}.jar) in your application CLASSPATH.

About the Application CLASSPATH The Mule SAP Transport depends on three libraries:

  • mule-transport-sap-{version}.jar

  • sapjco-3.0.x.jar

  • sapidoc-3.0.x.jar

You need to place these in your application CLASSPATH.

For the SAP Transport, MuleSoft recommends the following directories:

  • $MULE_HOME/apps/YOUR_APP/lib: To make libraries available for just your application

  • $MULE_HOME/lib/user: To share libraries among all applications running within the same Mule ESB instance

You also need to tell Mule ESB where the SAP JCo dynamic linked library resides. To accomplish this, you can do either of the following:

  • Configure the LD_LIBRARY_PATH environment variable

  • Configure the Mule ESB wrapper configuration file $MULE_HOME/conf/wrapper.conf by adding the line wrapper.java.library.path.{N}=PATH/TO/SAP-JCO/LIB-DIR

SAP Inbound Endpoint Requirements

If you are configuring a SAP Inbound Endpoint (JCo Server), then you need to modify your OS services file, which is:

  • /etc/services file (for Unix-based OSes)

  • C:\WINDOWS\system32\drivers\etc\services file (for Windows)

In the above file, you must add your gateway (which is configured through the jcoGwService attribute or the jco.server.gwserv / jco.client.gwserv property). There’s no need to add the whole mapping list.

For example, to set the following, jcoGwService=sapgw00, you simply add the following string:

sapgw00 3300/tcp

Port 3300 is predefined by SAP, so if you need to validate other port numbers based on your SAP instance number, you can check the complete list of service-to-port mappings, which can be found here.

Namespace and Syntax

XML namespace:

xmlns:sap=+http://www.mulesoft.org/schema/mule/sap+

XML Schema location:

  • http://www.mulesoft.org/schema/mule/sap

  • http://www.mulesoft.org/schema/mule/sap/3.2/mule-sap.xsd

Within the Schema location URL , you can replace the alias current with a specific Mule ESB version number — such as 3.2, for example.

Connector Syntax:

<sap:connector name="SapConnector" jcoClient="100" jcoUser="User" jcoPasswd="Password"               jcoLang="en" jcoAsHost="host" jcoSysnr="00" jcoTrace="true"               jcoPoolCapacity="3" jcoPeakLimit="10"/>

Endpoint Syntax

Inbound Endpoint

<sap:inbound-endpoint name="idocServer" type="idoc" rfcType="trfc"     jcoConnectionCount="5" jcoGwHost="yoursapgw.company.com" jcoProgramId="send_idoc"     jcoGwService="sapgw00" exchange-pattern="one-way"/>

Outbound endpoint

<sap:outbound-endpoint name="idocSender" type="idoc" connector-ref="SapConnector"                       exchange-pattern="request-response"/>

The Connector

The sap:connector element allows the configuration of JCo connection parameters that can then be shared among sap:inbound-endpoints and sap:outbound-endpoints in the same application.

Configurable Attributes

Attribute Description Default Value

name

The reference name of the connector used internally by Mule configuration.

jcoClient

The SAP client. This is usually a number (For example: 100).

jcoUser

The logon user name for password-based authentication

jcoPasswd

The logon password used for password- based authentication

jcoLang

The language to use for logon dialogs. If not defined, the default user language is used.

en

jcoAsHost

The SAP application server host (either the IP address or server name can be specified).

jcoSysnr

The SAP system number

jcoTrace

Enable/disable RFC trace

false

jcoTraceToLog

If jcoTraceToLog is true then JCo trace is redirected to Mule ESB log files. If this attribute is set, it overrides the Java startup environment property (-Djco.trace_path=<PATH>)

jcoPoolCapacity

The maximum number of idle connections kept open by the destination. No connection pooling takes place when the value is 0.

5

jcoPeakLimit

The maximum number of active connections that can be created for a destination simultaneously

10

jcoClientExtendedProperties-ref

A reference to java.util.Map containing additional JCo connection parameters. Additional information and a complete list of parameters can be found here

Configuration Example

<sap:connector name="SapConnector" jcoClient="100" jcoUser="User" jcoPasswd="Password"    jcoLang="en" jcoAsHost="host" jcoSysnr="00" jcoTrace="true" jcoPoolCapacity="3"    jcoPeakLimit="10"/>
If you want to disable JCo Pool, then just do not provide values for the attributes jcoPoolCapacity and jcoPeakLimit. Also providing a value of zero for the attribute jcoPoolCapacity disables pooling.

SAP Solution Manager

The MuleSoft Enterprise Java Connector for SAP is SAP Solution Manager ready.

To configure it, you create a child element sap:sld-config inside sap:connector so that Mule registers with the System Landscape Directory (SLD) every time the application starts. This child element supports the following attributes:

Attribute Description Default Value

url

The URL (including host and port) where your SLD is listening. Usually the URL conforms to a pattern like this: http://sld-host.company.com:80/sdl/ds

user

A user who has privileges to update information in the SLD

password

The password for the user who has privileges to update the SLD settings

computerName

The name of the machine on which your application.

The host name (without the domain), as obtained from the OS.

localSystemName

The descriptive name for your application.

Example

<sap:connector name="SapConnector" jcoClient="100" jcoUser="User" jcoPasswd="Password"               jcoLang="en" jcoAsHost="host" jcoSysnr="00" jcoTrace="true"               jcoPoolCapacity="3" jcoPeakLimit="10">    <sap:sld-config url="http://sapsld.mulesoft.com:80/sld/ds" user="slduser" password="secret" computerName="mule01" localSystemName="Mule ESB Enterprise Connector"/></sap:connector>

If you have multiple SAP connectors in the same Mule application or even on the same Mule server, then there is no reason to configure a different SLD for every one of them.

Unless you need to register with different SLD servers, you can configure a single sap:sld-config for only one sap:connector, and that SLD serves for all SAP connectors running on the same host.

Endpoints

The MuleSoft Enterprise Java Connector for SAP supports both inbound and outbound endpoints.

  • Inbound Endpoint: Receives IDocs and BAPI calls over RFC.

    • [Receiving IDocs]

    • [Receiving BAPI calls]

  • Outbound Endpoint: Sends IDocs and executes BAPIs over RFC.

Endpoint Address

To support for dynamic endpoints, the SAP Transport supports a URI-style address, for which the general format is:

address="sap://[jcoUser]:[jcoPasswd]@[jcoAsHost]?attr1=value1&attr2=value2& …​ &attrN=valueN"

These attributes can be:

  • The same attributes supported in the connector or endpoint element (for example jcoClient, jcoSysnr, etc.)

  • Specific SAP Connection Properties (for example jco.client.r3name, jco.client.type, etc.)

Whenever attributes that are not specified, default values are used.

You can use Mule Expressions inside the address attribute, just as you do for other Mule ESB transports.

Example of an Inbound Endpoint Address

<sap:inbound-endpoint   address="sap://TEST_USER:secret@localhost?type=function&amp;rfcType=trfc&amp;jcoClient=100&amp;jcoSysnr=00&amp;jcoPoolCapacity=10&amp;jcoPeakLimit=10&amp;jcoGwHost=localhost&amp;jcoGwService=gw-service&amp;jcoProgramId=program_id&amp;jcoConnectionCount=2"/>

Example of an Outbound Endpoint Address

<sap:outbound-endpoint   address="sap://TEST_USER:secret@localhost?type=function&amp;rfcType=trfc&amp;jcoClient=100&amp;jcoSysnr=00&amp;jcoPoolCapacity=10&amp;jcoPeakLimit=10"/>

Important

You must to “escape” the ampersand sign ('&') in the address attribute, replacing it with '&'.

Prioritizing Connection Properties

Properties for SAP JCo connections (inbound and outbound) can be configured in numerous places. The following list details the priorities accorded to values specified in different places, with the highest priority level listed first.

  1. Attributes at <sap:inbound-endpoint/> and <sap:outbound-endpoint/> level (For example jcoClient, jcoUser, jcoPasswd, jcoSysnr, jcoGwHost, jcoProgramId, …​)

  2. Properties in the address attribute at <sap:inbound-endpoint/> and <sap:outbound-endpoint/> level

  3. Properties inside the Map configured in the jcoClientExtendedProperties-ref and/or jcoServerExtendedProperties-ref attributes at at <sap:inbound-endpoint/> and <sap:outbound-endpoint/> level

  4. Attributes configured at <sap:connector/> level (For example jcoClient, jcoUser, jcoPasswd, jcoSysnr, …​)

  5. Properties inside the Map configured in the jcoClientExtendedProperties-ref at <sap:connector/> level

  6. Default values

XML Definition

This definition is the XML representation of a function (JCOFunction) or IDoc (IDocDocument / IDocDocumentList).

In short, these are the XML documents you receive from and send to SAP.

The SAP transport includes Transformers that convert the XML documents exchanged between the endpoints and SAP into corresponding SAP objects that the endpoints can handle.

JCo Function

<?xml version="1.0" encoding="UTF-8"?><jco name="BAPI_PO_CREATE1" version="1.0">  <import>    <structure name="POHEADER">      <field name="COMP_CODE">2100</field>      <field name="DOC_TYPE">NB</field>      <field name="VENDOR">0000002101</field>      <field name="PURCH_ORG">2100</field>      <field name="PUR_GROUP">002</field>    </structure>    <structure name="POHEADERX">      <field name="DOC_TYPE">X</field>      <field name="VENDOR">X</field>      <field name="PURCH_ORG">X</field>      <field name="PUR_GROUP">X</field>      <field name="COMP_CODE">X</field>    </structure>  </import>  <tables>    <table name="POITEM">      <row id="0">        <field name="NET_PRICE">20</field>        <field name="PLANT">2100</field>        <field name="MATERIAL">SBSTO01</field>        <field name="PO_ITEM">00010</field>        <field name="QUANTITY">10.000</field>      </row>    </table>    <table name="POITEMX">      <row id="0">        <field name="PO_ITEMX">X</field>        <field name="MATERIAL">X</field>        <field name="QUANTITY">X</field>        <field name="PLANT">X</field>        <field name="PO_ITEM">00010</field>        <field name="NET_PRICE">X</field>      </row>    </table>    <table name="POSCHEDULE">      <row id="0">        <field name="QUANTITY">10.000</field>        <field name="DELIVERY_DATE">27.06.2011</field>        <field name="SCHED_LINE">0001</field>        <field name="PO_ITEM">00010</field>      </row>    </table>    <table name="POSCHEDULEX">      <row id="0">        <field name="PO_ITEM">00010</field>        <field name="QUANTITY">X</field>        <field name="DELIVERY_DATE">X</field>        <field name="SCHED_LINEX">X</field>        <field name="PO_ITEMX">X</field>        <field name="SCHED_LINE">0001</field>      </row>    </table>  </tables></jco>

JCo Function Response

<?xml version="1.0" encoding="UTF-8" standalone="no"?><jco name="Z_MULE_EXAMPLE">  <import>    ...  </import>  <export>    <structure name="RETURN">      <field name="TYPE"></field>      <field name="ID"></field>      <field name="NUMBER"></field>      <field name="MESSAGE"></field>      <field name="LOG_NO"></field>      <field name="LOG_MSG_NO"></field>      <field name="MESSAGE_V1"></field>      <field name="MESSAGE_V2"></field>      <field name="MESSAGE_V3"></field>      <field name="MESSAGE_V4""></field>      <field name="PARAMETER"></field>      <field name="ROW"></field>      <field name="FIELD"></field>      <field name="SYSTEM"></field>    </structure>  </export>  <exceptions>    <exception>MULE_EXCEPTION_01</exception>    <exception>MULE_EXCEPTION_02</exception>    <exception>MULE_EXCEPTION_03</exception>  </exceptions></jco>

Return Types

  • A: Abort

  • S: Success

  • E: Error

  • W: Warning

  • I: Information

Important

If evaluateFunctionResponse is set to true, then the SAP outbound endpoint throwe an exception when the return type is A, E, or exceptions are present.

IDoc Document / Document List

IDocs are XML documents defined by SAP. You can download their definition from your SAP server using the SAP UI.

<?xml version="1.0"?><ORDERS05>   <IDOC BEGIN="1">        <EDI_DC40 SEGMENT="1">          <TABNAM>EDI_DC40</TABNAM>           <MANDT>100</MANDT>          <DOCNUM>0000000000237015</DOCNUM>           <DOCREL>700</DOCREL>            <STATUS>30</STATUS>         <DIRECT>1</DIRECT>          <OUTMOD>2</OUTMOD>          <IDOCTYP>ORDERS05</IDOCTYP>         <MESTYP>ORDERS</MESTYP>         <STDMES>ORDERS</STDMES>         <SNDPOR>SAPB60</SNDPOR>         <SNDPRT>LS</SNDPRT>         <SNDPRN>B60CLNT100</SNDPRN>         <RCVPOR>MULE_REV</RCVPOR>           <RCVPRT>LS</RCVPRT>         <RCVPRN>MULESYS</RCVPRN>            <CREDAT>20110714</CREDAT>           <CRETIM>001936</CRETIM>         <SERIAL>20101221112747</SERIAL>     </EDI_DC40>     <E1EDK01 SEGMENT="1">           <ACTION>004</ACTION>            <CURCY>USD</CURCY>          <WKURS>1.06383</WKURS>          <ZTERM>0001</ZTERM>         <BELNR>0000000531</BELNR>           <VSART>01</VSART>           <VSART_BEZ>standard</VSART_BEZ>         <RECIPNT_NO>C02199</RECIPNT_NO>         <KZAZU>X</KZAZU>            <WKURS_M>0.94000</WKURS_M>      </E1EDK01>              ...             <E1EDS01 SEGMENT="1">           <SUMID>002</SUMID>          <SUMME>1470.485</SUMME>         <SUNIT>USD</SUNIT>      </E1EDS01>  </IDOC></ORDERS05>

Inbound Endpoint

The SAP inbound endpoint acts as RFC server or IDoc server. The JCo server needs to register against the SAP instance, and for this reason it requires both client and server configuration attributes.

Attribute Description Default Value

name

The reference name of the endpoint used internally by Mule configuration.

exchange-pattern

The available options are request-response and one-way.

address

The standard way to provide endpoint properties. For more information check: Endpoint Address.

type

The type of SAP object this endpoint processes (such as, function or idoc)

function

rfcType

The type of RFC the endpoint used to receive a function or IDoc. The available options are srfc (which is sync with no TID handler), trfc and qrfc (both of which are async, with a TID handler).

srfc

functionName

If the type is function then this is the name of the BAPI function that is handled. If no value is provided, then a generic handler is configured to receive all calls.

jcoClient

The SAP client. This is usually a number (For example: 100)

jcoUser

The logon user for password-based authentication.

jcoPasswd

The logon password associated with the logon user for password based authentication.

jcoLang

The logon language., If not defined, the default user language is used.

en

jcoAsHost

The SAP application server host. (Use either the IP address or server name).

jcoSysnr

The SAP system number.

jcoPoolCapacity

The maximum number of idle connections kept open by the destination. No connection pooling takes place when the value is 0.

5

jcoPeakLimit

The maximum number of simultaneously active connections that can be created for a destination.

10

jcoClientExtendedProperties-ref

A reference to java.util.Map, which contains additional JCo connection parameters for the client connection.

jcoGwHost

The gateway host on which the server should be registered.

jcoGwService

The gateway service, i.e. the port on which registration is performed.

jcoProgramId

The program ID with which the registration is performed.

jcoConnectionCount

The number of connections that should be registered at the gateway.

2

jcoClientExtendedProperties-ref

A Reference to java.util.Map, which contains additional JCo connection parameters. Additional information and a complete list of parameters can be found here.

Example

<sap:inbound-endpoint exchange-pattern="request-response" type="function" rfcType="srfc"  jcoGwHost="gateway-host" jcoGwService="gateway-service" jcoProgramId="program_id"   jcoConnectionCount="2" functionName="BAPI_FUNCTION_NAME" jcoServerExtendedProperties-ref="mapWithServerProperties"/>

Output Mule Message

The inbound-endpoint generates a Mule Message with the following contents:

  • Payload: A org.mule.transport.sap.SapObject instance. This is a Java POJO whose two main properties are:

    • type: SapType.FUNCTION or SapType.IDOC, depending on whether a BAPI call or an IDoc is being received.

    • value: The type depends on the specific JCo Object: com.sap.conn.idoc.IDocDocument or com.sap.conn.idoc.IDocDocumentList for IDocs and com.sap.conn.jco.JCoFunction for BAPI calls.

The payload can be transformed into an XML Definition with the following transformer: <sap:object-to-xml/>

Receiving IDocs

To configure a IDoc Server, you need to complete the following steps:

  1. Set the type parameter to idoc.

  2. Define the rfcType parameter as trfc or qrfc (IDocs are asychronous by definition, so they cannot be received over srfc).

  3. Configuring the TID Handler. (The default is an in-memory TID handler).

  4. Specify the following required attributes: jcoGwHost, jcoGwService, jcoProgramId.

  5. Specify required connection attributes, as necessary, for the endpoint or the connector. This might include, for example, jcoClient, jcoUser, jcoPasswd, jcoAsHost, jcoSysnr.

A Sample IDoc Server Configuration

<mule>   ... <sap:connector name="SapConnector" jcoClient="100" jcoUser="mule_user" jcoPasswd="secret" jcoLang="en"       jcoAsHost="sap-as.mulesoft.com" jcoSysnr="00" jcoTrace="true" jcoPoolCapacity = "3" jcoPeakLimit="10"       jcoClientExtendedProperties-ref="sapProperties"/>    ... <flow name="sapExample">        <sap:inbound-endpoint name="sapInbound" exchange-pattern="request-response" type="idoc"          rfcType="trfc" jcoGwHost="sapgw.mulesoft.com" jcoProgramId="idoc_send" jcoGwService="sapgw00"           jcoConnectionCount="2" jcoClientExtendedProperties-ref="sapProperties">                          <sap:default-in-memory-tid-store/>      </sap:inbound-endpoint>     ... </flow></mule>

Receiving BAPI calls

To configure a BAPI RFC Server you must complete the following steps:

  1. Set the type parameter to function.

  2. Define the rfcType parameter to trfc, qrfc or srfc. If rfcType is not specified, srfc is used by default).

  3. If rfcType is trfc or qrfc, then you may also need to Configuring the TID Handler

  4. Specify the following required attributes: jcoGwHost, jcoGwService, jcoProgramId

  5. Specify the required connection attributes, as necessary, for the endpoint or the connector. This might include, for example, jcoClient, jcoUser, jcoPasswd, jcoAsHost, jcoSysnr.

A Sample BAPI RFC Server Configuration

<mule>    ... <sap:connector name="SapConnector" jcoClient="100" jcoUser="mule_test" jcoPasswd="secret" jcoLang="en" jcoAsHost="sapas.mulesoft.com"        jcoSysnr="00" jcoTrace="true" jcoPoolCapacity = "3" jcoPeakLimit="10" jcoClientExtendedProperties-ref="sapProperties"/>  ... <flow name="sapExample">        <sap:inbound-endpoint name="sapInbound" exchange-pattern="request-response" type="function" rfcType="trfc" jcoGwHost="sapas.mulesoft.com"            jcoProgramId="rfc_send" jcoGwService="sapgw00" jcoConnectionCount="2"/>      ... </flow></mule>

Configuring the TID Handler

The TID (Transaction ID) handler , an important component for tRFC and qRFC, ensures that Mule ESB does not process the same transaction twice.

The SAP Transport allows you to configure different TID stores:

  • In Memory TID Store: This default TID store facilitates the sharing of TIDs within the same Mule ESB instance. If the rfcType is tRFC or qRFC, and no TID store is configured, then this default store is used.

  • Mule Object Store TID Store: This wrapper uses existing Mule ESB object stores to store and share TIDs. If you need multiple Mule ESB server instances, you should configure a JDBC Object Store so that you can share TIDs among the instances.

Important

If the rfcType is configured to srfc, or it is not provided (thus defaulting to srfc), then no TID handler is configured. Furthermore, if a TID handler has been configured in the XML file, it’s ignored.

Example of a Default In-memory TID Store

To configure an In-memory TID Store successfully, you must understand the following:

  1. The In-memory TID Store won’t work as expected if you have multiple Mule ESB instances that share the same program id. (This is because the SAP gateway load-balances across all registered SAP servers that share the same program id).

  2. The rfcType in the <sap:inbound-endpoint …​/> should be trfc or qrfc

  3. Configuring the child element <sap:default-in-memory-tid-store/> is optional, since the in-memory handler is the option by default.

<?xml version="1.0" encoding="UTF-8"?><mule xmlns="http://www.mulesoft.org/schema/mule/core"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:spring="http://www.springframework.org/schema/beans"      xmlns:sap="http://www.mulesoft.org/schema/mule/sap"    xsi:schemaLocation="        http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.2/mule.xsd        http://www.mulesoft.org/schema/mule/sap http://www.mulesoft.org/schema/mule/sap/3.2/mule-sap.xsd        http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/3.2/mule-xml.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">    <!-- Configuration for both SAP & the TID Store -->    <spring:bean id="sapProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"      <spring:property name="ignoreUnresolvablePlaceholders" value="true" />        <spring:property name="location" value="classpath:sap.properties"/>    </spring:bean> <!-- SAP Connector -->    <sap:connector name="SapConnector" jcoClient="${sap.jcoClient}"      jcoUser="${sap.jcoUser}" jcoPasswd="${sap.jcoPasswd}" jcoLang="${sap.jcoLang}" jcoAsHost="${sap.jcoAsHost}"     jcoSysnr="${sap.jcoSysnr}" jcoTrace="${sap.jcoTrace}" jcoPoolCapacity="${sap.jcoPoolCapacity}" jcoPeakLimit="${sap.jcoPeakLimit}"/>      <flow name="idocServerFlow">        <sap:inbound-endpoint name="idocServer" exchange-pattern="request-response" type="idoc" rfcType="trfc" jcoGwHost="${sap.jcoGwHost}"                            jcoProgramId="${sap.jcoProgramId}" jcoGwService="${sap.jcoGwService}" jcoConnectionCount="${sap.jcoConnectionCount}">          <sap:default-in-memory-tid-store/>      </sap:inbound-endpoint>                     ...    </flow></mule>

A Sample JDBC-based Mule Object Store TID Store

To configure the Mule Object Store TID Store, complete the following steps:

  1. Configure the rfcType in the <sap:inbound-endpoint …​/> component as trfc or qrfc

  2. Configure the child element <sap:mule-object-store-tid-store>

  3. Configure a DataSource bean with Database Connection details.

  4. Configure a JDBC connector.

The child element of <sap:mule-object-store-tid-store> can be any of the supported Mule Object Stores.

This example illustrates how to configure a MySQL-based JDBC object store.

<?xml version="1.0" encoding="UTF-8"?><mule xmlns="http://www.mulesoft.org/schema/mule/core"      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"      xmlns:spring="http://www.springframework.org/schema/beans"      xmlns:sap="http://www.mulesoft.org/schema/mule/sap"      xmlns:jdbc="http://www.mulesoft.org/schema/mule/jdbc"    xsi:schemaLocation="        http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.2/mule.xsd        http://www.mulesoft.org/schema/mule/sap http://www.mulesoft.org/schema/mule/sap/3.2/mule-sap.xsd        http://www.mulesoft.org/schema/mule/jdbc http://www.mulesoft.org/schema/mule/jdbc/3.2/mule-jdbc.xsd        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">  <!-- Configuration for both SAP & TID Store -->    <spring:bean id="sapProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"      <spring:property name="ignoreUnresolvablePlaceholders" value="true" />        <spring:property name="location" value="classpath:sap.properties"/>    </spring:bean>    <spring:bean id="jdbcProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">        <spring:property name="location" value="classpath:jdbc.properties"/>    </spring:bean>   <!-- TID Store configuration -->    <spring:bean id="jdbcDataSource"         class="org.enhydra.jdbc.standard.StandardDataSource"        destroy-method="shutdown">        <spring:property name="driverName" value="${database.driver}"/>        <spring:property name="url" value="${database.connection}"/>    </spring:bean>    <jdbc:connector name="jdbcConnector" dataSource-ref="jdbcDataSource" queryTimeout="${database.query_timeout}">        <jdbc:query key="insertTID" value="insert into saptids (tid, context) values (?, ?)"/>        <jdbc:query key="selectTID" value="select tid, context from saptids where tid=?"/>        <jdbc:query key="deleteTID" value="delete from saptids where tid=?"/>    </jdbc:connector>    <!-- SAP Connector -->    <sap:connector name="SapConnector" jcoClient="${sap.jcoClient}"      jcoUser="${sap.jcoUser}" jcoPasswd="${sap.jcoPasswd}" jcoLang="${sap.jcoLang}" jcoAsHost="${sap.jcoAsHost}"     jcoSysnr="${sap.jcoSysnr}" jcoTrace="${sap.jcoTrace}" jcoPoolCapacity="${sap.jcoPoolCapacity}" jcoPeakLimit="${sap.jcoPeakLimit}"/>      <flow name="idocServerFlow">        <sap:inbound-endpoint name="idocServer" exchange-pattern="request-response" type="idoc" rfcType="trfc" jcoGwHost="${sap.jcoGwHost}"                            jcoProgramId="${sap.jcoProgramId}" jcoGwService="${sap.jcoGwService}" jcoConnectionCount="${sap.jcoConnectionCount}">          <sap:mule-object-store-tid-store>               <jdbc:object-store name="jdbcObjectStore" jdbcConnector-ref="jdbcConnector"                  insertQueryKey="insertTID"                  selectQueryKey="selectTID"                  deleteQueryKey="deleteTID"/>         </sap:mule-object-store-tid-store>        </sap:inbound-endpoint>        ...    </flow></mule>

Make sure to note the following points:

  1. Specific confguration attributes are store in two properties files: sap.properties and jdbc.properties.

  2. To configure more than one PropertyPlaceholder, the first one must have the property ignoreUnresolvablePlaceholders set to true. (i.e., <spring:property name="ignoreUnresolvablePlaceholders" value="true" />)

A Sample Database Creation Script for the JDBC Object Store

-- MySQL ScriptCREATE DATABASE saptid_db;GRANT ALL ON saptid_db.* TO 'sap'@'localhost' IDENTIFIED BY 'secret';GRANT ALL ON saptid_db.* TO 'sap'@'%' IDENTIFIED BY 'secret';USE saptid_db;CREATE TABLE saptids( tid VARCHAR(512) PRIMARY KEY,  context TEXT);

Outbound Endpoint

The SAP outbound endpoint executes functions (BAPIs) or send IDocs.

Attribute Description Default Value

name

The reference name of the endpoint used internally by mule configuration.

exchange-pattern

The available options are request-response and one-way.

address

The standard way to specify endpoint properties. For more information check: Endpoint Address.

type

The type of SAP object this endpoint is processing (function or idoc)

function

rfcType

Type of RFC the endpoint uses to execute a function or send and IDoc. Allowed values are srfc, trfc and qrfc

srfc

queueName

If the RFC type is qrfc, then this is the name of the queue.

functionName

When the type is function, this BAPI function is executed.

evaluateFunctionResponse

When the type is function, a true flag indicates that the SAP transport should evaluate the function response and throw and exception when an error occurs in SAP. When this flag is set to false, the SAP transport does not throw an exception when an error occurs, and the user is responsible of parsing the function response.

false

definitionFile

The path to the template definition file of either the function to be executed or the IDoc to be sent.

idocVersion

When the type is idoc, this version is used when sending the IDoc. Values for the IDoc version correspond to IDOC_VERSION_xxxx constants in com.sap.conn.idoc.IDocFactory

0 (IDOC_VERSION_DEFAULT).

jcoClient

The SAP client. This is usually a number (For example: 100).

jcoUser

The logon user for password-based authentication.

jcoPasswd

The password associated with the logon user for password-based authentication

jcoLang

The language used by the logon dialogs. When not defined, the default user language is used.

en

jcoAsHost

The SAP application server host (IP or server name).

jcoSysnr

The SAP system number.

jcoPoolCapacity

The maximum number of idle connections kept open by the destination. No connection pooling takes place when the value is 0.

5

jcoPeakLimit

The maximum number of active connections that can be created for a destination simultaneously

10

jcoClientExtendedProperties-ref

A reference to java.util.Map containing additional JCo connection parameters. Additional information and a complete list of parameters can be found here.

IDoc Versions

Value Description

0

IDOC_VERSION_DEFAULT

2

IDOC_VERSION_2

3

IDOC_VERSION_3

8

IDOC_VERSION_QUEUED

A Sample SAP Outbound Endpoint Configuration

<sap:outbound-endpoint exchange-pattern="request-response" type="function" rfcType="qrfc"    queueName="QRFC_QUEUE_NAME" functionName="BAPI_FUNCTION_NAME"    definitionFile="path/to/definition/file.xml"/>

Input Mule Messages

The outbound-endpoint expects a Mule Message carrying any of the following payloads:

  • org.mule.transport.sap.SapObject instance. This is a Java POJO, whose two main properties are:

    • type: SapType.FUNCTION (for a BAPI call) or SapType.IDOC (for an IDoc).

    • value: The specific JCo Object depends on the payload type: com.sap.conn.idoc.IDocDocument or com.sap.conn.idoc.IDocDocumentList for IDocs and com.sap.conn.jco.JCoFunction for BAPI calls.

  • Any other Object. You need to provide the XML definition with the attribute definitionFile or Embedding the XML Definition it in the XML.

The payload can be transformed from a XML Definition into a SapObject with the following transformers:

<!-- IDocs --><sap:xml-to-idoc/>

<!-- BAPI calls --><sap:xml-to-function/>

Embedding the XML Definition

As an alternative to providing the SAP object definition in a file (through the definitionFile attribute), the XML definition can be embedded inside the sap:outbound-endpoint element by using the
sap:definition element. As the definition is an XML fragment, it has to be provided inside a CDATA section.

<sap:outbound-endpoint ...> <sap:definition>        <![CDATA[        <jco>         <import>          <structure name="POHEADER">           <field name="COMP_CODE">#[payload.value1]</field>           <field name="DOC_TYPE">#[header:value2]</field>             <field name="VENDOR">#[bean:value3]</field>             <field name="PURCH_ORG">#[xpath://path/to/value4]</field>         </structure>          </import>     </jco>      ]]>  </sap:definition></sap:outbound-endpoint>

Executing functions

There are different ways to execute a function:

  1. Create an instance of com.sap.conn.jco.JCoFunction and send it as the payload to the SAP outbound-endpoint. In this case, the following attributes is ignored:type, functionName, definition, definitionFile. You can create the JCoFunction object in a Java component or Script for example.

  2. Generate the XML definition for the JCoFunction and send it as the payload (i.e., in one of these formats: InputStream, byte[], or String) to the SAP outbound-endpoint through the <xml-to-function/> transformer. In this case, if the function name is provided in the XML definition, it overrides the value in the attribute functionName. The following attributes are also ignored: type, definition, definitionFile.

  3. Configure definitionFile or embed the XML definition in the SAP outbound-endpoint (If both are configured, then the contents of the definitionFile override the embedded XML definition). The type attribute should be set to function. In this case, if the function name is provided in the XML definition, it overrides the value in the attribute functionName. The XML definition file may contain Mule Expressions that can be substituted at runtime with values present in the Mule Event (payload, headers, global properties, beans, etc.)

Invocation of a function results in a JCoFunction object. The Mule SAP outbound-endpoint wraps this object inside org.mule.transport.sap.SapObject. You can access the response JCoFunction object by invoking the getValue method.

You can also use the <object-to-xml/> transformer to get the XML representation of the JCoFunction.

Examples

XML input and XML output

Example notes:

  1. Input is received as an XML document that uses the tag <jco name="BAPI_NAME"> to specify the BAPI to be called.

  2. The function output is transformed into a XML document.

  3. If the execution of the BAPI by SAP produces an error, an exception is raised from the outbound endpoint (because evaluateFunctionResponse is true).

<mule>    ... <sap:connector name="SapConnector" jcoClient="100" jcoUser="mule_test" jcoPasswd="secret" jcoLang="en" jcoAsHost="sapas.mulesoft.com"        jcoSysnr="00" jcoTrace="true" jcoPoolCapacity = "3" jcoPeakLimit="10" jcoClientExtendedProperties-ref="sapProperties"/>  ... <flow name="sapExample">        ...     <xml-to-function/>      <sap:outbound-endpoint name="sapOutbound" exchange-pattern="request-response" type="function" rfcType="srfc" evaluateFunctionResponse="true"/>      <object-to-xml/>        ... </flow></mule>

A Sample of an Embedded XML Definition using Mule Expressions

Example notes:

  1. The payload is a Java object. (For this example, let’s assume it has a property name is_value1_).

  2. The function output is transformed into a XML document

  3. The name of the BAPI function to be executed is BAPI_PO_CREATE1

  4. Inside the definition, you can see various Mule Expressions

<mule>  ... <sap:connector name="SapConnector" jcoClient="100" jcoUser="mule_test" jcoPasswd="secret" jcoLang="en" jcoAsHost="sapas.mulesoft.com"        jcoSysnr="00" jcoTrace="true" jcoPoolCapacity = "3" jcoPeakLimit="10" jcoClientExtendedProperties-ref="sapProperties"/>  ... <flow name="sapExample">        <!-- Load values into Mule Message -->        ...             <sap:outbound-endpoint exchange-pattern="request-response" type="function" functionName="BAPI_PO_CREATE1">          <sap:definition>                <![CDATA[                <jco>                 <import>                  <structure name="POHEADER">                   <field name="COMP_CODE">#[payload.value1]</field>                   <field name="DOC_TYPE">#[header:value2]</field>                     <field name="VENDOR">#[bean:value3]</field>                     <field name="PURCH_ORG">#[xpath://path/to/value4]</field>                 </structure>                  </import>             </jco>              ]]>          </sap:definition>       </sap:outbound-endpoint>        <sap:object-to-xml/>        ...     <!-- Process XML result -->           </flow></mule>

Sending IDocs

There are different ways to send an IDoc:

  1. Create an instance of com.sap.conn.idoc.IDocDocument or com.sap.conn.idoc.IDocDocumentList and send it as the payload to the SAP outbound-endpoint. In this case the following attributes is ignored: type, definition, definitionFile. You can create the IDoc document object in a Java component or Script for example.

  2. Generate the XML definition for the IDoc and send it as the payload (InputStream, byte[] or String) to the SAP outbound-endpoint through the <xml-to-idoc/> transformer. In this case the following attributes is ignored: type, definition, definitionFile.

  3. Configure definitionFile or embed the XML definition in the SAP outbound-endpoint (If both are configured then the contents of the definitionFile overrides the embedded XML definition). The type attribute should be set to idoc. In this case the XML definition file may contain Mule Expressions that can be substituted in runtime with values present in the Mule Event (payload, headers, global properties, beans, etc.)

Reading a file that represents an IDoc (XML Document)

Example notes:

  1. This example polls the directory C:/sap-test/in for IDocs XML documents, then sends them to SAP.

  2. Extended properties are defined in the map sapProperties.

  3. The outbount endpoint is configured with the address attribute.

  4. The transformer <sap:xml-to-idoc /> receives a Stream, then transforms it into a SAP Object that the endpoint can process.

<?xml version="1.0" encoding="UTF-8"?><mule xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    xmlns:spring="http://www.springframework.org/schema/beans" xmlns:sap="http://www.mulesoft.org/schema/mule/sap"  xmlns:file="http://www.mulesoft.org/schema/mule/file" xsi:schemaLocation="       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd       http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/3.2/mule.xsd       http://www.mulesoft.org/schema/mule/file http://www.mulesoft.org/schema/mule/file/3.2/mule-file.xsd       http://www.mulesoft.org/schema/mule/sap http://www.mulesoft.org/schema/mule/sap/3.2/mule-sap.xsd">  <spring:bean name="sapProperties" class="java.util.HashMap">        <spring:constructor-arg>            <spring:map>                <spring:entry key="jco.server.unicode" value="1" />         </spring:map>       </spring:constructor-arg>   </spring:bean>  <sap:connector name="SapConnector" jcoSysnr="00" jcoPeakLimit="10"       jcoClientExtendedProperties-ref="sapProperties" />   <file:connector name="FileConnector" moveToDirectory="C:/sap-test/bk"        moveToPattern="#[function:datestamp]-#[header:originalFilename]"        streaming="false" /> <flow name="sapExample">        <file:inbound-endpoint address="file://C:/sap-test/in" />       <sap:xml-to-idoc />     <sap:outbound-endpoint           address="sap://mule_user:password@sapas.mulesoft.com:00?lang=en&amp;jcoClient=100&amp;jcoTrace=false&amp;jcoPoolCapacity=100"           exchange-pattern="request-response" type="idoc"/>    </flow></mule>

Transactions

The SAP transport, which is based on JCo, doesn’t support distributed transactions because JCo doesn’t support XA.

The SAP outbound endpoint supports the child element transaction:

<sap:transaction action="ALWAYS_BEGIN" bapiTransaction="true|false"/>
Attribute Description Default Value

action

The action attribute is part of the Mule ESB transaction standard and can have the following values: NONE, ALWAYS_BEGIN, BEGIN_OR_JOIN, ALWAYS_JOIN and JOIN_IF_POSSIBLE

bapiTransaction

When set to true , either BAPI_TRANSACTION_COMMIT or BAPI_TRANSACTION_ROLLBACK is called at the end of the transaction, depending on the result of that transaction.

false

For more information, consult: [Transactions Configuration Reference].

Combining the RFC type (rfcType) attribute defined in the outbound endpoint with the transaction facilitates different ways for the SAP transport to handle the transaction.

sRFC stateful

Configuration

<sap:outbound-endpoint    exchange-pattern="request-response" type="function" rfcType="srfc" ...>      <sap:transaction action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" bapiTransaction="false"/>    </sap:outbound-endpoint>

Stateful calls are used to call more than one BAPI in SAP using the same context. If the execution of calling these BAPIs take place in the same thread, then this is equivalent in JCo to:

JCoContext.begin(destination);function1.execute(destination);function2.execute(destination);function3.execute(destination);JCoContext.end(destination);

sRFC stateful BAPI transaction

Configuration

<sap:outbound-endpoint  exchange-pattern="request-response" type="function" rfcType="srfc" ...>      <sap:transaction action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" bapiTransaction="true"/> </sap:outbound-endpoint>

If the BAPIs that are called change values in SAP tables, then a call to a special BAPI is required: BAPI_TRANSACTION_COMMIT or BAPI_TRANSACTION_ROLLBACK. For this to work, the whole unit of work needs to be in the same Thread and the calls need to be stateful. The JCo code to implement this is:

commitFunction = createJCoFunction("BAPI_TRANSACTION_COMMIT");rollbackFunction = createJCoFunction("BAPI_TRANSACTION_ROLLBACK");try{    JCoContext.begin(destination);    function1.execute(destination);    function2.execute(destination);    commitFunction.execute(destination);}catch(Exception ex){    rollbackFunction.execute(destination);}finally{    JCoContext.end(destination);}

tRFC stateful

Configuration

<sap:outbound-endpoint  exchange-pattern="request-response" type="function" rfcType="trfc" ...>      <sap:transaction action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" bapiTransaction="false"/>    </sap:outbound-endpoint>

The JCo code to invoke BAPIs through tRFC looks like this:

String tid = destination.creatTID();try{    JCoContext.begin(destination, tid);    function1.execute(destination, tid);    function2.execute(destination, tid);}finally{    JCoContext.end(destination);}

qRFC stateful

Configuration

<sap:outbound-endpoint    exchange-pattern="request-response" type="function" rfcType="qrfc"  queueName="QUEUE_NAME" ...>      <sap:transaction action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" bapiTransaction="false"/>    </sap:outbound-endpoint>

To invoke BAPIs through qRFC, you need to provide a value for the attribute queueName. The JCo code to implement this is:

String tid = destination.creatTID();try{    JCoContext.begin(destination, tid);    function1.execute(destination, tid, queueName1);    function2.execute(destination, tid, queueName2);}finally{    JCoContext.end(destination);}

Important

If a transaction is not specified, then all calls (execute function or send IDoc) are stateless.

Transformers

  1. <sap:xml-to-function/>

  2. <sap:xml-to-idoc/>

  3. <sap:object-to-xml/>

Troubleshooting

Checking log files

Mule ESB stores log files (which are store on a per application basis) in the $MULE_HOME\logs directory:

  • mule.log: Default Mule ESB log file

  • mule-app-YOUR_APP_NAME.log: Per application log file

Enabling JCo trace

JCo Trace can be enabled from outside Mule ESB; it values to the following java startup environment properties:

  • -Djco.trace_level=N (where 0 ⇐ N ⇐ 10, with 10 = most detailed trace)

  • -Djco.trace_path=<PATH> (optional)

For more information, consult the JCo documentation.

To enable traceat Connector level, complete the following steps”:

  1. Set the attribute jcoTrace to true or provide the extended JCo property jco.client.trace or jco.server.trace with value 1.

  2. Provide a value for -Djco.trace_level=N at Mule ESB startup. Permissible levels are [0 .. 10]. The most commonly used levels are:

    • 0 - nothing

    • 1 - errors and warnings

    • 2 - execution path, errors, and warnings

    • 3 - full execution path, errors, and warnings

    • 4 - execution path, info messages, errors, and warnings

    • 6 - full execution path, info messages, errors, and warnings

    • 7 - debug messages, full execution path, info messages, errors, and warnings

    • 8 - verbose debug messages, full execution path, info messages, errors, and warnings

  3. Optionally, you can provide a value for -Djco.trace_path=<PATH>. This is supposed to be the complete path to an existing directory where trace files are stored, but there other special values can be applied:

    • stdout - JCo trace information is sent to standard output stream

    • stderr - JCo trace information is sent to standard error stream

If -Djco.trace_path is not set, then trace files are stored in the working directory. For Mule ESB standalone, this is usually the $MULE_HOME/bin folder.

Common errors

IDOC_ERROR_METADATA_UNAVAILABLE

RfcException: [mc-vmware|a_rfc] message: (3) IDOC_ERROR_METADATA_UNAVAILABLE: The meta data for the IDoc type "??????????????????????????å å" with extension "  ORDSAPB6L B60CL          ???" is unavailable.    Return code: RFC_FAILURE(1)    error group: 104    key: RFC_ERROR_SYSTEM_FAILURE

The RFC destination should support Unicode. You can implement this in SAP with transaction SM59.

SAP Transport cannot join transaction of type [org.mule.TransactionClass].

The action of type [srfc|trfc|qrfc] is stateless, because SAP Transport doesn’t support Multi Transactions for the moment.

Missing transaction handler.

[10-11 08:02:26] ERROR SapJcoServerDefaultListener [JCoServerThread-1]: Exception occured on idoc_send connection 3-10.30.9.26|sapgw00|idoc_send: check TID fault: No transaction handler is installed. Unable to process tRFC/qRFC requests.RfcException: [mule.local|MULESOFT_IDOC_SEND_TEST]    message: check TID fault: No transaction handler is installed. Unable to process tRFC/qRFC requests.    Return code: RFC_FAILURE(1)    error group: 104    key: RFC_ERROR_SYSTEM_FAILUREException raised by myhost.com.ar|MULESOFT_IDOC_SEND_TEST  at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcServer.playbackTRfc(MiddlewareJavaRfc.java:2625)    at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcServer.handletRfcRequest(MiddlewareJavaRfc.java:2546)   at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcServer.listen(MiddlewareJavaRfc.java:2367)  at com.sap.conn.jco.rt.DefaultServerWorker.dispatch(DefaultServerWorker.java:284)   at com.sap.conn.jco.rt.DefaultServerWorker.loop(DefaultServerWorker.java:369)   at com.sap.conn.jco.rt.DefaultServerWorker.run(DefaultServerWorker.java:245)    at java.lang.Thread.run(Thread.java:680)

If you are getting the message: No transaction handler is installed. Unable to process tRFC/qRFC requests then you may need to set the rfcType has to be trfc or qrfc in the <sap:inbound-endpoint />

Parameter 'parameter name' not supported

SAP extended properties (configure in a Map bean or as endpoint address parameters) should have valid names. If you provide an invalid property name you get an error message similar to:

Root Exception stack trace:RfcException: [null]    message: Parameter 'type' not supported: 'f'    Return code: RFC_INVALID_PARAMETER(19)    error group: 101    key: RFC_ERROR_PROGRAM at com.sap.conn.rfc.api.RfcOptions.checkParameters(RfcOptions.java:182) at com.sap.conn.jco.rt.MiddlewareJavaRfc$JavaRfcClient.connect(MiddlewareJavaRfc.java:1328) at com.sap.conn.jco.rt.ClientConnection.connect(ClientConnection.java:731)    + 3 more (set debug level logging or '-Dmule.verbose.exceptions=true' for everything)

In this example, JCo libraries are informing that the parameter with name type is not valid. The complete list of valid property names can be found here.