How to copy data across multiple branches of Multicast in SAP CPI
Introduction:
Recently came across multiple SCN threads looking for how to copy the data across multiple branches of Multicast in SAP CPI, so this is how we can achieve the same with small example using HashMap.
Scenario:
We will be creating below sample scenario where we are passing some test data to multiple branches where each branch has its own set of transformations based on some key value and at the end of the Message processing data from both the branches needs to be merged and sent to Target side.
Step 1:
Content modifier with sample data.
<Root>
<Record>
<Field1>F1</Field1>
<Condition>X</Condition>
<Field2>F2</Field2>
<Field3>3</Field3>
</Record>
<Record>
<Field1>F11</Field1>
<Condition>X</Condition>
<Field2>F21</Field2>
<Field3>31</Field3>
</Record>
<Record>
<Field1>F12</Field1>
<Condition>Y</Condition>
<Field2>F22</Field2>
<Field3>32</Field3>
</Record>
<Record>
<Field1>F13</Field1>
<Condition>X</Condition>
<Field2>F23</Field2>
<Field3>33</Field3>
</Record>
<Record>
<Field1>F14</Field1>
<Condition>Y</Condition>
<Field2>F24</Field2>
<Field3>34</Field3>
</Record>
<Record>
<Field1>F15</Field1>
<Condition>N</Condition>
<Field2>F25</Field2>
<Field3>345</Field3>
</Record>
<Record>
<Field1>F16</Field1>
<Condition>N</Condition>
<Field2>F26</Field2>
<Field3>346</Field3>
</Record>
</Root>
Step 2:
Script to initiate the Hash Map which is used in both the branches.
Script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
//Body
def body = message.getBody();
def str=body.toString()
//Initiate HashMap and assign it to Header
HashMap<String, String> hmap1 = new HashMap<String, String>();
message.setHeader("cacheEntity",hmap1);
return message;
}
Step 3:
Content filter which filters certain set of data in my case data having Condition field value “X”.
Step 4:
In my case I will not be doing much transformation so storing the data after filter into hash map which can be used in second branch.Below Script pulls the hash map that was initialized in Step 2 and overwrites the content of it.
Script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
//Body
def body = message.getBody();
def str=body.toString()
def map = message.getHeaders();
//Get initialized cached entity form Header
HashMap<String, String> cacheData = map.get("cacheEntity");
cacheData.put("Branch1",str)
message.setHeader("cacheEntity",cacheData);
return message;
}
Step 5:
Content filter which filters certain set of data in my case data having Condition field value “Y”.
Step 6:
Now we have second branch data ready and need to send the data from both the branch together to target system.Below script will do the concatenation of both the data( one set from Branch Y and another from Branch X ).
Script:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
def Message processData(Message message) {
//Body
def body = message.getBody();
def map = message.getHeaders();
def output = map.get("cacheEntity");
def value=output.get("Branch1")
def TargetData = "<Output>"+body+value+"<\\Output>"
message.setBody(TargetData);
return message;
}
Output Generated:
<Output>
<Root>
<Record>
<Field1>F12</Field1>
<Condition>Y</Condition>
<Field2>F22</Field2>
<Field3>32</Field3>
</Record>
<Record>
<Field1>F14</Field1>
<Condition>Y</Condition>
<Field2>F24</Field2>
<Field3>34</Field3>
</Record>
</Root>
<Root>
<Record>
<Field1>F1</Field1>
<Condition>X</Condition>
<Field2>F2</Field2>
<Field3>3</Field3>
</Record>
<Record>
<Field1>F11</Field1>
<Condition>X</Condition>
<Field2>F21</Field2>
<Field3>31</Field3>
</Record>
<Record>
<Field1>F13</Field1>
<Condition>X</Condition>
<Field2>F23</Field2>
<Field3>33</Field3>
</Record>
</Root>
<\Output>
Conclusion:
Since the headers or properties set in first branch not accessible in second or further branches above solution will help to overcome that issue.
Thanks to Eng Swee Yeoh for the wonderful blog where he explains the above behavior with below Conclusion.This still holds good for my blog also.!
Header/Property Object Type | Created In | Accessible in Subsequent Branch | Modifications in Predecessor Branch seen in Subsequent Branch |
java.lang.String | Main route | Yes | No |
java.util.HashMap | Main route | Yes | Yes |
Any | Multicast branch | No | N/A |
Thanks Praveen Tirumareddy for your as usual great support:)
Hope this helps SAP CPI beginners!
Regards,
Sriprasad Shivaram Bhat
Hi Sri,
Good one. Keep blogging !
thanks and regards,
Praveen T
Hi Sri,
Good one as always 🙂 Thanks!
Regards,
Karthik
Hi Sri
Great Work. Thanks For Sharing!!
Regards
Gagan
Thanks Sri.
Good one as always ? Thanks!
Regards,
Ashwini
Very Nice Blog 🙂
Thank you..
Venu
Hello Sriprasad,
I tried the scenario as described but the output i get at the end of Step 6 is <Output>net.sf.saxon.dom.DOMNodeList@1e388df4<\Output> and not what is expected.
Why would this be so? Also, if i initiate and set a Hashmap value inside a sequential multicast branch of a local integration process; will it be readable after the join step in the calling integration process?
Regards,
Diptee
Hello Diptee Sawant,
I too tried the scenario and got the same same output as you mentioned. If you got any solution, can you help me with that.
Regards
Leenu
Thanks for the details. I should have seen this posting little early. Just recently I ran into a scenario where I need to access hashmap object in a different branch of sequential multicast. After so much of struggle, I eventually realized that I cannot access hashmap from previous branch.
So, I ended up with a workaround of storing that payload. At a later stage, where I needed that data, I used a content modifier to get it back and handed over to the content to next process. (Just not in the form of a hashmap, but in a property value format).