This rule is used to calculate attributes before a web-service operation call.
Argument | Type |
Purpose |
application | sailpoint.object.Application |
Application whose data file is being processed. |
provisioningPlan | sailpoint.object.ProvisioningPlan |
Used to update the payload of the http request. Provisioning plan has an account request which defines the operation to be performed on the account. An account request can contain multiple attributes requests and each attribute request represents an operation on a single account attribute. This argument enables the user to update the body/payload or URL attributes of endpoint object using the provisioningPlan information. |
requestEndPoint | sailpoint.connector.webservices.EndPoint | Current request information; contains the header, body, context url, method type, response attribute map, successful response code |
restClient | sailpoint.connector.webservices.WebServicesClient | This is a WebServicesClient (HttpClient) object that would enable the user to call Web Services API to target system. |
oldResponseMap | java.util.Map | The response object returned from earlier endpoint configuration of same operation type like Account Aggregation, Get Object and so on. |
Argument | Type |
Purpose |
EndPoint / Map | sailpoint.connector.webservices.EndPoint / sailpoint.connector.webservices.Map |
The rule allows user to return the Endpoint object (requestEndPoint) or a map. The map can hold updatedEndPoint and connectorStateMap keys where the value expected is Endpoint (requestEndPoint) and connectorStateMap object respectively. The connectorStateMap object is a map that contains key and value of the attribute that must be updated in the application through rule. |
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="WebServiceBeforeOperationRule">
<Description>Describe your rule here.</Description>
<Source><![CDATA[
// Add your logic here.
]]></Source>
</Rule>
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule name="Example Rule" type="WebServiceBeforeOperationRule">
<Description>This rule is used by the Web Services connector before performing any operation like testconnection, aggregation etc.</Description>
<Source><![CDATA[
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import connector.common.JsonUtil;
import connector.common.Util;
import sailpoint.connector.webservices.EndPoint;
import sailpoint.connector.webservices.WebServicesClient;
import sailpoint.object.Application;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
Map body = requestEndPoint.getBody();
String jsonBody = (String) body.get("jsonBody");
log.info("Rule - Modify Body: running");
try {
Map jsonMap = JsonUtil.toMap(jsonBody);
if (jsonMap != null) {
Object roleEntry = jsonMap.get("webSiteAndRole");
String role = "";
if (roleEntry != null && roleEntry instanceof ArrayList) {
ArrayList rolesArray = (ArrayList) roleEntry;
if (rolesArray.size() > 0) {
role = (String) rolesArray.get(0);
}
} else if (roleEntry != null) {
role = (String) roleEntry;
}
jsonMap.remove("webSiteAndRole");
jsonMap.put("webSiteAndRole", role);
log.info("Rule - Modify Body: setting webSiteAndRole = " + role);
String webID = "";
if (provisioningPlan != null) {
log.info("Rule - Modify Body: plan is not null");
for (AccountRequest accReq : Util.iterate(provisioningPlan.getAccountRequests())) {
log.info("Rule - Modify Body: iterating over account requests");
for (ProvisioningPlan.AttributeRequest attReq : Util.iterate(accReq.getAttributeRequests())) {
log.info("Rule - Modify Body: iterating over attribute requests");
String attrName = attReq.getName();
String value = null;
if (attrName != null && "webId".equalsIgnoreCase(attrName)) {
webID = (String) attReq.getValue();
log.info("Rule - Modify Body: setting webID = " + webID);
}
}
}
} else {
log.info("Rule - Modify Body: plan is null");
}
if (!"".equals(webID)) {
jsonMap.put("webID", webID);
}
// Add in any other missing fields that are required
if (!jsonMap.containsKey("webLogonEmail")) {
jsonMap.put("webLogonEmail", "");
}
if (!jsonMap.containsKey("taxID")) {
jsonMap.put("taxID", "");
}
if (!jsonMap.containsKey("taxIdType")) {
jsonMap.put("taxIdType", "");
}
if (!jsonMap.containsKey("actorLogonId")) {
jsonMap.put("actorLogonId", "");
}
String finalBody = JsonUtil.render(jsonMap);
body.put("jsonBody", finalBody);
requestEndPoint.setBody(body);
}
} catch (Exception ex) {
log.error("Rule - Modify Body: " + ex);
}
return requestEndPoint;
]]></Source>
</Rule>
This section describes the following types of Web Services class:
NOTE: The Web Services Classes mentioned in this section are general guidelines. New classes/methods would be added.
The following table list the different rules and their description:
Rule | Description |
Constructor Detail |
|
WebServicesClient |
Default constructor. public WebServicesClient() Constructor that configures the client using the given args. public WebServicesClient(java.util.Map args) throws java.lang.Exception Throws: java.lang.Exception |
Method Detail | |
configure |
Configure connection parameters. See the ARG_* constants. public void configure(java.util.Map args) throws java.lang.Exception Throws: java.lang.Exception |
executeGet |
Returns: Response object Throws: java.lang.Exception |
executePost |
Returns: Response object Throws: java.lang.Exception |
executePut |
Returns: Response object Throws: java.lang.Exception |
executePatch |
Returns: Response object Throws: java.lang.Exception |
getResponseHeaders |
Get last executed Request's Response headers. public java.util.Map<java.lang.String,java.lang.String> getResponseHeaders() |
executeDelete |
Returns: Response object Throws: java.lang.Exception |
The following table list the different rules and their description:
Rule |
Description |
Constructor Detail |
|
EndPoint |
public EndPoint() |
Method Detail |
|
setAfterRule |
Setting the after rule name public void setAfterRule(java.lang.String value) |
setBeforeRule |
Setting the before rule name public void setBeforeRule(java.lang.String value) |
setParseRule |
public void setParseRule(java.lang.String value) |
setContextUrl |
Set the context url for the particular operation (create user, update user, account aggregation, and so on) public void setContextUrl(java.lang.String value) |
setHttpMethodType |
Set the http method (put, post, get, patch and delete) for the particular operation (create user, update user, account aggregation, and so on) public void setHttpMethodType(java.lang.String value) |
setOperationType |
Set the operation (Account Aggregation, Group Aggregation, Create Account etc) for the particular operation record (create user, update user, account aggregation, and so on) public void setOperationType(java.lang.String value) |
setRootPath |
Set the root of the JSON response returned from the managed system (Managed system) for the particular operation (create user, update user, account aggregation, and so on) public void setRootPath(java.lang.String value) |
setFullUrl |
set the complete url (endpoint) of the operation that need to be performed for the particular operation (create user, update user, account aggregation, and so on) public void setFullUrl(java.lang.String value) |
setBaseUrl |
Set the base url (the machine id or IP and the port where the service is executing) for the operation that need to be performed. Ideally this would be common for all the operation. public void setBaseUrl(java.lang.String value) |
setSequenceNumberForEndpoint |
Set the Sequence number particular operation (create user, update user, account aggregation, and so on) public void setSequenceNumberForEndpoint(int value) |
setUniqueNameForEndPoint |
Set Unique operation name for particular operation (create user, update user, account aggregation, and so on) public void setUniqueNameForEndPoint(java.lang.String value) |
setResMappingObj |
Set the Response mapping for the response attribute returned in the JSON response from the managed system (Managed system) for the particular operation like create user, update user, account aggregation, and so on. Here the key would be attribute name (attribute in the schema) and value would be the JSON response path after the root path mentioned above. public void setResMappingObj(java.util.Map value) |
setHeader |
Set HTTP header information in the form of key value (For example, key=“ContentType” Value=“Application/JSON”) public void setHeader(java.util.Map value) |
addHeader |
Adding key value if header exists or will create header and add public void addHeader(java.lang.String entry, java.lang.String value) |
setBody |
Set http body information as a Map. Here the map would contain three keys bodyFormat, bodyFormData and jsonBody. The bodyFormat value can be raw that means user has provided values as raw JSON string else user has provided value in the key value format that must be converted into JSON. public void setBody(java.util.Map value) |
setResponseCode |
Set the value of successful response code as list (200, 299, 201). This would be respected by the connector if any other response code would be consider as request failure. public void setResponseCode(java.util.List value) |
getAfterRule |
Fetch the name of after rule assigned to the particular operation like create, update user, account aggregation, and so on: public java.lang.String getAfterRule() |
getBeforeRule |
Fetch the name of before rule assigned to the particular operation like create, update user, account aggregation, and so on. public java.lang.String getBeforeRule() |
getParseRule |
public java.lang.String getParseRule() |
getContextUrl |
Fetch the contextUrl provided to the particular operation like create, update user, account aggregation, and so on public java.lang.String getContextUrl() |
getHttpMethodType |
Fetch the httpMethodType (get,put,post,delete and patch) provided to the particular operation like create, update user, account aggregation, and so on. public java.lang.String getHttpMethodType() |
getOperationType |
Fetch the operationType (Account Aggregation,Create Account,Group Aggregation etc) provided to the particular operation like Create, update user, account aggregation, and so on. public java.lang.String getOperationType() |
getRootPath |
Fetch the rootPath provided to the particular operation like Create, update user, account aggregation, and so on. public java.lang.String getRootPath() |
getFullUrl |
Fetch the fullUrl that is a combination of basicUrl + contextUrl for the particular operation like Create, update user, account aggregation, and so on. public java.lang.String getFullUrl() |
getBaseUrl |
Fetch the baseUrl which is common for all operation like Create, update user, account aggregation, and so on. public java.lang.String getBaseUrl() |
getSequenceNumberForEndpoint |
Fetch the sequenceNumber for the particular operation (Create, update user, account aggregation, etc) that decide the priority of execution for operation, if there are multiple endpoint of same operation like account aggregation. public int getSequenceNumberForEndpoint() |
getUniqueNameForEndPoint |
Fetch the uniqueName provided to the particular operation like Create, update user, account aggregation, and so on. public java.lang.String getUniqueNameForEndPoint() |
getResMappingObj |
Fetch the responseMapping map that will have key as schema attribute and value as JSON path in the JSON response for particular operation like Create, update user, account aggregation, and so on. public java.util.Map getResMappingObj() |
getHeader |
Fetch the Http header map that holds the header information for particular operation like Create, update user, account aggregation, and so on. public java.util.Map getHeader() |
getBody |
Fetch the body map that holds the body information with keys like bodyFormat, jsonBody and bodyFormData. The bodyFormat can have raw or formData value. bodyFormData will have value as map jsonBody will have value as string with whole JSON. public java.util.Map getBody() |
getResponseCode |
Fetch the success response code (list) value which will decide whether the operation was successful or not for particular operation like Create, update user, account aggregation, and so on. public java.util.List getResponseCode() |
getAttributes |
public sailpoint.object.Attributes getAttributes() |
getAttribute |
public java.lang.Object getAttribute(java.lang.String name) |
getBooleanAttributeValue |
public boolean getBooleanAttributeValue(java.lang.String name) |
getStringAttributeValue |
public java.lang.String getStringAttributeValue(java.lang.String name) |
setAttribute |
public void setAttribute(java.lang.String name, java.lang.Object value) |
getPaginationSteps |
Fetch the paging steps as a string which will decide how account/group paging will work. public java.lang.String getPaginationSteps() |
setPaginationSteps |
Set the paging steps as a string which will decide how account/group paging would work. public void setPaginationSteps(java.lang.String paginationSteps) |
toString |
public java.lang.String toString() Overrides: toString in class java.lang.Object |
getResponseBody |
Retrieve last executed Request's Response Body. public java.lang.String getResponseBody() |
setXpathNamespaces |
Sets XPath namespaces using the supplied Map object. public void setXpathNamespaces(Map<String, String> xpathNamespaces) |
getXpathNamespaces |
Retrieves XPath namespaces. public Map<String, String> getXpathNamespaces() |
getPagingInitialOffset() |
Retrieves the initial page offset. public int getPagingInitialOffset() |
setPagingInitialOffset() |
Sets the initial paging offset. public void setPagingInitialOffset(int pagingInitialOffset) |
getPagingSize() |
Retrieves the page limit. public int getPagingSize() |
setPagingSize |
Sets the page limit. public void setPagingSize(int pagingLimit) |
Can we totally stop the execution of the requestEndPoint if some condition passed in plan does not match a condition. PS. return null; does not work.
Hi Team,
I am getting below error while running the code in Web Service Before Operation Rule.
persistent hashmap cannot be cast to java.lang.string
Code:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import connector.common.JsonUtil;
import connector.common.Util;
import sailpoint.connector.webservices.EndPoint;
import sailpoint.connector.webservices.WebServicesClient;
import sailpoint.object.Application;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
Map body = requestEndPoint.getBody();
String jsonBody = (String) body.get("jsonBody");
//log.info("Rule - Modify Body: running");
Date date = new Date();
SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd");
String strDate = formater.format(date);
try
{
Map jsonMap = JsonUtil.toMap(jsonBody);
if (jsonMap != null)
{
// get the date from jsonbody and update it
Object date = jsonMap.get("date");
jsonMap.remove("date");
jsonMap.put("date", strDate);
// append the body back to source
String finalBody = JsonUtil.render(jsonMap);
body.put("jsonBody", finalBody);
requestEndPoint.setBody(body);
}
}
catch (Exception ex)
{
log.error("Rule - Modify Body: " + ex);
}
return requestEndPoint;
Please advice.
Thanks,
Sasitharan Duraisamy.
I encountered the "persistent hashmap cannot be cast to java.lang.string" issue myself. How are you attaching the before operation rule to your source? In the source configuration API, you should have a line "beforeRule": null, in the configuration for each endpoint. Since the documentation doesn't make it clear how to attach the rule, I had first tried:
"beforeRule": {
"name": "RuleName",
"type": "WebServiceBeforeOperationRule",
"id": "123456..."
}
I believe that's the hash map that IdN is trying to cast into a string, as this "beforeRule" is just a string.
Try setting it to:
"beforeRule": "RuleName",
Hopefully that helps. It made all the difference for me.
Hii @MattUribe
Thanks for the response. I made the changes as per your suggestion. The code got executed & test connection was success. But the jsonBody in the target application is not getting changed. Basically, I am trying to update (code shared above) the date in below JSON, whenever we are triggering the above WebServiceBeforeOperationRule via Test Connection or Account Aggregation.but that is not happening.
RAW JSON BODY :
{
"jobFileContent" : "LS0tLS0tLS0gRU5DUllQVEVEIERBVEEgLS0tLS0tLS0KQUVTL0NCQy9QS0NTN1BhZGRpbmcKYXAzQ05ZVUZ4TTg9CmxFSWhXYUlXVmtPTEphUGwrbUp0S3F1RVBGanNzeWFlUkxlWmxFcHQ1ZWc9CkdWSTl3ejNUNHFkbnRmTldzOVpXUDlzL2Z1OUxUbURWWVdNOG1aL2hjR3ZPa2ozeUh3SHZ6THErd3dJY2pZNW5JTkx1dEdqUmcyTlAKR1g5YVllZ2F5NW9jUE5nNkQzRlNiVWpZdFc2SWk0VTVsb0F3MEpFcUdySHlrdHRRNFRnMgotLS0tLS0tLSBFTkQgT0YgRklMRSAtLS0tLS0tLQ==",
"date" : "2022-01-19",
"manAkPnr" : "000250.WEB.WEB1",
"tenant" : "",
"outputFormat" : "XML"
}
Please advice.
Thanks,
Sasitharan Duraisamy.
Hi Team,
Can call two different api from WebServiceBeforeOperation Rule at same time.
For e.g. I have one api to create user and another to add Entitlement but i wanted to use both the api.
I wanted to create a user with default entitlement.
Please advice.
Thanks,
Satish
Hi Team,
We have a requirement, where we need to send the body as XML. I went through the article, but could not figure a way to send the request body as String or XML. Is it supported by IDN?
Thanks,
Samant Vishwakarma
Hi, this rule does not support printing provisioningPlan object in XML? This is because when I try using provisioningPlan.toXml(), I was not able to deploy the rule to tenant. However, https://developer.sailpoint.com/idn/docs/rules/java-docs clearly mentions the toXml() being available.