Nav
You are viewing an older version of this section. Click here to navigate to the latest version.

SAP Connector Advanced Features

JCo Extended Properties

The SAP connector provides a wide set of additional JCo properties allowing the user to configure the connection at the connector or endpoint level, inside the mule-config.xml file.

The key names for these properties must match those expected by the JCo libraries. You can check them at SAP Client Properties and SAP Server Properties.

         
      
1
2
3
4
5
6
7
8
9
10
<spring:bean name="sapProperties" class="java.util.HashMap">
        <spring:constructor-arg>
            <spring:map>
                <spring:entry key="jco.client.client" value="100"/>
                <spring:entry key="jco.client.user" value="SAP_USER"/>
                <spring:entry key="jco.client.sysnr" value="00"/>
                ...
            </spring:map>
        </spring:constructor-arg>
    </spring:bean>

These properties can be used inside the connector or endpoint elements by referencing a Spring Bean that contains a map with the extended attributes. This can be done by configuring the jcoClientExtendedProperties-ref (inbound and outbound) or jcoServerExtendedProperties-ref (inbound only):


         
      
1
2
3
4
5
6
7
8
9
10
11
12
<!-- connector -->
<sap:connector name="SapConnector" jcoClientExtendedProperties-ref="sapProperties" ... />

<!-- outbound - client props -->
<sap:outbound-endpoint connector-ref="sapConnector" jcoClientExtendedProperties-ref="sapProperties" ... />

<!-- inbound - client props -->
<sap:inbound-endpoint connector-ref="sapConnector" jcoClientExtendedProperties-ref="sapProperties" ... />

<!-- inbound - server props -->
<sap:inbound-endpoint connector-ref="sapConnector" jcoServerExtendedProperties-ref="sapProperties" ... />

The extended attributes can be configured in one of two ways (or using both methods combined):

  1. As plain text, setting them directly to the JCo libraries. For example, boolean values must be represented by the string "0" (false) or "1" (true).

    <spring:entry key="jco.client.mysapsso2" value="MY_SSO_USER"/>
    <spring:entry key="jco.client.snc_mode" value="1"/>
  2. Using MEL expressions for each attribute (only supported since version 2.3.0 of the SAP Connector).

    <spring:entry key="jco.client.mysapsso2" value="#[flowVars.mySSOToken]"/>

Also, keep in mind the following:

  • the properties defined at connector or endpoint level will override the values in the properties map.

  • the properties defined at endpoint level will override the ones from the connector.

JCo Client Properties

These are the properties that can be used inside the map-referenced attribute jcoClientExtendedProperties-ref at connector or endpoint level (both inbound and outbound).

For an updated and complete list, check the Javadocs for com.sap.conn.jco.ext.DestinationDataProvider inside your JCo distribution.

You can also check the online documentation.

SAP Property Description Mule Config Attribute Default Value

jco.client.client

SAP client

jcoClient

jco.client.user

Logon user

jcoUser

jco.client.alias_user

Alias user name

jco.client.passwd

Logon password

jcoPasswd

jco.client.lang

Logon language

jcoLang

jco.client.sysnr

SAP system number

jcoSysnr

jco.client.ashost

SAP application server

jcoAsHost

jco.client.mshost

SAP message server

jco.client.gwhost

Gateway host

jco.client.gwserv

Gateway service

jco.client.r3name

R/3 name

jco.client.group

Group of SAP application servers

jco.client.tpname

Program ID of external server program

jco.client.tphost

Host of external server program

jco.client.type

Type of remote host 2 = R/2, 3 = R/3, E = External

jco.client.trace

Enable/disable RFC trace (0 or 1)

jcoTrace

jco.client.codepage

Initial codepage in SAP notation

jco.client.abap_debug

Enable ABAP debugging 0 or 1

jco.client.use_sapgui

Use remote SAP graphical user interface (0/1/2)

jco.client.getsso2

Get/Don’t get a SSO ticket after logon (1 or 0)

jco.client.mysapsso2

Use the specified SAP Cookie Version 2 as logon ticket

jco.client.x509cert

Use the specified X509 Certificate as logon ticket

jco.client.lcheck

Enable/Disable logon check at open time, 1 (enable) or 0 (disable)

jco.client.grt_data

