Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member26700
Participant

When implementing SuccessFactors integrations using Boomi we commonly define cache's and Picklist lookups.  The following example describes how to replicate the lookup feature using the HCI platform. 


In this example we are going to replace code values in inbound XML with descriptions. We have hard-coded picklist entities in Hashmap and Key is Custom-Object. This is very important information in this solution.Custom-Object is a Groovy class that identifies different kinds of Picklists (eg. CountryCode, EventReason, etc.).  The Groovy class (Custom-Object) will be placed in the "main.resoruces.script" folder.

Step 1:
______

Define Groovy class (Custom-Object) and override equals and hashCode methods of object and place the Groovy/Object file in  "main.resoruces.script" folder.

 




Contents of Custom Object, Groovy class:

package src.main.resources.script

class KeyMapping {
private String str1;
private String str2;
public KeyMapping(String string, String string1) {
this.str1 = string;
this.str2 = string1;
}
//@Override
public boolean equals(Object obj) {
return obj.str1.equals(str1) && obj.str2.equals(str2)
}
//@Override
public int hashCode()
{
return (str1 + str2).hashCode();
}
}


Contents of Inbound message:

<xml>
<person>
<name>gbk</name>
<code>US</code> <!-- Picklist code that will be repalced with Description -->
</person>
<person>
<name>user1</name>
<code>UK</code> <!-- Picklist code that will be repalced with Description -->
</person>
<person>
<name>user2</name>
<code>JP</code> <!-- Picklist code that will be repalced with Description -->
</person>
</xml>

Step 2:
______


Next step is to initialize Hashmap object that will hold Picklist Entities. This Hashmap will hold our Custom-Object as Key and value mapping.


import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import src.main.resources.script.KeyMapping;

def Message processData(Message message) {
HashMap<KeyMapping, String> cacheData = new HashMap<KeyMapping, String>();
message.setHeader("cacheEntity",cacheData);
return message;
}

Step 3:
______



Contents of load cache:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import src.main.resources.script.KeyMapping;

def Message processData(Message message) {

//body
def body = message.getBody();

def map = message.getHeaders();
//Get initialized cached entity form Header
HashMap<KeyMapping, String> cacheData = map.get("cacheEntity");

//to get all externalParameters defined.
def propertyMap = message.getProperties()

//Example to add pickList_Name (CountryCodes) and ExternalCode
KeyMapping one = new KeyMapping("CountryCodes","US");
KeyMapping two = new KeyMapping("CountryCodes","UK");
KeyMapping three = new KeyMapping("CountryCodes","JP");

//Setting the pickLists to Cache entity
cacheData.put(one,"United States");
cacheData.put(two,"United Kingdom");
cacheData.put(three,"Japan");

//set cache object in Header Set Picklist back to Header with same property that we initialized in step 2
message.setHeader("cacheEntity",cacheData);

return message;
}

Step 4:
______

Now that we loaded data into Cache Entity (Look up object) next step is replace code values in inbound XML with actual description.

For this to happen we first construct key for look-up with our Custom-Object and pass this key object to HaspMap entity to read Description for the key object.



Contents of Lookup:

 
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import java.lang.StringBuffer;

import java.io.InputStream;
import org.jaxen.jdom.JDOMXPath;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

import src.main.resources.script.KeyMapping;

def Message processData(Message message) {

//Body
def body = message.getBody(java.lang.String);

def messageLog = messageLogFactory.getMessageLog(message);

//to get all externalParameters defined.
def propertyMap = message.getProperties()

//Headers , Get cached data from Header set in step 3
def map = message.getHeaders();
def pickList = map.get("cacheEntity");

//Lookup and replace the message contents
def finalStr = evaluateMessage(body, pickList, message);
message.setBody(finalStr);

return message;
}

//Function to lookup and replace Code with Description
def String evaluateMessage(String body, HashMap pickList, Message message){

SAXBuilder builder = new SAXBuilder();
InputStream is = new ByteArrayInputStream(body.getBytes("UTF-8"));
Document doc = builder.build(is);

def xPathCode = new JDOMXPath("//person");
def messageLog = messageLogFactory.getMessageLog(message);

for (Element child : xPathCode.selectNodes(doc)) {
//Get all elements with code and replace with Desc
if(child.getChild("code")!=null){
//replace with picklist
String code = child.getChild("code").getText();
//Construct Key with code and retireve Description PickList:CountryCodes
KeyMapping vo = new KeyMapping("CountryCodes",code);
String desc = pickList.get(vo);
//update inbound node with Desc
child.getChild("code").setText(desc);
}

}
XMLOutputter outputter = new XMLOutputter();
def xmlString = outputter.outputString(doc);
return xmlString;
}

 

Step 5:
______

Updated inbound XML with description in Datastore or SFTP.
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<person>
<name>gbk</name>
<code>United States</code> <!-- Udpated with Desc -->
</person>
<person>
<name>user1</name>
<code>United Kingdom</code> <!-- Udpated with Desc -->
</person>
<person>
<name>user2</name>
<code>Japan</code> <!-- Udpated with Desc -->
</person>
</xml>


Thanks,
Bhargav
19 Comments
Sriprasadsbhat
Active Contributor
Hello Bhargav,

Thanks for sharing very nice blog.

