2 answers
- 10-1
This works
ServiceNow - Outgoing sync
replica.u_risk_type = entity.u_risk_type
ServiceNow - Incoming sync
entity.u_risk_type = replica.u_risk_type?.value?.collect{"${it.value}"}.join(",")
Jira - Outgoing sync
replica.u_risk_type = issue.customFields."Risk Type"
Jira - Incoming sync
issue.customFields."Risk Type"?.value = nodeHelper.getOptions(issue, "Risk Type", Arrays.asList(replica.u_risk_type?.split("\\s*,\\s*")))
Add your comment... - 10-1
Hi there,
For example, if you have a multiselect(multiple choices) Custom Field in Jira side, and a "Risk Type" multi select choices in ServiceNow. You can try doing the following to make it bidirectional:
Jira to ServiceNow
Outgoing Jira:
replica.customFields."Risk Type" = issue.customFields."Risk Type"
Incoming SNOW:
if(entity.tableName == "incident") { entity.u_risk_type = replica.customFields."Risk Type"?.value?.collect { opt -> opt?.value } ?: nodeHelper.getOptions(issue,"Risk Type",replica.customFields."Risk Type"?.value?.collect {it -> it?.value}) }
ServiceNow to Jira
Outgoing SNOW:
if(entity.tableName == "incident") { replica."Risk Type" = entity.u_risk_type }
Incoming Jira:
issue.customFields."Risk Type"?.value = replica."Risk Type".collect { opt -> opt?.value } ?: nodeHelper.getOptions(issue,"Risk Type",replica."Risk Type"?.collect {it -> it?.value})
This worked for me. At the moment, we will work to add this to our documentation to make it a bit clear for everybody.
Kind regards,
Ariel
- Enrique Cadalso
Hello,
I was asking for "multi-select list in both sides". The provided example is for "multiselect(single choice) Custom Field in Jira side".
I don't think it will work like that.
Thanks,
Enrique
- Ariel Aguilar
Hi Enrique,
As you may know, both instances may have many and vary options. If the example is not working for this case, could you add the required name fields as shown on your instances. In this way, we won't duplicate our efforts.
Thanks,
Ariel
- Enrique Cadalso
Hi Ariel,
Here you have the details.
In Servicenow there is a field type Multiple choice - multi selection that accept multiple values.
In Jira there is a field type Select List (multiple choices) that accept multiple values.
Both fields contain the same options so mapping is not required.
I need to know what is the syntax for the assignment in all sides.
Servicenow Field Name Servicenow Field type Jira Field Name Jira Field type Risk Type (u_risk_type) Multiple choice - multi selection
Options
- Option1
- Option2
- Option2
Risk Type (customfield_21703) Select List (multiple choices)
Options
- Option1
- Option2
- Option2
Regards,
Enrique
- Enrique Cadalso
Using the provided code the error happens in Jira side. This is the error (anonymized )
Impact: ISSUE Local entity: ETP-27 Remote entity: PRB0038185 Connection: Jira_to_ServiceNow Error type: Sync rules result validation error. Error Creation Time: 2021-07-26 10:44:41.742 Error Detail Message: Unexpected error occurred. The customfield `u_risk_type` was assigned to `value=[] class=java.util.ArrayList`, but it should have been set to a custom field object Generate an exalate support.zip file and contact support. Error Stack Trace: com.exalate.api.exception.bug.hubobjects.UnsupportedHubObjectsVersionBugException: Unexpected error occurred. The customfield `u_risk_type` was assigned to `value=[] class=java.util.ArrayList`, but it should have been set to a custom field object Generate an exalate support.zip file and contact support. at com.exalate.error.services.BugExceptionCategoryService.generateUnsupportedHubObjectsVersionBugException(BugExceptionCategoryService.scala:32) at com.exalate.hubobject.HubObjectValidator.checkCustomFieldConsistency(HubObjectValidator.java:96) at com.exalate.hubobject.HubObjectValidator.checkDataStructuresConsistency(HubObjectValidator.java:69) at com.exalate.hubobject.HubObjectValidator.validateIssueReplica(HubObjectValidator.java:54) at com.exalate.hubobject.v1_2.HubObjectHelper.validateReplica(HubObjectHelper.java:442) at com.exalate.processor.jira.JiraCreateReplicaProcessor.createHubReplica(JiraCreateReplicaProcessor.java:199) at com.exalate.processor.jira.JiraCreateReplicaProcessor.createHubReplica(JiraCreateReplicaProcessor.java:130) at com.exalate.replication.request.CreateReplicaSyncRequestState.transition(CreateReplicaSyncRequestState.java:139) at com.exalate.replication.request.CreateReplicaSyncRequestState.transition(CreateReplicaSyncRequestState.java:48) at com.exalate.replication.in.RequestProcessorService.processSyncRequest(RequestProcessorService.java:319) at com.exalate.replication.in.RequestProcessorService.processSyncRequestsForIssue(RequestProcessorService.java:189) at com.exalate.replication.in.RequestProcessorService.processSyncRequests(RequestProcessorService.java:126) at com.exalate.replication.in.RequestWorker$1.run(RequestWorker.java:91) at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.lambda$executeHandlingLocks$13(ClusteredSensitiveExecutorService.java:31) at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.executeHandlingLocks(ClusteredSensitiveExecutorService.java:46) at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.executeHandlingLocks(ClusteredSensitiveExecutorService.java:29) at com.exalate.replication.in.RequestWorker.run(RequestWorker.java:81) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Incoming sync data: Summary: Test snow ticket 01 Entity Key: PRB0038185(id: undefined) Encoded payload: { "version": { "major": 1, "minor": 15, "patch": 0 }, "hubIssue": { ... "u_risk_type": "Option1, Option2", ... "internalMap": { ... "u_risk_type": "Option1, Option2", ... }, ... }, "issueUrl": "**********************" }
Regards,
Enrique
- Ariel Aguilar
Hi Enrique,
I did some changes on the code I sent before, please take a look to update. Please be aware, I am not sure what "Multiple choice - multi selection" could be for ServiceNow. I have looked on their docs: https://docs.servicenow.com/bundle/quebec-platform-administration/page/administer/reference-pages/reference/r_FieldTypes.html
Either way, this might work for you. Just let me know.Kind regards,
Ariel
- Enrique Cadalso
I get the same error.
When assigning values in Jira to a multi select field we are supposed to pass a collection of Option IDs. I was hoping Exalate would do the heavy lifting for me and I don't have to iterate the values in "u_risk_type": "Option1, Option2", get the IDs and use some Jira Java API function to assign the values. In this case "Option1, Option2" are just strings. I don't' see square brackets so I wonder if they are interpreted as an array.
I am attaching in the screenshot how the field looks in the Servicenow UI, in case it helps. However, knowing what is received in the replica (included in the error) should be enough to know how to assign it to the Jira field.
Thanks,
Enrique
- Ariel Aguilar
Hi Enrique,
I have modified both Jira and ServiceNow incoming sides one more time, let me know if that works for you.
Kind regards,
Ariel
- Enrique Cadalso
Using last version of the code error in Jira is:
Impact: RELATIONLocal entity: ETP-27Remote entity: PRB0038185Connection: JiraCloud_to_ServiceNowError type: Sync rules errorError Creation Time: 2021-07-27 12:51:55.113Error Detail Message: Wrong value type provided for custom field Risk Type(customfield_21703) Error Stack Trace: com.exalate.api.exception.script.ScriptException: Wrong value type provided for custom field Risk Type(customfield_21703) at com.exalate.error.services.ScriptExceptionCategoryService.categorizeProcessorAndIssueTrackerExceptionsIntoScriptExceptions(ScriptExceptionCategoryService.scala:34) at com.exalate.processor.jira.JiraChangeIssueProcessor.applyProcessorResult(JiraChangeIssueProcessor.java:314) at com.exalate.processor.jira.JiraChangeIssueProcessor.changeIssue(JiraChangeIssueProcessor.java:201) at com.exalate.replication.request.UpdateIssueSyncRequestState.transition(UpdateIssueSyncRequestState.java:118) at com.exalate.replication.request.UpdateIssueSyncRequestState.transition(UpdateIssueSyncRequestState.java:36) at com.exalate.replication.in.RequestProcessorService.processSyncRequest(RequestProcessorService.java:319) at com.exalate.replication.in.RequestProcessorService.processSyncRequestsForIssue(RequestProcessorService.java:189) at com.exalate.replication.in.RequestProcessorService.processSyncRequests(RequestProcessorService.java:126) at com.exalate.replication.in.RequestWorker$1.run(RequestWorker.java:91) at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.lambda$executeHandlingLocks$13(ClusteredSensitiveExecutorService.java:31) at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.executeHandlingLocks(ClusteredSensitiveExecutorService.java:46) at com.exalate.node.util.concurrent.ClusteredSensitiveExecutorService.executeHandlingLocks(ClusteredSensitiveExecutorService.java:29) at com.exalate.replication.in.RequestWorker.run(RequestWorker.java:81) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748) Caused by: java.lang.IllegalStateException: Wrong value type provided for custom field Risk Type(customfield_21703) at com.exalate.node.hubobject.v1_3.NodeHubObjectConversionService.getNodeOptions(NodeHubObjectConversionService.java:1659) at com.exalate.node.hubobject.v1_3.NodeHubObjectConversionService.getNodeCustomFieldValue(NodeHubObjectConversionService.java:1424) at com.exalate.node.hubobject.v1_4.NodeHubIssueHelper.updateCustomFieldWith(NodeHubIssueHelper.java:1378) at com.exalate.node.hubobject.v1_4.NodeHubIssueHelper.updateCustomFieldsWith(NodeHubIssueHelper.java:1357) at com.exalate.node.hubobject.v1_4.NodeHubIssueHelper.applyFields(NodeHubIssueHelper.java:1211) at com.exalate.node.hubobject.v1_4.NodeHubIssueHelper.updateIssueWith(NodeHubIssueHelper.java:854) at com.exalate.node.hubobject.v1_4.NodeHubIssueHelper.updateIssueWith(NodeHubIssueHelper.java:751) at com.exalate.compatibility.HubObjectHelperAdapter.updateNodeIssueWith(HubObjectHelperAdapter.java:61) at com.exalate.hubobject.v1_2.HubObjectHelper.updateNodeIssueWith(HubObjectHelper.java:352) at com.exalate.processor.jira.JiraChangeIssueProcessor.applyProcessorResult(JiraChangeIssueProcessor.java:311) ... 18 more Incoming sync data: Summary: Test snow ticket 01Entity Key: PRB0038185(id: undefined)Encoded payload: { "version": { "major": 1, "minor": 15, "patch": 0 }, "hubIssue": { ... "Risk Type": "Option1, Option2", ... "summary": "Test snow ticket 01", "comments": [], "internalMap": { ... "Risk Type": "Option1, Option2", ... }, ... }, "issueUrl": "************" }
No errors on Servicenow but field is silently not populated:
The remote replica in Service now (data coming from Jira) is as follows
{ "version": { "major": 1, "minor": 14, "patch": 0 }, "hubIssue": { ... "customFields": { "Risk Type": { "id": 21703, "name": "Risk Type", "uid": "21703", "type": "OPTIONS", "value": [ { "id": "21909", "sequence": 1, "value": "Option1", "disabled": false, "childOptions": [] }, { "id": "21911", "sequence": 3, "value": "Option3", "disabled": false, "childOptions": [] } ] } }, "description": "Test snow ticket 01 description\r\nTest snow ticket 01 description2", ... "summary": "Test snow ticket 01", "comments": [], "internalMap": { ... }, ... }, "issueUrl": "https://jira*******/browse/ETP-27" }
Add your comment...
Question raised by Enrique:
We have a multi-select list in both sides (Jira and SNOW), same options. We need bidirectional synchronization.
I found how to do it Jira to Jira, but I didn’t found what replica.customFields.“MyField” = entity.multi_select_custom_field would send.
From other documentations it seems entity.multi_select_custom_field will send the value, not a custom field object.
Is there an example code in the documentation how to synchronize them?
Thanks,