Additional data for GUI

jco.client.use_guihost

Host to which to redirect the remote GUI

jco.client.use_guiserv

Service to which to redirect of the remote GUI

jco.client.use_guiprogid

Program ID of the server which starts the remote GUI

jco.client.snc_mode

Secure Network Connection (SNC) mode, 0 (off) or 1 (on)

jco.client.snc_partnername

SNC partner. For example, p:CN=R3, O=XYZ-INC, C=EN

jco.client.snc_qop

SNC level of security, 1 to 9

jco.client.snc_myname

SNC name. Overrides default SNC partner

jco.client.snc_lib

Path to library which provides SNC service.

jco.client.dest

R/2 destination

jco.client.saplogon_id

String defined for SAPLOGON on 32-bit Windows

jco.client.extiddata

Data for external authentication (PAS)

jco.client.extidtype

Type of external authentication (PAS)

jco.client.dsr

Enable/Disable dsr support (0 or 1)

jco.client.deny_initial_password

Deny usage of initial passwords (0 default or 1)

jco.destination.peak_limit

Maximum number of active connections that can be created for a destination, simultaneously

jcoPeakLimit

jco.destination.pool_capacity

Maximum number of idle connections kept open by the destination. A value of 0 has the effect that there is no connection pooling.

jcoPoolCapacity

jco.destination.expiration_time

Time in ms after that the connections hold by the internal pool can be closed.

jco.destination.expiration_check_period

Interval in ms the timeout checker thread uses to check the connections in the pool for expiration

jco.destination.max_get_client_time

Max time in ms to wait for a connection, if the max allowed number of connections is allocated by the application.

jco.destination.repository_destination

Specifies the destination to be used as a repository, i.e. use this destination’s repository.

jco.destination.repository.user

Optional: if repository destination is not set, and this property is set, it will be considered as user for repository calls. This allows use of a different user for repository lookups.

jco.destination.repository.passwd

The password for a repository user. Mandatory, if a repository user should be used.

jco.destination.repository.snc_mode

Optional: if SNC is used for this destination, it is possible to turn it off for repository connections, if this property is set to 0. Defaults to the value of jco.client.snc_mode.

jco.destination.one_roundtrip_repository

1 = force usage of RFC_METADTA_GET in SAP Server, 0 = deactivate it. If not set, the destination will make initially a remote call to check if RFC_METADATA_GET is available.

Prioritizing Connection Properties

Properties for SAP connections, both inbound and outbound, can be configured in numerous places, which may cause an overlap of connection parameters. The following list details the priorities accorded to values specified in different places, with the highest priority level listed first.

  1. Attributes defined at the SAP Inbound Endpoint and SAP Outbound Endpoint level, such as User, Password, Gateway Host, etc.

  2. Properties in the Address attribute at the SAP Inbound Endpoint and SAP Outbound Endpoint levels. (However, MuleSoft does not recommend using the Address attribute for SAP connections.)

  3. Properties inside the Map configured in the Extended Properties pane for the JCo client or server at the SAP Inbound Endpoint and SAP Outbound Endpoint levels.

  4. Attributes configured at the SAP Connector Configuration level (that is, AS Host, User, Password, SAP Client, etc).

  5. Properties inside the Map configured in the Extended Properties pane at the SAP Connector Configuration level.

  6. Default values.

JCo Server Properties

These properties can be used inside the map-referenced attribute jcoServerExtendedProperties-ref at inbound-endpoint level.

For an updated and complete list, check the Javadocs for com.sap.conn.jco.ext.ServerDataProvider inside your JCo distribution zip file.

You can also check the online documentation.

SAP Property Description Mule Config Attribute Default Value

jco.server.gwhost *

Gateway host server should be registered on

jcoGwHost

 

jco.server.gwserv *

Gateway service, i.e. the port registration can be performed on

jcoGwService

 

jco.server.progid *

The program ID registration is performed with.

jcoProgId

 

jco.server.connection_count *

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

jcoConnectionCount

2

jco.server.saprouter

SAP router string to use for a system protected by a firewall.

 

jco.server.max_startup_delay

The maximum time (in seconds) between two startup attempts, if a failure occurs.

 

jco.server.repository_destination

Client destination from which to obtain the repository.

 

