Can multiple payloads be sent to Webservices Target System from ISC in one call?

Hello People,
Need your advice
Trying to sync data with 4 different payloads into a Webservice app from ISC

4 different https operation

When sync is run with individual operation it’s successful but when combined , it throws me an error


["Exception occurred while performing \u0027Modify\u0027 operation on identity \u0027291529536652808\u0027:  Error: {\n  \"status\" : 400,\n  \"message\" : \"ContactPaths can only contain a maximum of 3 e-mail addresses.\"\n}"]

Could anyone help me how can I achieve successful sync using these 4 operation with different payloads.

Thank you

Hi Rita,

Can you share a view of what your update account API calls look like for each operation so we can understand better what your calls are doing?

Thanks,
Margo

Hello @margocbain
Sure,
All four API calls are same only Body is different.

if $email and $phone fields is empty in webservice app, the sync process should add the respective the values.
However, if values already exist, the process should not perform any addition

Add email and phone

[
  {
    "op": "add",
    "path": "/paths/-",
    "value": {
      "pathId": 123456,
      "value": "$plan.Email$"
    }
  }
]


[
  {
    "op": "add",
    "path": "/paths/-",
    "value": {
      "pathId": 78901,
      "countryCode": "US",
      "value": "$plan.phone$"
    }
  }
]

if updated values for $email or $phone are received from HR, the existing values should be modified by sync in the webservice.

Modify email and phone

[
  {
    "op": "replace",
    "path": "/paths/pathId:123456/value",
    "value": "$plan.Email$"
  }
]



[
  {
    "op": "replace",
    "path": "/paths/pathId:78901/value",
    "value": "$plan.phone$"
  }
]

Thank you

Hi Rita,

I’d recommend changing all of these to ‘replace’. By using the ‘add’ op, it will append the values, which explains why you’re getting the error for having more than 3 emails in the account.

Thanks,
Margo

But there will be time when a value needs to be added to $email and $phone

Hi Rita,

You can write a before operation rule. Where you could check if the email/phone already exists on the account.

if it exists then you can craft the body of “replace” operation.
If it does not exists already then you can craft the body of the “add” operation

Hope this can help but, Please letme know if you find some other solution for the problem :slight_smile:

Hello @neeraj99
I came up with this

import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;

String operationToRun = null;

if (provisioningPlan != null) {
for (AccountRequest accReq : provisioningPlan.getAccountRequests()) { // listing account request
for (AttributeRequest attrReq : accReq.getAttributeRequests()) {// 
String attrName = attrReq.getName();
String newValue = (String) attrReq.getValue();
String existingValue = accReq.getNativeIdentityAttributes() != null ?
(String) accReq.getNativeIdentityAttributes().get(attrName) : null;

  if ("Email".equals(attrName)) {
    if (existingValue == null || existingValue.trim().isEmpty()) {
      operationToRun = "Add Email";
    } else if (!existingValue.equals(newValue)) {
      operationToRun = "Modify Email";
    }
  } else if ("phone".equals(attrName)) {
    if (existingValue == null || existingValue.trim().isEmpty()) {
      operationToRun = "Add Phone";
    } else if (!existingValue.equals(newValue)) {
      operationToRun = "Modify Phone";
    }
  }
}
}
}

return operationToRun;

I have a question you are returning operationToRun,
Just a problem when you are writing this in before operation rule how are you capturing this?

I have created 4 different http operation so thought of writing a rule will select operation.

I am open to any suggestion here

I was just wandering how would you explicitly select 1 update operation out of 4.

BeforeOperation rule runs for a specific operation, which means you cannot change the operation from the rule.

What you need to do is create one Modify Account operation and inside the BeforeOperation rule, change the body based on the attribute found in the Provision Plan

@iamology

What you saying is I don’t need 4 different operation set up in ISC. i just need one and modify the body. How will i send the payload to the targeted system?

You don’t need to add anything to the body in the UI. Instead update the body in the BeforeOperation rule like below

JSONArray intendedBody = new JSONArray(javaList);
Map jsonBody = new HashMap();
jsonBody.put("jsonBody", intendedBody.toString());
requestEndPoint.setBody(jsonBody);

javaList above needs to be created by applying your login on contents of Provisioning Plan

Add single update operation and then use before operation rule to call all required api’s in single code.

1 Like

Hello,
@neeraj99 @iamology @iamology

Thanks for your suggestions! I’ve used them to develop a BeforeOperation rule and would be grateful for any feedback you can provide.


import java.util.*;
import connector.common.JsonUtil;
import sailpoint.object.ProvisioningPlan;
import sailpoint.object.ProvisioningPlan.AccountRequest;
import sailpoint.object.ProvisioningPlan.AttributeRequest;
import sailpoint.connector.webservices.Endpoint;

// Get request endpoint
Endpoint requestEndPoint = (Endpoint) args.get("requestEndPoint");

// Extract attribute values from provisioning plan
ProvisioningPlan plan = (ProvisioningPlan) args.get("provisioningPlan");
String email = null;
String phone = null;

if (plan != null && plan.getAccountRequests() != null) {
    for (AccountRequest acctReq : plan.getAccountRequests()) {
        if ("Source ABC".equalsIgnoreCase(acctReq.getApplicationName())) {
            for (AttributeRequest attrReq : acctReq.getAttributeRequests()) {
                if ("secondaryEmail".equals(attrReq.getName())) {
                    email = (String) attrReq.getValue();
                }
                if ("phoneCallCell1".equals(attrReq.getName())) {
                    phone = (String) attrReq.getValue();
                }
            }
        }
    }
}


// Get existing attributes from Source ABC
Map<String, Object> existingAttributes = (Map<String, Object>) args.getOrDefault("existingAttributes", new HashMap<>());

String existingEmail = (String) existingAttributes.get("secondaryEmail");
String existingPhone = (String) existingAttributes.get("phoneCallCell1");


// Build dynamic payload
List<Map<String, Object>> payloadList = new ArrayList<>();

// Email logic
if (email != null) {
    Map<String, Object> emailPayload = new HashMap<>();
    if (existingEmail == null || "".equals(existingEmail)) {
        emailPayload.put("op", "add");
        emailPayload.put("path", "/paths/-");

        Map<String, Object> valueMap = new HashMap<>();
        valueMap.put("pathId", 240001148045317L); 
        valueMap.put("value", email);

        emailPayload.put("value", valueMap);
        
    } else if (!existingEmail.equals(email)) {
        emailPayload.put("op", "replace");
        emailPayload.put("path", "/paths/pathId:240001148045317/value");
        emailPayload.put("value", email);

        
    }
    if (!emailPayload.isEmpty()) {
        payloadList.add(emailPayload);
    }
}

// Phone logic
if (phone != null) {
    Map<String, Object> phonePayload = new HashMap<>();
    if (existingPhone == null || "".equals(existingPhone)) {
        phonePayload.put("op", "add");
        phonePayload.put("path", "/paths/-");

        Map<String, Object> valueMap = new HashMap<>();
        valueMap.put("pathId", 240001148045319L); 
        valueMap.put("value", phone);
        valueMap.put("countryCode", "US"); 

        phonePayload.put("value", valueMap);
        
    } else if (!existingPhone.equals(phone)) {
        phonePayload.put("op", "replace");
        phonePayload.put("path", "/paths/pathId:240001148045319/value");
        phonePayload.put("value", phone);

        
    }
    if (!phonePayload.isEmpty()) {
        payloadList.add(phonePayload);
    }
}

// Inject payload
if (!payloadList.isEmpty()) {
    String finalPayload = JsonUtil.render(payloadList);
    requestEndPoint.setPayload(finalPayload);
    
} else {
    
}

return requestEndPoint;


Thank you

Hi @j1241
This looks good to me on high level. Give it a shot and see if syntax & Logic is working as expected & if not you can just drop the error here someone would pick it up.

2 Likes

Could you suggest me a better way of handlining this saas rule validator errors.

Line 23 - [LintBSHMethodInvocation(92)]  Could not retrieve definition for variable name 'args'
    23: Endpoint requestEndPoint = ( Endpoint ) args .getOrDefault ( "requestEndPoint" , new Endpoint ( ) )

 Line 27 - [LintBSHMethodInvocation(92)]  Could not retrieve definition for variable name 'args'
    27: ProvisioningPlan plan = ( ProvisioningPlan ) args .get ( "provisioningPlan" )

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.