While comments are flying nicely between ServiceNow INCs and JIRA, the same can not be said of the comments from our RITMs. We have a custom field for our IT Work Notes, a Journal Entry field named u_journal_2. No matter what I try it seems to throw up an error of some kind, either a type mismatch (String instead of List) or, and currently, No such property: issue for class: Script355.
I have followed the guide on " How to Sync Comments in Jira Cloud", trying replacing the “replica.comments” to “replica.u_journal_2” but it either doesn’t work or there is an error.
I feel like I have tried everything but it might be that I am not understanding what it is trying to do properly. Any help would be much appreciated!
Sadly that didn’t seem to work for me. I left the Incoming Sync on Jira as is and added the new line into the Outgoing Sync on ServiceNow as you mentioned. The sync does stay active on both sides and doesn’t throw up an error but when I try to add a new comment into the u_journal_2 field, it doesn’t appear in the ticket on Jira. However, updates to the Summary happen without an issue.
I noticed you used “requestItem” before the field names on all of the variables. I have the others as “entity” but that seems to be working perfectly. I am assuming that wouldn’t be the issue?
Also, I was looking for this to happen from Jira to ServiceNow as well. I tried throwing some mud at the wall to see if it would stick with:
On the SNOW outgoing you are using:
replica.u_journal_2 = requestItem.u_journal_2
replica.comments = requestItem.comments
And that means that you are populating the standard comments object in exalate, and also a custom object called replica.u_journal_2, but if you look at the incoming on Jira, I do not think you are utilizing the u_journal_2 field at all (or am I missing something).
Ah yes! This must have been from a time I had to remove it as it was breaking the rest of the script and I didn’t notice I had not put it back in. This is what I have currently:
Outgoing Sync from SNow:
if (entity.tableName == "incident") {
replica.key = entity.key
replica.summary = "SN Incident - " + entity.short_description
replica.description = "*Caller Name:* " + entity.caller_id.display_value + "\n*SN Priority:* " + entity.priorityValue.name + "\n\n-------------------------- [update below line]\n" + entity.description
replica.attachments = entity.attachments
replica.comments = entity.comments
replica.state = entity.state
replica.priority = entity.priorityValue
//if(!(entity.assigned_to instanceof String)){
//replica.assigned_to = entity.assigned_to.display_value
//}
}
// If the synced ticket is an Request, send the following fields with updated Short Description
if (entity.tableName == "sc_req_item") {
replica.key = entity.key
replica.summary = "SN Request (" + entity.cat_item.display_value + ") - " + entity.short_description
replica.description = "*Requested For:* " + entity.requested_for.name + "\r\r*For more information on this ticket please see:*\r \r[https://hestest.service-now.com/now/nav/ui/classic/params/target/sc_req_item.do%3Fsys_id%3D" + entity.sys_id + "|https://hestest.service-now.com/now/nav/ui/classic/params/target/sc_req_item.do%3Fsys_id%3D" + entity.sys_id + "|smart-link]"
replica.attachments = entity.attachments
replica.customFields.u_journal_2 = entity.customFields.u_journal_2
Incoming Sync from JIRA:
if (firstSync) {
issue.projectKey = "SNOW"
// Set the same issue type as the source issue. If not found, set a default.
issue.typeName = nodeHelper.getIssueType(replica.type?.name, issue.projectKey)?.name ?: "ServiceNow"
// The Description sync lives in "firstSync" as, if it is a RITM, this will be the only time it syncs
issue.description = replica.description
}
issue.summary = replica.summary
issue.comments = commentHelper.mergeComments(issue, replica)
issue.attachments = attachmentHelper.mergeAttachments(issue, replica)
// Append content from 'u_journal_2' to the comments
if (replica.customFields?.u_journal_2) {
issue.comments += "\n" + replica.customFields.u_journal_2
}
// If the synced ticket comes from an Incident
if (!issue.summary.startsWith("SN Request")) {
issue.description = replica.description
// Unless ServiceNow ticket has been closed, leave State alone. If it is, then close JIRA ticket
if (replica.state == "Resolved" || replica.state == "Closed" || replica.state == "Canceled") {
def statusMap = [
"Resolved" : "Done",
"Closed" : "Done",
"Canceled" : "Done",
]
def remoteStatusName = replica.state
issue.setStatus(statusMap[remoteStatusName] ?: "In Progress")
}
// Updates Priority from ServiceNow ticket
def priorityMapping = [
// remote side priority <-> local side priority
"1 - Critical" : "Highest",
"2 - High" : "High",
"3 - Moderate" : "Medium",
"4 - Low" : "Low"
]
def priorityName = priorityMapping[replica.priority?.name] ?: "Low" // set default priority in case the proper urgency could not be found
issue.priority = nodeHelper.getPriority(priorityName)
// If ticket is a Request Item
} else {
// Unless ServiceNow ticket has been closed, leave State alone. If it is, then close JIRA ticket
if (replica.state == "Closed Complete" || replica.state == "Closed Incomplete") {
def statusMap = [
"Closed Complete" : "Done",
"Closed Incomplete" : "Done",
]
def remoteStatusName = replica.state
issue.setStatus(statusMap[remoteStatusName] ?: "In Progress")
issue.summary = replica.summary
}
}
Currently this solution does sync/stay active but doesn’t put the information into the JIRA ticket. Also, the other way around (JIRA to ServiceNow) is probably more important. I can give the script for that too if/when needed.
I would like to see the payload (Remote Replica) as you see it on the Jira side please to ensure that the contents of the journal custom field are actually coming over.
If they are, I think the following line issue.comments += "\n" + replica.customFields.u_journal_2
would need to change to something like this: issue.comments = commentHelper.addComment(replica.customFields.u_journal_2, false, issue.comments)
Interesting, so there is no u_journal_2 field. Is it populated in the RITM?
Also, I would change the following in SNOW outgoing: replica.customFields.u_journal_2 = entity.customFields.u_journal_2
to replica.u_journal_2 = entity.u_journal_2
Ok, that’s looking a lot more healthy now I have changed that line:
{
"version": {
"major": 1,
"minor": 14,
"patch": 0
},
"hubIssue": {
"u_journal_2": "01/05/2025 11:13 - Iain Dewar (IT Work Notes)\nOne more time!\n\n01/05/2025 11:07 - Iain Dewar (IT Work Notes)\nLets go with some more work notes!\n\n16/04/2025 10:01 - Iain Dewar (IT Work Notes)\nWork notes?\n\n",
"voters": [],
"fixVersions": [],
"internalMap": {
"u_journal_2": "01/05/2025 11:13 - Iain Dewar (IT Work Notes)\nOne more time!\n\n01/05/2025 11:07 - Iain Dewar (IT Work Notes)\nLets go with some more work notes!\n\n16/04/2025 10:01 - Iain Dewar (IT Work Notes)\nWork notes?\n\n"
},
"labels": [],
"customKeys": {},
"entityProperties": {},
"components": [],
"attachments": [],
"customFields": {},
"eventTriggerContext": {},
"description": "*Requested For:* null\r\r*For more information on this ticket please see:*\r \r[https://hestest.service-now.com/now/nav/ui/classic/params/target/sc_req_item.do%3Fsys_id%3Df766e0bcfb58621090abf92abeefdc4a|https://hestest.service-now.com/now/nav/ui/classic/params/target/sc_req_item.do%3Fsys_id%3Df766e0bcfb58621090abf92abeefdc4a|smart-link]",
"watchers": [],
"key": "RITM0064072",
"summary": "SN Request (WeTransfer Access) - Access to PIC Trinity House Hi-Res Pictures 3",
"comments": [],
"workLogs": [],
"affectedVersions": []
},
"issueUrl": "https://hestest.service-now.com//nav_to.do?uri=sc_req_item.do?sys_id=f766e0bcfb58621090abf92abeefdc4a"
}
I did also change the line you mentioned (using commentHelper) but while the information is going over, it doesn’t seem to be appearing in the Comment box.
…and that has started putting the comments into the ticket. It’s ALL the comments but it’s a start. Guess I just need to put them all into an array and just show the first comment.
Now that you have changed the replica structure on source side, you will need to do the same on destination i.e. change issue.comments = commentHelper.addComment(replica.customFields.u_journal_2, false, issue.comments)
to issue.comments = commentHelper.addComment(replica.u_journal_2, false, issue.comments)
p.s.: I see you were faster than me! Yes, that should be the issue indeed
What I meant was that each time it sent all previous IT Work Notes along with the new one
But yeah, looking at the information it is sending, I should be able to isolate the most recent comment and just post that (the last IT work note ends in \n\n even when you add new lines to the Work Note where it looks like this \r\n\r\n). I should be able to figure this out now when it comes to moving the IT Work Notes from ServiceNow to Jira.
Now we need to go the other way which seems to be more tricky. I have put the following information for this.
Outgoing Sync from JIRA: (It looks like this as it wasn’t telling us who was making the comments when it got it ServiceNow. This works perfectly in INCs)
This I would need to set up and test to provide an accurate answer, but here are a couple of observations:
The manipulation you are doing in Outgoing Sync from JIRA, I would do this in the Incoming in SNOW. You have the author info available as part of the comment object received in SNOW, so this would be easier done there I think – but minor detail, not important.
About the journal field, I would try: entity.u_journal_2 = "A test string" – does this work?
If it works, then entity.u_journal_2 = replica.comments,last().body
and see how it goes.
That worked out great and now the comments from one side are now appearing in the other.
Sadly, we have gone from one extreme to the other however. Instead of never appearing, the last comment is now being added every time there is any update to the JIRA ticket even if there is no new comment.
Weirdly I have had a lot of luck with this if statement when the connection is to an Incident ticket:
if (replica.addedComments == null || replica.addedComments.isEmpty())
However, when I try to use this with a record on the Request Item table, it doesn’t work. There is no difference to the Outgoing Sync from JIRA so I don’t know why there would be a difference when it comes to the Incoming sync. I have tried using: