Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
bhavesh_kantilal
Active Contributor

Background


In Part 1 of this blog series, a Login Integration Flow was created that persisted the sessionID, serverURL and sessionTime to the Global Variables of HCI.

  • How is this Integration Flow#1 used when the IDoc from SAP arrives to HCI?

  • How can a Global Variable be read from the HCI DataStore?

  • How easy is it to add SOAP Headers to your SOAP Message?


This blog covers this and the end to end flow. Read on!

Update#1: Currently ( As of Apr 12, 2016 ) HCI does not support the ability to set the SOAP URL Dynamically in the SOAP Receiver Adapter. Hence, at this moment, while the SOAP URL is persisted into the Global Variables, this is not used anywhere. The list of parameters supported Dynamically is listed here : HCI Dynamic Parameters

Nov 3, 2016 - The limitation described is no longer applicable. You can set the URL Dynamically as described in this blog : Dynamic address in the SOAP receiver adapter of HANA Cloud Platform, Integration Services by m.jaspers

Integration Flow#2 – Material Master Replication Process


ProcessFlow




















































Step Type Description
Integration Flow Trigger

  • The Integration Flow is triggered using a IDoc Sender Channel.

  • The authentication mode is set to Basic Authentication.


Content Modifer

  • Content Modifier sets the Header properties SAP_ApplicationID, SAP_Sender, SAP_Receiver

  • SAP_ApplicationID is set to the IDoc number XPath to enable search for the Interface with the IDoc Number

  • SAP_Sender is set to SNDPRN XPath to enable set Sending System Details

  • SAP_Receiver is set to RCVPRN XPath to enable set Receiver System Details

  • This is an optional step and can be skipped.


Mapping

  • The Message Mapping to Map the Source IDoc to the UPSERT Webservice call is triggered.

  • This blog does not go into the details of this mapping and this should be covered in the Pre-Requiste section of the Part1 of this Blog series


Content Modifier

  • Set the Property - sessionID, sessionURL, sessionTime.

  • These Properties are read from the Global Variables persisted in the IntegrationFlow#1- Login.

  • Setting these properties in this step enables these to be accessible as local variables within the Integration Flow


Script

  • The script checks if the sessionID is valid. SalesForce sessionIDs are valid for 2 hours from the time the Login is made.

  • This Groovy script checks the if currentTime is within sessionTime+2 Hours

    • If yes, property sessionValid is set to True

    • If no, property sessionValid is set to False



  • In summary, this Script checks if the session continues to be valid and sets a Flag accordingly.


Gateway

  • If Session InValid -> Branch 1

  • If Session Valid -> Branch 2 (Default Branch)




SessionInValid -

Branch 1

Request Reply


  • Make a SOAP Call to the Integration Flow#1 Login

  • This Request Reply step triggers the call to the Integration Flow #1, if the session is Invalid and a Login call has to be made to get a new sessionID.


Content Modifier

  • Set the Property - sessionID, sessionURL, sessionTime.

  • These Properties are read from the Global Variables persisted in the IntegrationFlow#1- Login.

  • Setting these properties in this step enables these to be accessible as local variables within the Integration Flow


Script

  • Add sessionID to the SOAP Header

  • Perform certain XML Namespace Manipulations - Reasons for this are as described in the Prerequisite documents of Blog 1 of this series.


Request - Reply

  • Make the SOAP call to SalesForce to perform Upsert operation



 


Content Modifier


Set the Headers to enable monitoring with the corresponding IDoc Headers. The documentation on this can be read in the blog: End2End monitoring of HCI message flow in Standard Content - Made easy



Mapping

Mapping from the Source IDoc to the SFDC Upsert Request. The details of the mapping are not discussed in this blog.



Content Modifier

Content Modifier enables to set the Property sessionID,sessionURL,sessionTime. The values for these properties are read from their corresponding Global Variables.



Script

The below script is used to validate if the session is valid. If session is Valid, property sessionValid is set to "True" else set to "False"
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.util.Date;
import java.text.SimpleDateFormat;
def Message processData(Message message) {
def messageLog = messageLogFactory.getMessageLog(message);
def propertyMap = message.getProperties()
//Read sessionTime from the Properties
String sessionTime = propertyMap.get("sessionTime");
//Set a Log Message for Monitoring purporses
messageLog.setStringProperty("sessionTime ", sessionTime);
// Convert sessionTime to a Calendar Date
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
cal.setTime(sdf.parse(sessionTime));
// Add 2 Hours to sessionTime
Calendar cal1 = Calendar.getInstance();
SimpleDateFormat sdf1 = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
cal1.setTime(sdf1.parse(sessionTime));
cal1.add(Calendar.HOUR_OF_DAY, 2);
// Get Current Time
SimpleDateFormat sdfDate = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");//dd/MM/yyyy
Date now = new Date();
String sessionValid = "";
// Validate if session is Valid
if(now.before(cal1.getTime())){
sessionValid = "true";
}else{
sessionValid = "false";
}
message.setProperty("sessionValid",sessionValid);
messageLog.setStringProperty("sessionValid ", sessionValid);
return message;
}







 

