Example for WebService Before Operation Rule

Hi,

I would like implement a WebServiceBeforeOperationRule rule to update a body request before provisioning task.

I’ve reviewed the following link to take some examples: Web Services Before/After Operation Rule - Compass (sailpoint.com) but the problem here is that I need manage XML format and all examples of link before are based on JSON format.

Where can I get a guide or any example to manage the objects in the rule if the body request is in XML format? How can I manage requestEndPoint object to return the new XML body?

Thanks in advance

1 Like

Hi @ismaelmoreno1 ,
For XML Format, you need to have the xml as a String object & then put this string into a Map. Below is an example:

Map bodyMap = new HashMap();
bodyMap.put(“bodyFormat”, “raw”);
String xmlBody = “”;
xmlBody += “>”; // append more details to the xmlbody if required
bodyMap.put(“jsonBody”, xmlBody); // put the xmlbody into Map
requestEndPoint.setBody(bodyMap); // set the request body with Map

1 Like

One way to parse XML format in a rule is to use the xpath library. Here is an example that parses identity attributes from a raw response object in an after operation rule:

import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;

import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Node;

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.core.config.Configurator;


ArrayList accountsToReturn = new ArrayList();	


if(rawResponseObject != null) {

	log.debug("rawResponseObject is not null" );
	InputSource inputXML = new InputSource(new StringReader(rawResponseObject));
	XPath xpath = XPathFactory.newInstance().newXPath(); 
	
	Map userDetailsMap = new HashMap();
	try {

			inputXML = new InputSource(new StringReader(response.toString()));
			String username = xpath.evaluate("/RESPONSE/SINGLE/KEY/MULTIPLE/SINGLE/KEY[@name=\"username\"]/VALUE/text()", inputXML);
			
			inputXML = new InputSource(new StringReader(response.toString()));
			String firstname = xpath.evaluate("/RESPONSE/SINGLE/KEY/MULTIPLE/SINGLE/KEY[@name=\"firstname\"]/VALUE/text()", inputXML);
			
			inputXML = new InputSource(new StringReader(response.toString()));
			String lastname = xpath.evaluate("/RESPONSE/SINGLE/KEY/MULTIPLE/SINGLE/KEY[@name=\"lastname\"]/VALUE/text()", inputXML);
			
			inputXML = new InputSource(new StringReader(response.toString()));
			String email = xpath.evaluate("/RESPONSE/SINGLE/KEY/MULTIPLE/SINGLE/KEY[@name=\"email\"]/VALUE/text()", inputXML);
				
			
			userDetailsMap.put("username",username);
			userDetailsMap.put("First Name",firstname);
			userDetailsMap.put("Last Name",lastname);
			userDetailsMap.put("Work Email",email);
				
			accountsToReturn.add(userDetailsMap);
				
	} catch (XPathExpressionException e) {
				// TODO Auto-generated catch block
				log.error("Exception occurred : " + e);
	  }
		
	
}

			
Map accountListMap = new HashMap();	
accountListMap.put("data", accountsToReturn);

return accountListMap;

You can also use a combination of xpath and XML dom to select fields from an XML object.

		import java.util.Map;
		import javax.xml.parsers.ParserConfigurationException;
		import javax.xml.xpath.*;
		import java.io.IOException;
		import java.io.StringReader;
		import java.util.ArrayList;
		import java.util.HashMap;
		import org.w3c.dom.Element;
		import org.w3c.dom.NodeList;
		import org.xml.sax.InputSource;
		import org.xml.sax.SAXException;
		
		//Create variable to hold list of parsed groups to return to IdentityNow
		ArrayList groupsToReturn = new ArrayList();

		if(rawResponseObject != null)
		{

			InputSource inputXML = new InputSource(new StringReader(rawResponseObject));

			//Create XPath		   
			XPath xpath = XPathFactory.newInstance().newXPath();
			
			//Parse response to get to embedded XML
			String response = xpath.evaluate("//*[local-name()='Envelope']/*[local-name()='Body']/*[local-name()='Response']/*[local-name()='response']", inputXML);
			response = response.trim();
			
			InputSource unwrappedXML = new InputSource(new StringReader(response));
			
			//Parse innerXML to get all roles
			NodeList nodes = (NodeList) xpath.evaluate("/Roles/Role", unwrappedXML, XPathConstants.NODESET);         
			
			//Walk through all roles		          
			for (int i = 0; i < nodes.getLength(); i++) {
				try {
					Element role = (Element) nodes.item(i);
					
					//Parse group attributes
					String currentGroupName = role.getElementsByTagName("Name").item(0).getTextContent(); 
					String currentGroupDescription =  role.getElementsByTagName("Description").item(0).getTextContent();
					String currentGroupEnabled = role.getElementsByTagName("Enabled").item(0).getTextContent();
					
					//Build map fur group we're currently processing
					Map currentGroup = new HashMap();
					currentGroup.put("Name", currentGroupName);
					currentGroup.put("Description", currentGroupDescription);
					currentGroup.put("Enabled", currentGroupEnabled);
					
					// Add group we built to the list of group to return.
					groupsToReturn.add(currentGroup);
				} catch (Exception error) {
					//skip current role if there was an error in parsing
					continue;
				}//end of catch
				
			}//end of roles for loop
			Map groupListMap = new HashMap();
			groupListMap.put("data", groupsToReturn);
			
			return groupListMap;
		}//end of if rawResponseObject = null
		else {
			return null;
		}
5 Likes

Thanks @colin_mckibben , @AnamicaShroti both solution are valid for me. Thanks for you help!

A post was split to a new topic: Before rule executes twice during account aggregation