Introduction
Hi Everyone,
New year is here, and a lot of new year resolutions must have been set by all of us. I also came up with something new, not a new resolution but a new technique to make the integration a bit easier for everyone of you.
In my last
blog post, basically I wrote about how we can route message without using a router.
This blog is also on the similar lines and today I thought of taking it a step further.
Problem Statement
To send the message to multiple receivers in SAP Cloud Integration we use a multicast and if there are different conditions to be implemented or if the logic is a bit more complex and we use Process Direct functionality to call multiple IFlows along with sending data to multiple receivers, sometimes the readability of the flow is compromised
Figure (below) shows how a IFlow looks like with just router and multicasts…
Image Source: SAP BTP Trial Account
As shown in the figure above, to send the IDoc to a particular receiver we access the control data and identify the IDoc type, then use a router to route the message, but if the same IDoc needs to go to multiple destinations we must use a Multicast.
What if in future,
- There is a need to insert an addition IDoc type?
As we already know, we will have to edit and redeploy this IFlow, which proves to be a tedious task and highly not recommended in the live system where thousands of messages pass daily and making changes in the IFlow can affect the Business as Usual (BAU) activities. This may lead to multiple message failures, increase of the ticket counts and worse, loss of business or worse, monetary loss for the client.
2. There is a need to change the Process Direct address?
Yes, you are right this can be achieved using configurable parameter, but today I will show you one more way.
Solution Approach
If you have read my last
blog post, we already know that the issues mentioned above can be easily taken care of using:
- Groovy Scripting and,
- Value Mapping
And the same IFlow will look like this:
Image Source: SAP BTP Trial Account
The idea is on the similar lines, to use the Value Mapping for configuring the addresses and whenever we want to add or remove any IDoc Type in the IFlow, it can be done by just changing the Value mapping, rather than changing the complete IFlow.
Step by Step Logic
- Create 4 new properties in the Content Modifier, MESTYP, DOCTYP and SENDER, and read the values of IDoc Message Type, IDoc Type and Sender from the IDoc Control Data (EDIDC) segment respectively using XPath,
- We will take the IDoc control data as input of the Groovy,
- The required information is the Source, Message Type and the IDoc Type stored in the respective Exchange Properties,
- In the groovy script we will access the Value mapping and get the corresponding Process Direct address to the next IFlow for the particular receiver,
- Then we will write the address of the next IFlow for the particular receiver in the Headers as shown below.
The
Value Mapping for this solution will look like this:
Image Source: SAP BTP Trial Account
Groovy Code:
import java.util.HashMap;
import com.sap.it.api.ITApi.ValueMappingApi;
import com.sap.it.api.ITApiFactory;
import com.sap.it.api.mapping.ValueMappingApi;
import com.sap.gateway.ip.core.customdev.util.Message;
def Message checkReceiversMulti(Message message) {
// Get ValueMapping API
def api = ITApiFactory.getApi(ValueMappingApi.class, null);
def messageLog = messageLogFactory.getMessageLog(message);
if (api == null) {
throw new Exception("Could not retrieve ValueMappingAPI.");
}
// Get headers
map = message.getHeaders();
String MESTYP = map.get("MESTYP");
String DOCTYP = map.get("DOCTYP");
String Sender = map.get("Sender");
// Read MultiCast with Counter Value from Value Mapping
String value = api.getMappedValue(Sender, MESTYP, "ESB", DOCTYP,"Receivers" );
// Check if self-referencing value matches the subject
if (value == null ) {
throw new Exception("Could not retrieve ValueMappingAPI.");
}
def list = value.split('_').collect{it as String}
String prefix = list.get(1);
Integer counter = Integer.parseInt(list.get(2));
for(int i = 1;i<=counter;i++){
String receiver = api.getMappedValue(Sender, MESTYP, prefix + Integer.toString(i), DOCTYP,"Receivers" );
message.setHeader(prefix + Integer.toString(i), receiver); //ESB1, ESB2 in this example
receiver = "";
if(messageLog != null)
{
messageLog.setStringProperty("log1", prefix + Integer.toString(i))
//messageLog.addAttachmentAsString("log1",body,"text/plain");
}
}
return message;
}
Later the header “ESB1” and “ESB2” can be dynamically called in the Process Direct connectors of Receiver A and Receiver B respectively using Apache Camel expression:
Images Source: SAP BTP Trial Account
Summary
This approach increases the readability of the IFlow, along with other benefits, like the IFlow becomes more efficient and scalable.
This approach is just an example to help you start thinking in this direction and can be modified as per your need, for example if you have more receivers in your scenario, you would just need to make a slight change in the Value mapping and voila, your solution will be ready.
Hope this was useful.
Thanks and Regards,
Aayush Aggarwal