Skip to Content
Technical Articles

Fetching picklists from SuccessFactors and implementing custom lookup using Groovy Script in CPI

Introduction

In this blog, we will see how a SuccessFactors picklist lookup can be implemented and consume the picklist <key – value> pairs in the incoming XML and further message processing using SAP cloud platform integration in details.

 

Here, we will generate the output XML as shown below from input XML, where the values of three XML elements will be replaced with their keys.

In this case, values of TITLE, BLOOD_GROUP and Address_type fields need to be updated from picklists salutation, bloodGroup and addressType respectively.

It is important to understand that the <key-value> pair for addressType and salutation picklists would be <OptionId – en_US> but in case of bloodGroup picklist, <key-value> pair would be <external_code – en_US>. This difference can found in Groovy Script in step7.

Example of a few picklists exported from SuccessFactors:

The picklists pairs are highlighted which are being consumed in our scenario.

 

Description

The complete iFlow which is further explained step by step, here it is just to give you an overview that there’re basically two Local Integration Processes:

  • In first Local Integration Process(SF Picklist from lookup), we are fetching the required picklists in XML format and storing the same in global variable in CPI.

Alternative: You can also design a separate iFlow for SF lookup according to your business requirement.

  • In second Local Integration Process(Picklist Conversion), the required output XML message is generated by modifying the data with the help of custom object(Groovy Script).

 

Step1:

  • Start Timer 1 will trigger the execution of local process call SF Picklist from lookup.
  • Request Reply sfapi call is used to query the picklists from SuccessFactors using below configuration:

 

Step2:

  • Printing the XML payload fetched from SuccesFactors as an attachment using below code:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;

def Message processData(Message message) {
    def body = message.getBody(java.lang.String) as String; //get message body as String
    def messageLog = messageLogFactory.getMessageLog(message); 
    if(messageLog != null){ 
        messageLog.setStringProperty("Logging#1", "Printing Payload As Attachment") //set property for log
        messageLog.addAttachmentAsString("SF_Picklist:", body, "application/xml"); //generate attachment with content type application/xml
     }
    return message;
}

Result: The screenshot of XML payload attachment is provided below which contains various picklists.

 

Step3:

  • Store Picklist is variable which is configured to store picklist payload globally in CPI.

Result: Globally stored variable. Now we are open to consume this variable from any of the iFlows running in CPI.

 

Step4:

  • After a successful execution of local integration call, processing of content modifier Sample input payload in Main Integration Flow will take place.

Below sample input payload in XML format is passed for further processing. You can also connect to an external system for input XML data.

 

Step5:

  • We also need to check whether required input payload is coming or not as per our requirement. Here We’re checking if results XML tag is coming with data.

  • An attachment is generated for input payload which already shown in previous step.
  • A local integration call is processed for picklist conversion described in next step.

 

Step6:

  • In content modifier GV Picklist, a property is created to access the picklists from global variable which was stored in step3.

  • Input payload coming from Main Integration Flow is passed further as it is.

 

Step7:

  • Below Groovy Script is provided which is basically accessing the XML picklists from message property and input payload from message body.

Note: OptionId is represented by id in Groovy Code.