Parallel MultiCast & Gateway

Parallel MultiCast is used to enable have a Join Step to merge the multiple branches of the Gateway Step. If you would like to understand these step types further would suggest reading the blog : Multicast Pattern in Integration Flows (HCI-PI)


Gateway Properties are as below

  • If sessionValid = 'False' -> Make a Request/Reply call to HCI Integration Flow #1 - Join Step

  • If sessionValid = 'True' -> Default Branch as no call to SFDC for Login is required -  Join  Step




Request Reply

As mentioned previously, this Request Reply step uses the SOAP Adapter to make a call back to Integration Flow#1.

The SOAP Adapter treats this like any other Webservice and the Proxy-Type used has been Set to "Internet".

 

At this moment, I am not aware of any other means to trigger an Integration Flow of HCI and hence this approach has been documented.It would be great if a inbuilt feature is provided to do this to avoid traffic over the internet.





Content Modifier

This content modifier step performs the same tasks as one of the previous content modifier steps,i.e, enables to set the Property sessionID, sessionURL, sessionTime. The values for these properties are read from their corresponding Global Variables.



Script

This script is used to insert SOAP Headers into your Message. In this case, we insert the sessionID into the SOAP Header.

Note: This script also performs some rudimentary XMLNamespace manipulations for SFDC to address the WSDL Incompatibilities into your PI Graphical Mapping editor. There are better ways to do this including a XSLT / Parsing Technique. This blog does not delve into the details of the same.
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.ArrayList;
import java.util.List;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.cxf.binding.soap.SoapHeader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import com.sap.it.api.ITApiFactory;
import com.sap.it.api.securestore.SecureStoreService;
import com.sap.it.api.securestore.UserCredential;
import groovy.util.XmlSlurper;
def Message processData(Message message) {
def body = message.getBody();
def messageLog = messageLogFactory.getMessageLog(message);
// Read SessionID from the Property
def propertyMap = message.getProperties()
String sessionID = propertyMap.get("sessionID");
// Perform certain XMLNamespace manipulations. Note this is a very rudimentary mode of performing the same.
// An XSLT or a Parser are better modes to do the same.
String payload = message.getBody(java.lang.String);
payload = payload.replaceAll('type','xsi:type');
payload = payload.replaceAll('xmlns:ns0="urn:enterprise.soap.sforce.com"','xmlns:ns0="urn:enterprise.soap.sforce.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"');
payload = payload.replaceAll('xsi:type="Product2"','xsi:type="urn1:Product2"');
message.setBody(payload);
// Set SOAP Heeader sessionID
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
dbf.setIgnoringElementContentWhitespace(true);
dbf.setValidating(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.newDocument();
Element authHeader = doc.createElementNS("urn:enterprise.soap.sforce.com", "SessionHeader");
doc.appendChild(authHeader);
Element clientId = doc.createElement("sessionId");
clientId.setTextContent(sessionID);
authHeader.appendChild(clientId);
SoapHeader header = new SoapHeader(new QName(authHeader.getNamespaceURI(), authHeader.getLocalName()), authHeader);
List headersList = new ArrayList<SoapHeader>();
headersList.add(header);
message.setHeader("org.apache.cxf.headers.Header.list", headersList);
messageLog.setStringProperty("SessionID ", sessionID);
return message;
}






Request Reply

 

Now that the SOAP Message is formed with the correct SessionID in the SOAP Header, the request reply is aimed at making the SOAP Call to SFDC to perform the corresponding operation on SFDC. Unlike in the PI world, where a Do Not Use SOAP Envelope mode is required, so such mode is required in HCI as HCI natively provides a mode to manipulate the SOAP Header.


Testing Your Flow



  • Prior to testing this Integration Flow, make sure that the Integration Flow#1 Login has been triggered atleast once manually through SOAP UI. Reason : This Integration Flow assumes that the Global Variables sessionID, sessionURL and sessionTime exist in the SAP Data Store.

  • Trigger the IDoc from SAP.


Results



  • IDoc Triggered at 8:53:56 AM, Processing Time ~ 6 Seconds

    • This Integration Flow makes the Call to the Login Integration Flow.

    • The Logs also show the call to the Login Integration Flow ( Once )






  • IDoc's triggered at 8:53:58 and 8:54:00, Procesing Time ~ 1 Second

    • This Integration Flow re-uses the SessionID as the sessionID is valid.






Global Data Store Updated via the Login Integration Flow



 

Additional Details

  • Search using IDoc# works as required. Note as the variable was declared as a Integer only Number is to be used.

  • Likewise if variables is declared as a String, the same needs to be appended with zeroes or wild card prefix is to be used.






Logs Show the sessionID Status as per the Groovy Script

 


Final Note


The above 2 blogs show a means to implement a Integration with SFDC. Like in the PI world, there are multiple design options for this integration requirement. The idea behind this blog was not to delve into the various other options but show users how the most common approach used for persistence of sessionID's can be implemented using HCI.

Other patterns / models can be added into the comment sections!

13 Comments
Labels in this area