Unable to Synchronize Assets Field Values Between projects in JSM Cloud

Topic created on behalf of Yogesh Kumar

We are syncing issues between two projects on the same Jira Cloud instance. While most fields (standard and custom) are syncing as expected, we are encountering issues with syncing Assets (Insight) custom field values. These fields are populated on the source issue but are either not being transferred or appear as empty/null on the destination issue.

Since Exalate does not directly support the sync of Asset Fields directly, we will leverage the Groovy scripting interface offered by Exalate and use HttpClient to make an API call to the Asset Endpoint provided by Atlassian to get the value of the Asset field based on the custom field id that we provide.

Here’s the solution.

  • Include the GroovyHttpClient class into the outgoing script on the sending side where the Assets field is being exported from: GroovyHttpClient.groovy

  • Now in your outgoing script, please include the following API call:

    //getting the workspaceid and objectid from Jira Issue API
    String key = issue.key
    def result = httpClient.get(“/rest/api/latest/issue/”+“$key”)
    def workspaceId = (“${result.fields.“customfield_10062”.workspaceId}”.replace(“[”,“”).replace(“]”,“”))
    def objectId = (“${result.fields.“customfield_10062”.objectId}”.replace(“[”,“”).replace(“]”,“”))
    def USER = “<<jira_username>>”
    def token = “<<jira_token>>”

    //def token = System.getenv(“token”)

    //getting the Asset field details using the above fetched workspace and objectid using groovy http client
    def res = new GroovyHttpClient(nodeHelper)
    .http(
    “GET”,
    “https://api.atlassian.com/jsm/assets/workspace/${workspaceId}/v1/object/${objectId}”,
    null,
    [
    “Content-type” : [“application/json”],
    “Authorization” : [“Basic ${(USER+”:“+token).bytes.encodeBase64().toString()}”.toString()]
    ]
    )

    def js = new groovy.json.JsonSlurper()
    def jsonRes = js.parseText(res)
    replica.“Asset information” = jsonRes.label

  • The only changes required will be on
    lines 4 and 5: use the correct custom field ID
    lines 6 and 7: enter your username and API key (we can hide the key away from the scripts later)

Once we send this information to the other side, we can use a similar logic to find the id of the object and set this via REST API.

Here’s a doc that can help : Assets REST API guide

Thanks, Dhiren

GroovyHttpClient.groovy

1 Like

Hi Dhiren,

I am trying to sync the asset fields between two JSM cloud sites, I have followed the steps shared by you, I am not getting any errors but the field value in destination site is not getting updated., could you please guide us in this.

Hi @Janaki

Could you please share the outgoing and incoming scripts that you are currently using?

So we can check if there something that is missing. Also I would recommend to check the Replica of one of this issues, to see if the values from this insight fields its there, this will help us to identify if the issue is on the incoming script or if the data is missing from the outgoing.

Best,
Kevin

Hi Kevin,

This is my outgoing script String key = issue.key

def result = httpClient.get(“/rest/api/latest/issue/”+“$key”)

def workspaceId = (“${result.fields.“customfield_11034”.workspaceId}”).replace(“[”, “”).replace(“]”, “”)

def objectId = (“${result.fields.“customfield_11034”.objectId}”).replace(“[”, “”).replace(“]”, “”)

def USER = “my email id”
def TOKEN = “Api token”

//getting the Asset field details using the above fetched workspace and objectid using groovy http client
def res = new GroovyHttpClient(nodeHelper)
.http(
“GET”,

"https://api.atlassian.com/jsm/assets/workspace/${workspaceId}/v1/object/${objectId}",
null,
[
    "Content-type" : ["application/json"], 
    "Authorization" : ["Basic ${(USER + ":" + TOKEN).bytes.encodeBase64().toString()}".toString()]
]

)

def js = new groovy.json.JsonSlurper()

def jsonRes = js.parseText(res)
replica.“Asset information” = jsonRes.label

and in incoming script we are using this

import groovy.json.JsonSlurper
import groovy.json.JsonOutput

final String DESTINATION_ASSET_FIELD_ID = “customfield_14301”

def USER = “email id”
def TOKEN = “API token”

def DESTINATION_WORKSPACE_ID = “destination workspace id”
def OBJECT_TYPE_ID = “destination onject type id”

// The label synced from the source issue
def assetLabel = replica.“Asset information”

if (assetLabel) {

def aqlQuery = "objectType = ${OBJECT_TYPE_ID} AND Label = \"${assetLabel}\""


def searchUrl = "https://api.atlassian.com/jsm/assets/workspace/${DESTINATION_WORKSPACE_ID}/v1/object/search"


def authHeader = "Basic ${(USER + ":" + TOKEN).bytes.encodeBase64().toString()}"

def requestBody = JsonOutput.toJson([aql: aqlQuery])


def res = new GroovyHttpClient(nodeHelper).http(
    "PUT",
    searchUrl,
    requestBody,
    [
        "Content-type": ["application/json"],
        "Authorization": [authHeader]
    ]
)


def js = new JsonSlurper()
def searchResult = js.parseText(res.body)

if (searchResult && searchResult.size() > 0) {
    // We found at least one matching object. Use the first one.
    def foundObjectId = searchResult[0].id

    // 4. Update the destination issue field (issue)
    
    def updateValue = [[
        "workspaceId": DESTINATION_WORKSPACE_ID,
        "objectId": foundObjectId
    ]]

    // Update the field on the destination issue
    issue.fields."${DESTINATION_ASSET_FIELD_ID}" = updateValue 
}
}


Just and FYI we are syncing between two instances where the object ids are different in both the instances, we have tried from postman, we are able to update the value if the object id is hardcoded {
  "fields": {
    "customfield_14301": [
      {
        "workspaceId": "workspace id",
        "id": "workspaceid:401982",
        "objectId": "401982"
      }
    ]
  }
}

Hi @Janaki

Could I please ask you to check if the replica.“Asset information” is being populated as expected?

You can check this by going to entity sync status on Exalate and search for an issue were the assets is being sync from the other side (sending side) and check the remote replica.

The remote replica will be a JSON, in there you can look for the Asset information field and should have something inside the field, if the field is empty then we need to verify the outgoing, if there is values in the field then we can pinpoint to incoming.

Looking forward to your update.

Best,
Kevin

Hi @Kevin

Thanks for the response, yes, I have checked that, and the remote replica JSON contains the value, please find the below JSON. {
“version”: {
“major”: 1,
“minor”: 14,
“patch”: 0
},
“hubIssue”: {
“Asset information”: “Card”,
“voters”: ,
“project”: {
“idStr”: “10353”,
“key”: “key”,
“name”: “project name”
}

@Kevin , can you please guide me here

Hi @Janaki

Can we have a screen-share session please ?

I am sending you my Calendly link by DM. Please use that link to schedule a 30 minutes call with me.

Thanks,

Sonal

Hi @Janaki

Happy New Year!

I wanted to follow up and check if you were able to schedule a call. It should be quick, and we can pick up right where we left off. Alternatively, if you’ve already resolved the issue, please let me know.

Looking forward to your update!

Thanks,

Sonal