Skip to Content
Author's profile photo Dominic Beckbauer

Nested Calls in SAP Cloud Platform Integration Flows

Hello Integrators!

In this blog post, I want to show you how we work with nested calls to enrich data with an external ID from a different source in iFlows.

What are they good for?

Let’s say we want to load contacts to SAP Cloud for Customers, but we do not have the internal ID of the contacts in our source system. To do so, we would need to enrich the data and transfer the internal ID for each existing contact otherwise the system would end up creating a new record. There are many examples like this, where data is in a XML-Structure and the structure needs to be enriched before sending it to a service.

How’s it done?

The idea is to create two branches. In one, you are calling the service with the data you need and in the other one, you are bypassing the original data. After you have joined the two branches together, you start to enrich the bypassed payload with the new data.

Here you see that one branch bypasses the data and one makes a SOAP-Request to get IDs. We use a parallel multicast to create the two flows.

The structure of the nested call: map the message to the structure you need, make the call and extract the data from the payload to a header variable.

After collecting the external IDs, you should write them to a hashmap and save the hashmap in a header variable. Take a look at the “write hashmap” script. Then you can access the data in a script later.

In our case we get XML from the SOAP-Service that we call. We use the XMLSlurper to read it out in a Script.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
    
    HashMap<String, String> externalIdMapping = new HashMap<String, String>();
	
	def body = message.getBody(java.lang.String);
	def node = new XmlSlurper().parseText(body)

	for (i = 0; i < node.ObjectIDMapping.size(); i++) {
		externalIdMapping.put(node.ObjectIDMapping[i].RemoteObjectID.text(),node.ObjectIDMapping[i].LocalObjectID.text());		
	}
	
	message.setHeader("externalIdMapping",externalIdMapping);
	message.setBody("");
	
	return message;

}

In this case the hashmap uses a string as key and value. In other cases you can put whole structures and other objects as values.

Don’t forget to delete the body payload because it is not used anymore and you would get problems in the gather element or late when mapping.

After you have joined the flows again and gathered the messages to have the “old” payload and the hashmap header, you can use the hashmap in the next message mapping. Remember: we have an xml structure with an external ID as input but we need the internal ID for the service at the end of our flow.

In a custom function, you can read the data from the hashmap.

In our case the the custom function looks like this:

import com.sap.it.api.mapping.*;

def String customFunc(String arg1, MappingContext context){
    
HashMap<String, String> externalIdMapping = context.getHeader("externalIdMapping");
arg1 = externalIdMapping.get(arg1);
if ( arg1 == null ) {
    arg1="";   
}
return arg1 
}

Now you have enriched your XML with the external ID from a second source.

Do you have other ideas of implementing nested calls? I think it is also possible to bypass the old payload in a header variable, but, to me, this looks easier to read. Please let me know if you have any questions or suggestions.

Assigned Tags

      5 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Eng Swee Yeoh
      Eng Swee Yeoh

      Hi Dominic

       

      Thanks for sharing your approach on this blog.

       

      Just curious - essentially you just want to enrich the payload from an additional source, so wouldn't this have worked using the Content Enricher pattern that is already available?

       

      Regards

      Eng Swee

      Author's profile photo Dominic Beckbauer
      Dominic Beckbauer
      Blog Post Author

      Hi Eng Swee,

       

      interesting idea from you. In this case it seems like a pretty good choice. Do you have experience with the content enricher?

      It is not clear for me how to enrich a XML-structur with a full XML Node. Is this possible?

       

      Regards

      Dominic

       

      Author's profile photo Eng Swee Yeoh
      Eng Swee Yeoh

      Hi Dominic

       

      Yes, I have used the content enricher before. You can either use it in

      • Enricher mode - appends the returned message to a particular node if there is a match with a particular field in the source message
      • Combine mode - appends the full returned message at the end of the source message

       

      Depending on the output of either mode, you can further add a Message Mapping step after that to refine it to the final structure that you want.

       

      The best way to know if it works in your case would be to try it out - if it works then you don't have to reinvent the wheel for such functionality.

       

      Regards

      Eng Swee

       

       

       

       

       

       

      Author's profile photo Dominic Beckbauer
      Dominic Beckbauer
      Blog Post Author

      Hi Eng Swee,

      thanks for your response. I directly tried out the content enricher. What is when my request needs a Request Message that is different from the payload that should be enriched?

       

      So I need the Message Mapping but the Original payload should be enriched. For me it seems like this just works for special cases. Is there a pattern to apply to solve this?

       

      Best regards

      Dominic

       

      Author's profile photo Eng Swee Yeoh
      Eng Swee Yeoh

      Hi Dominic

       

      Looks like for your specific case, the content enricher might not work directly since the request message to the additional system is not the same as the payload to be enriched.

       

      I guess it is still possible to achieve (since the modelling environment is so flexible), by using a content modifier step to store the original payload into a header/property before the enricher call, and then a script step after the call to join back the original payload with the response. Since there are additional steps involved, I wouldn't say one way is better than the other between this and your approach.

       

      Regards

      Eng Swee