1
0
-1

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,

    CommentAdd your comment...

    2 answers

    1.  
      1
      0
      -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*")))
        CommentAdd your comment...
      1.  
        1
        0
        -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

        1. 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

        2. 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

        3. 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 NameServicenow Field typeJira Field NameJira 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

        4. 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

        5. 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

        6. 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



        7. 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

        8. 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"
          }



        CommentAdd your comment...