Wednesday, 1 March 2017

HOW TO CONNECT SAP USING THE MULESOFT

INTRODUCTION

Companies using SAP as a resource planning solution may need to integrate it with other applications in order to automate their business processes. This article demonstrates how to connect other systems with SAP using MuleSoft Mule ESB.
Install and Configure Java Connector Libraries
There are SAP Java Connector (JCo) libraries available which SAP Transport uses to perform below operations in the Mule application:
  • Execute BAPI functions over synchronous RFC (sRFC), transactional RFC (tRFC) and queued RFC (qRFC).
  • Send IDocs over tRFC and qRFC.
  • Receive IDocs over tRFC and qRFC.
  • Transform all SAP objects (JCoFunction & IDocs) to/from XML.
1. Download the SAP JCo and IDoc libraries from the SAP site: http://service.sap.com/connectors (it requires an SAP User ID). There will be two jars and one dynamic link library (dll):
  • sapidoc3.jar
  • sapjco3.jar
  • sapjco3.dll
Note: These libraries are operating system dependent, so download he SAP libraries that correspond to the OS you are working in.
2. Create a Mule application e.g. SAP.Connect
3. Place jars i.e. sapidoc3.jar and sapjco3.jar in application CLASSPATH. In this instance, I am showing one application so copy the files under: SAP.Connectsrcmainapplib.
Note: MuleSoft recommends configuring the following directories
  • $MULE_HOME/apps/YOUR_APP/lib: make libraries available just for your application.
  • $MULE_HOME/lib/user: Share libraries among all applications running within the same Mule ESB instance.
4. Copy SAP JCo dynamic linked library sapjco3.dll under local folder. For this application I placed the file under DLL folder.
Note: As per MuleSoft, it can be done by 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 CONNECTOR CONFIGURATION

1. Go to Global Elements of Mule application created in the step above, click the Create button, write SAP in Filter, select SAP under Connector Endpoints and click OK
SAPMulesoft-1
2. Provide SAP connection properties as shown in the image below, i.e.:
  • SAP Host
  • User
  • Password
  • SAP System Number
  • SAP Client
  • Login Language
  • For Required Dependencies, provide the JCo DLL sapjco3.dll path for the SAP Java Native Library, classpath of JAR sapjco3.jar for the SAP Java Connector and classpath of JAR sapidoc3.jar for the SAP Java IDoc Class Library
Click Test Connection and click the OK button if successful.
SAPMulesoft-2

OUTBOUND ENDPOINT CONFIGURATION

In this instance, we will poll the FTP location to receive the IDoc XML and send to SAP after converting to IDoc and receiving a successful/failed response from SAP. In order to accomplish this scenario, create a Mule flow with following artifacts:
  • FTP Endpoint – Location to receive XML document.
  • Byte Array to String – To convert the received byte array to string.
  • XML to SAP IDoc – Reads the input idoc array byte stream and converts it to an SAP object.
  • SAP Endpoint – To receive IDoc.
Inside the Mule flow drag-and-drop the SAP Endpoint and configure it as shown in the image below:
  • Endpoint Pattern – request-response
  • Connector Configuration – Select connector configured in above step
  • Type – IDoc
  • Object Name – SAP object for sending IDoc
  • RFC Type – Synchronous RFC
SAPMulesoft-3
Below is the whole mule flow:
SAPMulesoft-4

INBOUND ENDPOINT CONFIGURATION

For the SAP Inbound Endpoint (JCo Server), we need to modify OS services using the following path:
C:WINDOWSsystem32driversetcservices file
At the end of the services file set the following:
sapgw00   3300/tcp
1. Create a mule flow for inbound
2. Drag and drop SAP endpoint and configure as showing below:
SAPMulesoft-5
Below is the mule flow:
SAPMulesoft-6

Sunday, 12 February 2017

Configuring HTTPS Connector in Mule