import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.xml.XmlUtil;
import groovy.util.XmlParser;
def Message processData(Message message) {
		
		//message Body 
		def records = message.getBody(java.lang.String) as String;
		
		//accessing Global_picklist from Properties
		def map = message.getProperties();
		def picklist = map.get("Global_Picklist");
		
		// Define XML parser and builder for picklist and records
		def xlm_records = new XmlParser().parseText(records);
		def xml_picklist = new XmlParser().parseText(picklist);
		
		
//getting picklist values in HashMaps------------------------------------------------------------
		
		//bloodGroup
		HashMap<String, String> bloodGroup = new HashMap<String, String>();	//create a new Hashmap object
		xml_picklist.PicklistOption.findAll { p ->
			p.picklistId[0].text().toString().equals("bloodGroup")		//finding all bloodGroup picklistid entities
		}.each { p ->
			bloodGroup.put(p.externalCode[0].text().toString(),(p.en_US[0].text().toString().toUpperCase())) //put all key(externalCode) value(en_US->UpperCase) pairs in Hashmap
		}
		
		//salutation
		HashMap<String, String> salutation = new HashMap<String, String>();	//create a new Hashmap object
		xml_picklist.PicklistOption.findAll { p ->
			p.picklistId[0].text().toString().equals("salutation")		//finding all salutation picklistid entities
		}.each { p ->
			salutation.put(p.id[0].text().toString(),(p.en_US[0].text().toString().toUpperCase())) //put all key(id) value(en_US->UpperCase) pairs in Hashmap 
		}
		
		//addressType
		HashMap<String, String> addressType = new HashMap<String, String>();	//create a new Hashmap object
		xml_picklist.PicklistOption.findAll { p ->
			p.picklistId[0].text().toString().equals("addressType")		//finding all addressType picklistid entities
		}.each { p ->
			addressType.put(p.id[0].text().toString(),(p.en_US[0].text().toString().toUpperCase())) //put all key(id) value(en_US->UpperCase) pairs in Hashmap 
		}
		
		
		
		
//Updating corresponding keys into the xml records---------------------------------------------------------
		
		//loop for multiple records in message body
		int result_size = xlm_records.results.size();
		int count = 0;
		while(count < result_size)
		{	
			//----------------------------------------Blood group---------------------------------------------------------------------
			def check_exist_bloodGroup = xlm_records.results[count].BLOOD_GROUP.isEmpty(); // Checking if exists
			if(check_exist_bloodGroup.toString().equals("false")){
				def temp_variable = xlm_records.results[count].BLOOD_GROUP.text().toString().toUpperCase();	//get value of blood Group in UpperCase in temp_variable
				for (Map.Entry<String, String> entry : bloodGroup.entrySet()) {	//looping bloodGroup Hashmap to search corresponding value
					   if(entry.getValue().equals(temp_variable)){		//Finding value of temp_variable in corresponding hashmap
						   def lv_val = entry.getKey().toString();		//access and store corresponding key in lv_val variable 
						   xlm_records.results[count].BLOOD_GROUP[0].value = lv_val;	//replace value of particular xml element with unique key
					   }
					}
			} //IF End for Blood group
		
			//-------------------------------------------Salutation-------------------------------------------------------------------------
			def check_exist_saluation = xlm_records.results[count].TITLE.isEmpty(); // Checking for Title, is exists
			if(check_exist_saluation.toString().equals("false")){
				def temp_variable = xlm_records.results[count].TITLE.text().toString().toUpperCase();	//get value of Title in UpperCase in temp_variable
				for (Map.Entry<String, String> entry : salutation.entrySet()) {	//looping bloodGroup Hashmap to search corresponding value
					   if(entry.getValue().equals(temp_variable)){		//Finding value of temp_variable in corresponding hashmap
						   def lv_val = entry.getKey().toString();		//access and store corresponding key in lv_val variable 
						   if(lv_val.contains("-")){
						   lv_val = entry.getKey().toString().split("-");	//removing unwanted piece of from string if any
						   xlm_records.results[count].TITLE[0].value = lv_val[1];		//replace value of particular xml element with unique key
						   }
						   else{
						   xlm_records.results[count].TITLE[0].value = lv_val;
						   }
					   }
					}
			} //IF End for TITLE
			
			//-------------------------------------------Address_type-------------------------------------------------------------------------
			def check_exist_addresstype = xlm_records.results[count].Address_type.isEmpty(); // Checking for Title, is exists
			if(check_exist_addresstype.toString().equals("false")){
				def temp_variable = xlm_records.results[count].Address_type.text().toString().toUpperCase();	//get value of Title in UpperCase in temp_variable
				for (Map.Entry<String, String> entry : addressType.entrySet()) {	//looping bloodGroup Hashmap to search corresponding value
					   if(entry.getValue().equals(temp_variable)){		//Finding value of temp_variable in corresponding hashmap
						   def lv_val = entry.getKey().toString();		//access and store corresponding key in lv_val variable
						   if(lv_val.contains("-")){
						   lv_val = entry.getKey().toString().split("-");	//removing unwanted piece of from string if any
						   xlm_records.results[count].Address_type[0].value = lv_val[1];		//replace value of particular xml element with unique key
						   }
						   else{
						   xlm_records.results[count].Address_type[0].value = lv_val;
						   }
					   }
					}
			} //IF End for TITLE

		count++;
		}
		
// Generating response payload attachment
		def newXml = XmlUtil.serialize(xlm_records);
		def messageLog = messageLogFactory.getMessageLog(message);
		if(messageLog != null){
		messageLog.setStringProperty("Logging#1", "Printing Payload As Attachment")
		messageLog.addAttachmentAsString("XMLresponse:", newXml, "text/plain");
	 }
//Set output with the upadted xml
	message.setBody(newXml);
	return message;
}
  • The key-value pairs are stored in Hashmap as described in the code.

Result: The output payload produced by the above Groovy Script is the final required XML payload which is then printed as an attachment by custom Groovy code as follows:

 

Conclusion

In this way, we have called the picklists from SuccessFactors in XML format, stored in the global variable of SAP CPI, passed a sample XML payload for message processing then accessed picklists from global variable in a newly created property and finally XML payload is modified as required with the help of custom object Groovy Script.

You can utilize the above design and Groovy codes according to your requirement.

 

Thanks and Regards,

Ravi Jangra

4 Comments
You must be Logged on to comment or reply to a post.
  • Hi Ravi,

    It is really helpful, So many time we need this in CPI Integration.

    I have to ask why you did not use Data store to store the picklist data as it reads form database. key-value will be easy to fetch.

    also picklist data is heavy so, will it effect other iFlow processing time?

    Good luck!

    • Hi Aman,

      Thanks for your feedback and asking the question.

       

      Basically, You can use Data Store or Write Variable to store your transactional data for a limited period of time which you have to configure.

      If you would like to store Key-Value pairs and use it in an iflow later on, you can go for Write Variable flowstep. I’m using it just to explain the functionality of picklist processing and also my picklist data is too less.

      In case if you have a heavy data to be stored(regardless of picklist), Data Store flowstep would be a good option for you as it offers multiple standard operations i.e. Write, Get, Select and Delete.

      But in addition to that, Database access can slow down the message processing if you have a heavy data payload stored and eventually it will affect your processing time in all of those iFlows where data is being stored or performed other operations on DB.

      In cases of high payload processing, multiple DB operations can cause exceptions.

      I hope this answers your question.

      Best Regards,

      Ravi