jco.server.repository_map

Repository map, if more than one repository should be used by JCoServer.

 

jco.server.trace

Enable/disable RFC trace (0 or 1).

 

jco.server.worker_thread_count

Set the number of threads that can be used by the JCoServer instance.

 

jco.server.worker_thread_min_count

Set the number of threads the JCoServer should always keep running.

 

jco.server.snc_mode **

Secure Network Connection (SNC) mode, 0 (off) or 1 (on).

 

jco.server.snc_qop **

SNC level of security, 1 to 9.

 

jco.server.snc_myname **

SNC name of your server. Overrides the default SNC name. Typically this is something like p:CN=JCoServer, O=ACompany, C=EN.

 

jco.server.snc_lib **

Path to library which provides SNC service.

 

(*) optional parameters
(**) SNC parameters — required only if snc_mode is ON

Server Services Configuration

If you want to receive IDocs or be called as a BAPI but do NOT want to use the PORT number as the value for jcoGwService, then you will have to modify the Operating System services file:

  • Unix based systems → /etc/services

  • Windows → C:\WINDOWS\system32\drivers\etc\services

JCo requires this configuration in order to initialize the JCo Server, which must communicate with the SAP Gateway.

You can access the SAP Gateway on every application server using the TCP port sapgw{nr}, where {nr} is the instance number of the application instance.

You will need to add that SAP Gateway entry in the services file. So, for example, if you are trying to reach SAP instance 21, you will need to add:

sapgw21  3321/tcp

Complete SAP Services List

Port 3300 is predefined by SAP. 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 below:

Services Mappings

               
            
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
sapdp00  3200/tcp
sapdp01  3201/tcp
sapdp02  3202/tcp
sapdp03  3203/tcp
sapdp04  3204/tcp
sapdp05  3205/tcp
sapdp06  3206/tcp
sapdp07  3207/tcp
sapdp08  3208/tcp
sapdp09  3209/tcp
sapdp10  3210/tcp
sapdp11  3211/tcp
sapdp12  3212/tcp
sapdp13  3213/tcp
sapdp14  3214/tcp
sapdp15  3215/tcp
sapdp16  3216/tcp
sapdp17  3217/tcp
sapdp18  3218/tcp
sapdp19  3219/tcp
sapdp20  3220/tcp
sapdp21  3221/tcp
sapdp22  3222/tcp
sapdp23  3223/tcp
sapdp24  3224/tcp
sapdp25  3225/tcp
sapdp26  3226/tcp
sapdp27  3227/tcp
sapdp28  3228/tcp
sapdp29  3229/tcp
sapdp30  3230/tcp
sapdp31  3231/tcp
sapdp32  3232/tcp
sapdp33  3233/tcp
sapdp34  3234/tcp
sapdp35  3235/tcp
sapdp36  3236/tcp
sapdp37  3237/tcp
sapdp38  3238/tcp
sapdp39  3239/tcp
sapdp40  3240/tcp
sapdp41  3241/tcp
sapdp42  3242/tcp
sapdp43  3243/tcp
sapdp44  3244/tcp
sapdp45  3245/tcp
sapdp46  3246/tcp
sapdp47  3247/tcp
sapdp48  3248/tcp
sapdp49  3249/tcp
sapdp50  3250/tcp
sapdp51  3251/tcp
sapdp52  3252/tcp
sapdp53  3253/tcp
sapdp54  3254/tcp
sapdp55  3255/tcp
sapdp56  3256/tcp
sapdp57  3257/tcp
sapdp58  3258/tcp
sapdp59  3259/tcp
sapdp60  3260/tcp
sapdp61  3261/tcp
sapdp62  3262/tcp
sapdp63  3263/tcp
sapdp64  3264/tcp
sapdp65  3265/tcp
sapdp66  3266/tcp
sapdp67  3267/tcp
sapdp68  3268/tcp
sapdp69  3269/tcp
sapdp70  3270/tcp
sapdp71  3271/tcp
sapdp72  3272/tcp
sapdp73  3273/tcp
sapdp74  3274/tcp
sapdp75  3275/tcp
sapdp76  3276/tcp
sapdp77  3277/tcp
sapdp78  3278/tcp
sapdp79  3279/tcp
sapdp80  3280/tcp
sapdp81  3281/tcp
sapdp82  3282/tcp
sapdp83  3283/tcp
sapdp84  3284/tcp
sapdp85  3285/tcp
sapdp86  3286/tcp
sapdp87  3287/tcp
sapdp88  3288/tcp
sapdp89  3289/tcp
sapdp90  3290/tcp
sapdp91  3291/tcp
sapdp92  3292/tcp
sapdp93  3293/tcp
sapdp94  3294/tcp
sapdp95  3295/tcp
sapdp96  3296/tcp
sapdp97  3297/tcp
sapdp98  3298/tcp
sapdp99  3299/tcp
sapgw00  3300/tcp
sapgw01  3301/tcp
sapgw02  3302/tcp
sapgw03  3303/tcp
sapgw04  3304/tcp
sapgw05  3305/tcp
sapgw06  3306/tcp
sapgw07  3307/tcp
sapgw08  3308/tcp
sapgw09  3309/tcp
sapgw10  3310/tcp
sapgw11  3311/tcp
sapgw12  3312/tcp
sapgw13  3313/tcp
sapgw14  3314/tcp
sapgw15  3315/tcp
sapgw16  3316/tcp
sapgw17  3317/tcp
sapgw18  3318/tcp
sapgw19  3319/tcp
sapgw20  3320/tcp
sapgw21  3321/tcp
sapgw22  3322/tcp
sapgw23  3323/tcp
sapgw24  3324/tcp
sapgw25  3325/tcp
sapgw26  3326/tcp
sapgw27  3327/tcp
sapgw28  3328/tcp
sapgw29  3329/tcp
sapgw30  3330/tcp
sapgw31  3331/tcp
sapgw32  3332/tcp
sapgw33  3333/tcp
sapgw34  3334/tcp
sapgw35  3335/tcp
sapgw36  3336/tcp
sapgw37  3337/tcp
sapgw38  3338/tcp
sapgw39  3339/tcp
sapgw40  3340/tcp
sapgw41  3341/tcp
sapgw42  3342/tcp
sapgw43  3343/tcp
sapgw44  3344/tcp
sapgw45  3345/tcp
sapgw46  3346/tcp
sapgw47  3347/tcp
sapgw48  3348/tcp
sapgw49  3349/tcp
sapgw50  3350/tcp
sapgw51  3351/tcp
sapgw52  3352/tcp
sapgw53  3353/tcp
sapgw54  3354/tcp
sapgw55  3355/tcp
sapgw56  3356/tcp
sapgw57  3357/tcp
sapgw58  3358/tcp
sapgw59  3359/tcp
sapgw60  3360/tcp
sapgw61  3361/tcp
sapgw62  3362/tcp
sapgw63  3363/tcp
sapgw64  3364/tcp
sapgw65  3365/tcp
sapgw66  3366/tcp
sapgw67  3367/tcp
sapgw68  3368/tcp
sapgw69  3369/tcp
sapgw70  3370/tcp
sapgw71  3371/tcp
sapgw72  3372/tcp
sapgw73  3373/tcp
sapgw74  3374/tcp
sapgw75  3375/tcp
sapgw76  3376/tcp
sapgw77  3377/tcp
sapgw78  3378/tcp
sapgw79  3379/tcp
sapgw80  3380/tcp
sapgw81  3381/tcp
sapgw82  3382/tcp
sapgw83  3383/tcp
sapgw84  3384/tcp
sapgw85  3385/tcp
sapgw86  3386/tcp
sapgw87  3387/tcp
sapgw88  3388/tcp
sapgw89  3389/tcp
sapgw90  3390/tcp
sapgw91  3391/tcp
sapgw92  3392/tcp
sapgw93  3393/tcp
sapgw94  3394/tcp
sapgw95  3395/tcp
sapgw96  3396/tcp
sapgw97  3397/tcp
sapgw98  3398/tcp
sapgw99  3399/tcp

Endpoint Address

The SAP Connector supports a URI-style address to enable the use of dynamic endpoints, whose 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.

  • Specific SAP connection properties. For example, jco.client.r3name, jco.client.type.

Whenever attributes 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.

Inbound Endpoint Address


          
       
1
2
<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"/>

Outbound Endpoint Address


          
       