In this post I am going to clarify some concepts which will show how to configure an HTTPS client and server in Mule for SSL and two-way SSL (Mutual Authentication).
The following is an explanation of the roles both keystore and truststore play in HTTPS as well as how they are referred to in Mule.
Key Store (tls-key-store in Mule): A keystore contains private keys, and the certificates with their corresponding public/private keys. You only need this if Mule is exposing an HTTP endpoint (server) or the remote server requires client authentication. In Mule, this is defined with the ‘tls-key-store’ attribute on the HTTPS connector.
Trust Store (tls-server in Mule): used as a repository of CA (certificate authority) or simple certificates that the client should trust. Note: this is only required if the server we are connecting with, has a certificate which is signed by an authority not recognised in the java truststore or the certificate is self signed. In Mule, this is configured using the ‘tls-server’ attribute on the HTTPS connector.
Note: One main source of ambiguity in using the HTTPS connector is the use of tls-client, this is redundant (seeJIRA MULE-5213) and is a known issue. This is not required to configure SSL or two-way SSL.
One-way SSL
For normal SSL, on the server connector we need a keystore where the servers’ certificate and private key reside. In this example we are using self signed certificates, therefore we need a trustore on the client side.
The following are server and client HTTPS connectors for normal SSL with self signed certificate on the server side:
<https:connector name="httpsServerConnector" doc:name="HTTP\HTTPS" validateConnections="true">
<https:tls-key-store path="server-keystore.jks" keyPassword="keypass" storePassword="keypass" />
</https:connector>
<https:connector name="httpsClientConnector" doc:name="HTTP\HTTPS" validateConnections="true">
<https:tls-server path="client-truststore.jks" storePassword="keypass"/>
</https:connector>

Two-way SSL (Mutual Authentication)
When configuring two-way SSL between the HTTPS client and server, in Mule we need to:
1) configure an HTTPS client connector with both client keystore and truststore. The client keystore shall contain the clients public certificate and private key. The client truststore shall contain the servers certificate. 
2) configure the server connector with both server keystore and truststore as well as set ‘requireClientAuthentication’ to ‘true’ on the ‘tls-server’ (i.e. truststore) attribute. This shall force the server connector to check client requests in the trust store prior to granting access.
The server keystore shall contain the server’s public certificate and private key. The server truststore shall contain the client’s certificate.
In order to create the self signed certificate, trust store and key store for our HTTPS service, the java keytool was used. However the following graphical tool may prove handy.
The following is HTTPS server connector configuration for two-way SSL:
<https:connector name="httpsServerConnector" doc:name="HTTP\HTTPS" validateConnections="true">
<https:tls-key-store path="server-keystore.jks" keyPassword="keypass" storePassword="keypass" />
<https:tls-server path="server-truststore.jks" requireClientAuthentication="true" storePassword="keypass" />
</https:connector>

and a flow with inbound HTTPS using the above connector:
<flow name="httpsServer" doc:name="httpsServer">
<https:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8083" connector-ref="httpsServerConnector" doc:name="HTTPS" />
<logger message="accessed https server successfully!" level="INFO" doc:name="Logger" />
</flow>

The following is HTTPS client connector configuration for two-way SSL:
<https:connector name="httpsClientConnector" doc:name="HTTP\HTTPS" validateConnections="true" >
<https:tls-key-store path="client-keystore.jks" keyPassword="keypass" storePassword="keypass" />
<https:tls-server path="client-truststore.jks" storePassword="keypass"/>
</https:connector>

Client flow, accepting HTTP requests and sending to HTTPS server:
<flow name="httpsClient" doc:name="httpsClient">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="8081" doc:name="HTTP" path="test">
</http:inbound-endpoint>
<logger message="sending request from https client to https server..." level="INFO" doc:name="Logger" />
<https:outbound-endpoint exchange-pattern="request-response" host="localhost" port="8083" connector-ref="httpsClientConnector" doc:name="HTTP" />
</flow>