Technical Articles
SAP PI re-usable connectivity suite for Salesforce
Title:
SAP PI re-usable connectivity suite for Salesforce
Pre-Requisites:
- Fairly good knowledge in SAP PI (Single Stack).
- Knowledge of NW BPM
- Value mappings
Introduction:
This is a solution that I implemented in a time crunch situation which provided good value and cost savings for my company in reducing the number of API connections made my SAP PI to Salesforce per hour. I designed and implemented this solution with my prior knowledge of NW BPM’s, Value Mappings, Java Mappings, UDF and PI REST adapter configurations. I believe this will be helpful in cost reductions of your Salesforce subscriptions by keeping your API connections in check.
To begin with, I did an analysis on the number of API connections we were doing with Salesforce and the numbers were staggering. I got to know that the API connections were exceeding 10,000 per hour at times. In order to avoid the connections being dropped or paying additional subscription for increasing the API limits, I had to come up with a solution and this blog post is a result of that implementation.
Benefits:
- I was able to manage the no. of connections PI makes in an hour/day irrespective of the no. of transactions.
- Was able to save Cost premiums for exceeded API connections
- No additional adapter required
- Can be used for both SOAP based connections and REST connections
Solution Overview:
This solution uses a NW BPM to save away the Token and the Connection URL on to the runtime cache to be used during the actual connection.
Flow Diagram
Image 1: Pictorial Representation of the implementation
Implementation Steps
Step 1:
Use a trigger file to start your BPM at regular intervals.
Setup an ICO/iFlow to trigger the BPM at 30 mins / 1 hr intervals
ID Config:
Sender Channel:
ICO to BPM:
Step 2:
BPM Process
Image 2: BPM Workflow & Steps. Courtesy: NWDS
Tip: Salesforce token is over 100 characters. The limit of the cache variable is 100 characters. Hence we have to save it as 2 parts.
2.1 Login to SFDC
- Create ICO/iFlow to login to SFDC
- Capture the following from Login Response
- Token (2 Parts) as mentioned
- URL
2.2 Value Mapping Interface
Create a Re-Usable ICO/iFlow for value Mapping Interface
- ValueMapping interface used: ValueMappingAbsSync (standard)
- Sample Input Values:
- Agency: “Token1”
- Grp_id: <GUID>
- Grp_name: <GroupName>
- Operation: Insert
- Scheme: ID1
- Text: Token1(first 90 chars)
Tip: You can create a Value Mapping interface in the Directory (not shown here) and use its reference for updating all 3 Value mappings from the BPM
Repeat the Value mapping for the next 2 steps, Token2, URL
2.3: Operation mapping for the Value Mapping update interface
Image 4: Mapping for VM interface. Courtesy: SAP PI ESR
The Operation mapping needs a Delete Operation followed by Insert Operation. This will replace existing values with new values.
Step 3: Using the Token and URL from Cache
3.1 Retrieving the Token ID and URL from cache
Image 5: Header Mapping to export token. Courtesy: SAP PI ESR
REST
3.2: Sample UDF code for Token Export:
{
String Url = "";
Url = SFDCserverUrl.substring(SFDCserverUrl.indexOf("https"), (SFDCserverUrl.indexOf("/Soap/")));
DynamicConfiguration conf1 = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey key1 = DynamicConfigurationKey.create("http:/"+"/sap.com/xi/XI/System/REST","access_token");
conf1.put(key1, token);
DynamicConfiguration conf2 = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey key2 = DynamicConfigurationKey.create("http:/"+"/sap.com/xi/XI/System/REST","serverUrl");
conf2.put(key2, Url);
DynamicConfiguration conf3 = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey key3 = DynamicConfigurationKey.create("http:/"+"/sap.com/xi/XI/System/REST","Param1");
conf3.put(key3,Param1);
DynamicConfiguration conf4 = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey key4 = DynamicConfigurationKey.create("http:/"+"/sap.com/xi/XI/System/REST","Param2");
conf4.put(key4,Param2);
return"";
}
Salesforce REST Receiver:
Image 6: Receiver REST Channel. Courtesy: SAP PI ID
Note: See SAP Note 2174651 for security risks
SOAP Adapter:
3.3: Sample Java mapping code for SOAPĀ
Use Dynamic Configuration to retrieve the values from cache to prepare the SOAP Envelope. Sample Method is provided.
private void getSessionIdFromVM() throws ValueMappingException {
String context = "http://sap.com/xi/XI";
// get Token ID1
String senderAgency = "SenderAgencyForToken";
String senderScheme = "SenderSchemeForToken";
String receiverAgency = "Token";
String receiverScheme = "Token1";
String token1 = "";
String token2 = "";
String url = "";
IFIdentifier src = XIVMFactory.newIdentifier(context, senderAgency, senderScheme);
IFIdentifier dst = XIVMFactory.newIdentifier(context, receiverAgency , receiverScheme);
try {
token1 = XIVMService.executeMapping(src, dst, "Token1");
} catch (ValueMappingException e) {
// message the following if not found:
// return ("no ValueMapping found for [" + "Token1" + "]");
}
// get Token ID2
senderAgency = "SenderAgencyForToken";
senderScheme = "senderSchemeForToken";
receiverAgency = "Token";
receiverScheme = "Token2";
src = XIVMFactory.newIdentifier(context, senderAgency, senderScheme);
dst = XIVMFactory.newIdentifier(context, receiverAgency , receiverScheme);
try {
token2 = XIVMService.executeMapping(src, dst, "Token2");
} catch (ValueMappingException e) {
// message the following if not found:
// return ("no ValueMapping found for [" + "Token2" + "]");
}
// get URL
senderAgency = "SenderAgencyForURL";
senderScheme = "SenderSchemeForURL";
receiverAgency = "URLValue";
receiverScheme = "URL";
src = XIVMFactory.newIdentifier(context, senderAgency, senderScheme);
dst = XIVMFactory.newIdentifier(context, receiverAgency , receiverScheme);
try {
url = XIVMService.executeMapping(src, dst, "URL");
// return res;
} catch (ValueMappingException e) {
// message the following if not found:
// return ("no ValueMapping found for [" + "URL" + "]");
}
sessionId = token1 + token2;
SFDCserverUrl = url;
}
Conclusion:
I used re-usable ICO/iFlows to update the Value Mappings for each token that is needed for API connectivity. Once the setup for capturing the Token information is completed, the Java mappings and UDF’s are re-usable for your REST and SOAP connections.
Please leave your comments, feedback which are very much appreciated.
Best Regards,
Paul.
Note: All images/code is my own development