1
2
<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"/>
You must “escape” the ampersand ('&') in the address attribute, replacing it with &.

Clustered Environments Configuration

The SAP connector is Mule HA ready, meaning that it can work in a Mule Cluster without any issues. However, depending on the application architecture, you may need to configure your SAP endpoints accordingly.

The key to a fully working application in cluster is the implementation of reliability patterns.

Outbound Endpoint

The outbound endpoint is usually not a problem for HA environments. If the application is correctly built to work in a cluster, then there are no special considerations. Ensure that at any given moment, only one node is processing a specific request. Typically, this is guaranteed by HA-ready inbound endpoints.

Inbound Endpoint

The inbound endpoint represents a bigger challenge when configuring your application in HA mode. The following sections provide information that will assist you in making the best decision.

SAP-Side Functionality

The SAP Connector is based on JCo Server functionality. JCo Server connects a gateway on the SAP side that is responsible for the following:

  1. Load balancing requests to the SAP inbound endpoint.

  2. In the case of transactional RFCs (rfcType is tRFC or qRFC), starting the transaction and making sure the same request is not sent to multiple inbound endpoints, thus avoiding duplicate requests from more than one cluster node.

Configuring the SAP Inbound Endpoint for HA

When configuring multiple SAP inbound endpoints in an HA configuration, remember that ALL nodes can share the Transaction IDs (TIDs). For this purpose, it is mandatory to configure a distributed object store-based transaction ID store. The recommended object store implementation for HA configuration is the managed-store, since the default implementation varies depending on whether the application is running standalone or in cluster (shared object store among cluster nodes).

Also, recall that in HA configurations the payload should be serializable. To ensure this is done, configure the inbound endpoint to output XML. In Mule 3.6.0, this is easily achieved with the outputXml attribute set to true. In previous versions, you needed to configure a global transformer.

Mule 3.6.0 and Newer


           
        
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<!-- SAP Connector -->
<sap:connector name="SapConnector"
    jcoAsHost="${sap.jcoAsHost}"
    jcoUser="${sap.jcoUser}"
    jcoPasswd="${sap.jcoPasswd}"
    jcoSysnr="${sap.jcoSysnr}"
    jcoClient="${sap.jcoClient}"
    jcoLang="${sap.jcoLang}"
    jcoPoolCapacity="${sap.jcoPoolCapacity}"
    jcoPeakLimit="${sap.jcoPeakLimit}"/>
 
<!-- Flow -->
<flow>
    <sap:inbound-endpoint connector-ref="SapConnector"
        type="function"
        rfcType="trfc"
        jcoGwHost="${sap.jcoGwHost}"
        jcoGwService="${sap.jcoGwService}"
        jcoProgramId="${sap.jcoProgramId}"
        outputXml="true">
        <!-- TID store -->
        <sap:mule-object-store-tid-store>
            <managed-store storeName="sap-tid-store" persistent="true" />
        </sap:mule-object-store-tid-store>
    </sap:inbound-endpoint>
    <!-- Other stuff here -->
</flow>

Mule 3.4.x and before


           
        
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<!-- SAP Connector -->
<sap:connector name="SapConnector"
    jcoAsHost="${sap.jcoAsHost}"
    jcoUser="${sap.jcoUser}"
    jcoPasswd="${sap.jcoPasswd}"
    jcoSysnr="${sap.jcoSysnr}"
    jcoClient="${sap.jcoClient}"
    jcoLang="${sap.jcoLang}"
    jcoPoolCapacity="${sap.jcoPoolCapacity}"
    jcoPeakLimit="${sap.jcoPeakLimit}"/>
 
<!-- SAP Transformer -->
<sap:object-to-xml name="sap-object-to-xml" />
 
<!-- Flow -->
<flow>
    <sap:inbound-endpoint connector-ref="SapConnector"
        type="function"
        rfcType="trfc"
        jcoGwHost="${sap.jcoGwHost}"
        jcoGwService="${sap.jcoGwService}"
        jcoProgramId="${sap.jcoProgramId}"
        transformer-refs="sap-object-to-xml">
        <!-- TID store -->
        <sap:mule-object-store-tid-store>
            <managed-store storeName="sap-tid-store" persistent="true" />
        </sap:mule-object-store-tid-store>
    </sap:inbound-endpoint> 
    <!-- Other stuff here -->
</flow>

TID Handler Configuration

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

With the SAP connector you can configure different TID stores:

  • In Memory TID Store: the default TID store that 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. This is not recommended for a production environment does not work well in a clustered environment.

  • 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 or a cluster-enabled Object Store so that you can share TIDs between the instances.

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 will be ignored.

Default In-memory TID Store

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

  1. The in-memory TID Store does NOT work as expected if you have multiple Mule ESB instances that share the same program ID. This happens because the SAP gateway balances the load 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 set by default.

    
                 
              
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    
    <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:context="http://www.springframework.org/schema/context"
          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/current/mule.xsd
            http://www.mulesoft.org/schema/mule/sap http://www.mulesoft.org/schema/mule/sap/current/mule-sap.xsd
            http://www.mulesoft.org/schema/mule/xml http://www.mulesoft.org/schema/mule/xml/current/mule-xml.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd">
     
        <!-- Credentials -->
        <context:property-placeholder location="sap.properties"/>
     
        <!-- 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 --> 
        <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}">
                <!-- TID -->
                <sap:default-in-memory-tid-store/>
            </sap:inbound-endpoint>             
            <!-- Other stuff here -->
        </flow>
    </mule>

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.


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<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:context="http://www.springframework.org/schema/context"
      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/current/mule.xsd
        http://www.mulesoft.org/schema/mule/sap http://www.mulesoft.org/schema/mule/sap/current/mule-sap.xsd
        http://www.mulesoft.org/schema/mule/jdbc http://www.mulesoft.org/schema/mule/jdbc/current/mule-jdbc.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-current.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd">
 
    <!-- Credentials -->
    <context:property-placeholder location="sap.properties"/>
 
    <!-- JDBC configuration -->
    <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 -->
    <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 -->
    <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}">
            <!-- TID -->
            <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>
        <!-- Other stuff here -->
    </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" />)

Database Creation Script for the JDBC Object Store


           
        
1
2
3
4
5
6
7
8
9
10
11
12
13
-- MySQL Script
CREATE 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
);

Retrieve TID Using a MEL Expression

When sending or retrieving IDocs, depending on the use case you may be required to obtain the IDoc number. Since the interchange of IDocs is inherently asynchronous, the only information that SAP and Mule share is the Transaction IDs.

The Transaction ID has been added as a new property to the Mule Message to satisfy the requirement that a Transaction ID be provided to get an IDoc number. This enhancement allows the customer to call RFC-enabled Function Modules on SAP in order to retrieve the IDoc number. These RFC-enabled Function Modules are:

  • INBOUND_IDOCS_FOR_TID

  • OUTBOUND_IDOCS_FOR_TID

Use the following MEL expression to extract the value of the TID:

#[message.outboundProperties.sapTid]

Below are two simple examples for inbound and outbound calls:


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!-- INBOUND | Receive IDoc -->
<sap:inbound-endpoint type="idoc" rfcType="trfc" outputXml="true"
    jcoGwHost="${sap.jcoGwHost}" jcoProgramId="${sap.jcoProgramId}"
    jcoGwService="${sap.jcoGwService}" jcoConnectionCount="${sap.jcoConnectionCount}" ...>
                    <!-- transaction config -->
            <sap:mule-object-store-tid-store>
               <jdbc:object-store name="jdbcObjectStore" ... />
            </sap:mule-object-store-tid-store>
        </sap:inbound-endpoint>
<logger message="#[message.outboundProperties.sapTid]" level="INFO" doc:name="Logger"/>


<!-- OUTBOUND | Send IDoc -->
<sap:outbound-endpoint type="idoc" rfcType="trfc" outputXml="true" ...>
        <!-- transaction config -->
        <sap:transaction action="BEGIN_OR_JOIN"/>
</sap:outbound-endpoint>
<logger message="#[message.outboundProperties.sapTid]" level="INFO" doc:name="Logger"/>
The TID feature is only available since SAP Connector 2.2.8.

Transactions

The SAP Connector does not support distributed transactions because JCo does not support XA. However, the SAP outbound endpoint supports the child element transaction:

<sap:transaction action="ALWAYS_BEGIN" bapiTransaction="true|false"/>