Regards,
Sriprasad Shivaram Bhat
Looks excellent, Bhargav!  The lookup functionality is so key for many integration use cases and sharing this flexible approach will be a great additional for anybody's HCI tool belt. Thanks!
-Wes
Former Member
0 Kudos
Hello Bhargav,

Thanks for sharing this .

I have requirement of replicating marketing attributes from C4C to Hybris marketing via HCI , so i need to use lookup to differentiate account and contact data from source ,same requirement is achieved in PO via RFC lookup but i am not sure how to do this in HCI , Can you please help me on this.

Regards,

Ashwini

 
former_member26700
Participant
0 Kudos
HI @Ashwini Sharma,

 

Please connect with me and we can discuss the approach.

 

Thanks,

-Bhargrav
Former Member
0 Kudos
Hello Bhargava,

Please let me know how to connect with you to discuss this requirement , please send your availability details on my mail id ashwini.sharma@ibm.com

Thanks ,

Ashwini

 
Former Member
0 Kudos
Sorry for delayed response , My id is ashwini.sharma@in.ibm.com
Former Member
0 Kudos
Bhargav!!! Buddy, long time, no talk!  GREAT blog.  Thanks for sharing.  I will be putting this cache option into use this week.

 
former_member26700
Participant
0 Kudos
Great. Glad it is useful.

-Bhagav
former_member20702
Discoverer
0 Kudos
Hey Bhargav,

I'm getting error on last groovy script which calls, jdom....

for example,

import org.jdom.Document;

gives error:

unable to resolve class org.jdom.Document

I also tried with org.jdom2.Document and received same error.

Any thoughts?

 

~Belinda
former_member20702
Discoverer
0 Kudos
I figured out the jdom issue.  I downloaded the jdom binaries from:

http://www.jdom.org/downloads/index.html

.

I downloaded the jdom 1.1.3 and then copy and pasted to the folder in src.main.resources.script and then right click --> build Path --> add to build Build path.

-Belinda

 
former_member26700
Participant
0 Kudos
Nice. Thanks for updating the post. I just noticed your initial request 🙂

 

Bhargav
former_member20702
Discoverer
0 Kudos
Hey Bhargav,

Do you have example using query response input instead of hard code for the KeyMapping entries?

Thanks,

Belinda
former_member26700
Participant
0 Kudos
Hi Belinda,

I don't have query response but I believe it  should be straight forward. Connect with me offline to discuss.

Thanks,

Bhargav
Former Member
0 Kudos
our requirement is to use 2 query types to fetch the data from Success Factors

. Full mode : which picks up the empoyee's completed history of records for example : employee's complete history of Compensation information which we need to store in some temporary storage along with a primary key say Emplyee id

Person id 100 has 2 pay components say monthly salary and Bonus. I need to store this in the same format so that in the next step when my delta query mode picks only the modified record lets say persond is 100 has some changes like address change along with Paycomponent change in this case my delta query can go and retrieve the stored information using the primary key i e Person id (100) and corresponding paycomponent details

In Dell Boomi we use Add to cache step to store the information with a primary key . Later this information can be retrieved by passing the primary key and fetching the stored data.

Thanks in advance

Mahesh

 
Former Member
0 Kudos
 

Hello Bhargav,

Thanks for sharing a useful piece of information on custom lookups!

I tried to implement the solution in Web UI. But when I deploy the Integration, I get the below error in message monitoring

javax.script.ScriptException: org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed: script2__Script.groovy: 17: unable to resolve class src.main.resources.script.KeyMapping @ line 17, column 1. import src.main.resources.script.KeyMapping;

I tried to analyze the issue. In the blog, you have Implemented the solution in Eclipse. It is working perfectly fine in eclipse. You have used src.main.resources.script folder to import the script for KeyMapping. But, in Web UI how do we implement the same? Kindly, help me with this.

Have a nice day!

Best Regards,

Narasimha Kamath Ardi.
former_member26700
Participant
0 Kudos
Thanks Narashima.

 

I’ve to explore WebUI part. But, build this in eclipse and import back into ‘WebUI’ and check if it resolves the issue.

Keep us posted on results.

Bhargav
Former Member
0 Kudos
Hello Bharghav,

Thanks a lot for replying!

Yes, it did work. The problem was- the script KeyMapping.groovy which was used to override equals and hashcode had different name say Script123.groovy in the WebUI. Since Keymapping code is imported in all the three steps (initialize, load and update), I changed name of the script to KeyMapping.groovy and it did work successfully. But, when I change the name to something else it did throw the above error. To sum it up, since KeyMapping is imported in the major steps either keep the name as KeyMapping.groovy else change to the desired name in all the steps where KeyMapping is being used including KeyMapping.groovy.

Have a nice day!

Best Regards,

Narasimha Kamath Ardi.
0 Kudos
Hi Bhargav,

Your article is really great and helps us. We are working for one our client and client has some issue on Tenant performance, so they open the ticket with SAP.

SAP review our integration and the most amazing thing they said is don't use the class in your integration it will keep the place in native memory. we argue with them like we are following one of your expert solutions, but SAP disagrees with your custom solution to work with a class, SAP suggests us use the script instead of class.

Any comments on SAP suggestion, we have to rework on all integration where we implement this.

 

Thank you

Wajahat Imam
former_member26700
Participant
0 Kudos
Hi Imam,

I was brought to this attention internally after they reviewed your process. Since product is suggesting this and also since we saw performance issues, you might have to follow their advise.

Please update blog with your changes.

Thanks,

-Bhargav