Background
Integration between SFDC and a Back End SAP ERP has been a common Interface requirement for many PI consultants. A typical SFDC integration using PI would involve -
- Check sessionExpiryTime from Value Mapping
- If session expired,
- Make a Login Call to SFDC.
- Persist the SessionID, sessionExpiryTime and URL into PI Value Mapping ( Use Integration Directory API )
- Make corresponding API call to SFDC by adding SessionID to the Soap Header Using XSLT / Java Mappings or use Adapter Modules for the same.
So how do you do a SFDC Integration with HCI using the SOAP Adapter HCI provides? Are there better ways to do this Integration on HCI?
Note: There exists a Partner Adapter for SFDC from a SAP Partner for HCI. This blog does not go into the merits of using an out of the box adapter vs the below custom process.
Pre-Requisite:
There are detailed documents available on this on SCN for SFDC Integration using PI. In case you are new to SFDC Integration and would like to understand a flow of how SFDC Integration works would recommend to read the below first. The next sections of this blog assumes you are aware of the “How-To” in terms of SFDC Integration and will focus only on how HCI can be used for such Integration's.
Salesforce.com Integration Using SAP PI: A Case Study
HCI Scenario under Consideration
- SAP ERP Triggers a Material Master Change to HCI using a ARTMAS IDoc.
- The same has to be updated (UPSERT Operation) to SFDC.
HCI Implementation Process Flow
When implementing this Process Flow on HCI to make the design modular, 2 separate Integration Flows have been created,
- Integration Flow#1 – Login Process
- Integration Flow#2 – Actual Material Master Replication Process as described above. Integration Flow#2 will use Integration Flow#1 in case the session has expired.
Due to the complexity of this flow,this blog deals with Integration Flow#1. Integration Flow#2 will be published in a subsequent blog.
Integration Flow#1 – Login Process
Process Flow
Integration Flow Trigger |
|
Content Modifier |
|
Script |
|
Request Reply |
|
RemoveXMLNamespace |
|
Write Variables |
|
Content Modifer |
|
Content Modifier Settings
Set Body to match the SFDC Request XML. The %user% and %pass% will be replaced with the actual SFDC User and Password in the next step.
<?xml version="1.0" encoding="UTF-8"?><ns0:login xmlns:ns0="urn:enterprise.soap.sforce.com"><ns0:username>%user%</ns0:username><ns0:password>%pass%</ns0:password></ns0:login>
Set Property inputPayload to persist the actual Input to the Integration Flow. This will be used in the last step of the Integration Flow to return the response back to the calling Integration Flow.
Groovy Script
Groovy Script reads the User Name and Password from Deployed Credentials called :SFDCCredentials. Make sure that the corresponding credentials are deployed on the HCI Tenant. If the name of the Credentials is different adjust the code accordingly.
import com.sap.gateway.ip.core.customdev.util.Message; import java.util.HashMap; import com.sap.it.api.ITApiFactory; import com.sap.it.api.securestore.SecureStoreService; import com.sap.it.api.securestore.UserCredential; def Message processData(Message message) { /* Read Credentials. Name of Deployed Credentials : SFDCCredentials */ def messageLog = messageLogFactory.getMessageLog(message); messageLog.setStringProperty("Info1", "ReadLoginCredentials Script Called.."); String payload = message.getBody(java.lang.String) def service = ITApiFactory.getApi(SecureStoreService.class, null); def credential = service.getUserCredential("SFDCCredentials"); if (credential == null){ throw new IllegalStateException("No credential found for alias 'SFDCCredentials'"); } messageLog.setStringProperty("Info3", "SFDC Credentials Retrieved"); String userName = credential.getUsername(); String password = new String(credential.getPassword()); messageLog.setStringProperty("password ", password); message.setProperty("userName", userName); message.setProperty("password",password); payload = payload.replaceAll('%user%',userName); payload = payload.replaceAll('%pass%',password); message.setBody(payload); return message; }
Request Reply
Configure Request Reply to a SOAP Receiver Channel.URL of SOAP Receiver Channel would point to the SFDC Login URL. Use the SFDC WSDL as described in the documents in the Prerequisite section.
RemoveXMLNamespace - XSLT Mapping
The Login Response returned by SFDC is as shown in the image below.
The sessionID, serverUrl are persisted into Global variables from the LoginResponse XML in the next step using XPATH. As the login response contains the XML Namespace declaration highlighted, XPath Expression does not provide the required results. This XSLT Mapping has been used to remove all XML Namespaces to enable the Xpath expression to evaluate successfully in the next Step.
<?xml version="1.0"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output indent="yes" method="xml" encoding="utf-8" omit-xml-declaration="yes"/> <xsl:template match="*"> <xsl:element name="{local-name()}"> <xsl:apply-templates select="@* | node()"/> </xsl:element> </xsl:template> <xsl:template match="@*"> <xsl:attribute name="{local-name()}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:template> <xsl:template match="comment() | text() | processing-instruction()"> <xsl:copy/> </xsl:template></xsl:stylesheet>
Write Variables
The Write Variables step is used to persist the sessionID,serverUrl and sessionTime as Global Variables.
This step takes the output of the XML Mapping,.i.e, the Login Response without the namespace prefix and then parser's the same to set the Global variables - sessionID and serverURL using XPath expressions
As the underlying framework for HCI is Apache Camel, the variables available in Apache Camel are also available in HCI. The sessionTime Global variable is set using Camel Variables. Refer to section Variables in this camel link to understand what other options are available.
Name | DataType | Type | Value | Global Scope |
---|---|---|---|---|
sessionID | java.lang.String | XPath | /loginResponse/result/sessionId | Enabled |
serverURL | java.lang.String | XPath | /loginResponse/result/serverUrl | Enabled |
sessionTime | java.lang.String | Expression | ${date:now:dd-MM-yyyy HH:mm:ss} | Enabled |
Content Modifier
The Content Modifier step is used to return the Input XML to this Integration Flow as the output of this Integration flow. The property inputPayload that was persisted in the first content modifier step will now be used to set the response. Set Body as ${property.inputPayload}
Test Integration Flow#1 – Login Process
Test your flow by triggering the Interface using SOAP UI. SOAP UI should return the same data that was as your request.
Navigate to DataStoreViewer and go to sap_global_store. The Global variables are persisted in this DataStore and you should be able to see the corresponding entries in this Data Store as shown below.
Your Integration Flow#1 for Login to SFDC and persisting the session to Global Variables is now in place and can be triggered from any external system or any other HCI Integration Flow.
We will look at the Integration Flow#2 in the next blog of this series and how all pieces fit in together!