Compatibility Notes

Transaction support in the SAP Connector version 1.x is very limited and only transactions of one function call are allowed.

Starting with the SAP Connector version 2.1.0, the attribute bapiTransaction is no longer present at the transaction level. This attribute was moved to the outbound endpoint.

Attribute Description Default Value Since Version

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

1.0

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. Since version 2.1.0 this option has being moved to the outbound endpoint.

false

1.0

For more information, consult the Transactions Configuration Reference.

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

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

sRFC Stateful

All calls are done using synchronous RFC as the connector and share the same context.

Configuration


           
        
1
2
3
4
5
6
7
8
<sap:outbound-endpoint
    exchange-pattern="request-response"
    type="function"
    bapiTransaction="false"
    rfcType="srfc" ... >
    <sap:transaction
        action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" />
</sap:outbound-endpoint>

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


           
        
1
2
3
4
5
6
7
JCoContext.begin(destination);
 
function1.execute(destination);
function2.execute(destination);
function3.execute(destination);
 
JCoContext.end(destination);

sRFC Stateful BAPI Transaction

All calls are done using synchronous RFC as the connector and share the same context and the BAPI_TRANSACTION_COMMIT is called at the end of the transaction.

Configuration


           
        
1
2
3
4
5
6
7
8
<sap:outbound-endpoint
    exchange-pattern="request-response"
    type="function"
    bapiTransaction="true"
    rfcType="srfc" ... >
    <sap:transaction
         action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" />
</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. This can be done by setting the property bapiTransaction=true in the XML or by checking the property Is BAPI Transaction in the UI settings.

SAP sRFC Transaction BAPI

For this to work, the whole unit of work must be in the same thread and the calls need to be stateful.

The Java JCo code that calls these "special" BAPIs is as follows:


           
        
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

All calls are done using transactional RFC as the connector and share the same context.

Configuration


           
        
1
2
3
4
5
6
7
8
<sap:outbound-endpoint 
    exchange-pattern="request-response" 
    type="function"
    bapiTransaction="false"
    rfcType="trfc" ... >
    <sap:transaction
        action="NONE | ALWAYS_BEGIN | BEGIN_OR_JOIN | ALWAYS_JOIN | JOIN_IF_POSSIBLE" />     
</sap:outbound-endpoint>

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


           
        
1
2
3
4
5
6
7
8
9
10
11
String tid = destination.creatTID();
try
{
    JCoContext.begin(destination, tid);
    function1.execute(destination, tid);
    function2.execute(destination, tid);
}
finally
{
    JCoContext.end(destination);
}

qRFC Stateful

All calls are done using queued RFC as the connector and share the same context.

Configuration


           
        
1
2
3
4
5
6
7
8
9
<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:


           
        
1
2
3
4
5
6
7
8
9
10
11
String tid = destination.creatTID();
try
{
    JCoContext.begin(destination, tid);
    function1.execute(destination, tid, queueName1);
    function2.execute(destination, tid, queueName2);
}
finally
{
    JCoContext.end(destination);
}

Example

The following example only works in Mule 3.3+ with SAP Connector version 2.1.0 or greater. It describes how to execute two BAPIs in a stateful transaction.


          
       
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<mule ...>
 
    <!-- SAP credentials -->
    <!-- SAP Connector configuration -->

    <flow>
        <!-- Other components -->
        <sap:xml-to-object/>

        <!-- Transaction -->
        <transactional>
            <!-- BAPI call 1 -->
            <sap:outbound-endpoint
                exchange-pattern="request-response"
                type="function"
                bapiTransaction="true"
                rfcType="srfc"
                functionName="BAPI-1" ... >
                <sap:transaction action="ALWAYS_BEGIN"/>
            </sap:outbound-endpoint>
            
            <!-- Other components -->
            <sap:xml-to-object/>

            <!-- BAPI call 2 -->
            <sap:outbound-endpoint
                exchange-pattern="request-response"
                type="function"
                bapiTransaction="true"
                rfcType="srfc"
                functionName="BAPI-2" ... >
                <sap:transaction action="BEGIN_OR_JOIN"/>
            </sap:outbound-endpoint>
        </transactional>
        <!-- Other components -->
    </flow>
</mule>

See Also