Update Issue Listener: check if something changed

Olivier Billaud April 21, 2019

Hello all!

Sorry, this is the first time I try to create my own custom listener with Script Runner Listeners. And I don't know a lot of groovy, so I maybe tell some enormous mistakes...

My use case is:

When a ticket is updated, I want to check if a field A value was changed during this update, and maybe to edit this ticket 

The A field could be system field (description) or custom field, it depends.

 

I have many problems doing that:

1. The "IssueEvent" object doesn't have the Issue BEFORE the update and the Issue AFTER the update (but why... :( ), so I try to find what was changed during this update. But when i have a look on event.toString(), i just see that:

changelog=[GenericEntity:ChangeGroup][issue,17543][author,c_droobi][created,2019-04-21 18:24:28.473][id,80599],eventTypeId=2,sendMail=true,params={eventsource=action, baseurl=https://tst-jira.myjira.com},subtasksUpdated=true]

There is nothing!

I saw on different other topics solutions like this (for example in https://community.atlassian.com/t5/Marketplace-Apps-questions/Find-out-if-a-JIRA-update-event-changes-a-specific-issue-field/qaq-p/618091):

def change = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "SelectListA"}

but I can't find anything, my "change" variable is empty...

 

2. When i try to change the value of one of my fields, for example "description field", i see that the Issue object has no setter... I can see with the help of Google I should have a "mutable Issue" object, but I don't find how to transform my original Issue on mutable issue to work with...

 

Could you please help me to go further on this issue?

Thank you very much. Appreciate! :) 

2 answers

1 accepted

9 votes
Answer accepted
Peter-Dave Sheehan
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 22, 2019

It might help to break some of those long lines down and output some messages to the log.

For example, change:

def change = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "SelectListA"}

To

def changeLog = event?.changeLog //with groovy, all get methods can be accessed with this sort of shortcut)
def changeItems = changeLog.getRelated("ChildChangeItem")
def change changeItems?.find{ it.field == "SelectListA"}
if(!change){
//no changes found, let's try to see why not
if(!changeItems){
log.debug "There are no changes values in this event"
} else {
changeItems.each{
log.debug it
}
}
}

 This should show you the before and after of every change (if none are found that match SelectListA

 

For your second option, it's more than just getting a mutable issue. I think by default the issue associated with the event is mutable. I've never bothered to try to cast it to a specific type.

The following should just work:

event.issue.description = "my new description"

But that doesn't impact the db, it's just updating the object instance in memory. To complete the process and fully replicate the UI, you have to perform the following.

  1. call updateIssue() method from IssueManager to store the issue in the db
  2. call createChangeGroup() method from ChangeLogUtil to create the change history (optional)
  3. call reIndex(issue) method from IssueIndexingService to update the index and have the new values available for searching.

Something like this:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.index.IssueIndexingService
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.event.type.EventDispatchOption
import com.atlassian.jira.util.ImportUtils
import com.atlassian.jira.issue.history.ChangeLogUtils

def issueManager = ComponentAccessor.issueManager


event.issue.description = "my new description"

issueManager.updateIssue(event.user, event.issue, EventDispatchOption.DO_NOT_DISPATCH, false)

def wasIndexing = ImportUtils.isIndexIssues()
ImportUtils.setIndexIssues(true)
indexingService.reIndex(subTask)
ImportUtils.setIndexIssues(wasIndexing)

Olivier Billaud April 23, 2019

Wow, Peter-Dave, you're wonderful!

Thank you SO MUCH for helping me. That's perfect.

I succeeded to do what I wanted to do. I won't use your second part because I just wanted to change the Assignee so I used this method:

https://community.atlassian.com/t5/Jira-questions/Why-can-I-not-set-assignee-by-ID-Script-Runner/qaq-p/87404

(with ValidateAssign and Assign methods).

 

Just for some people who would see this topic, you have some little mistakes in your code:

childChangeItem => should have a cap ChildChangeItem

( it.field == "SelectListA"}

=>

{ it.field == "SelectListA"}
changeIteams

 =>

changeItems

 

Thank you again!! :) :)

Peter-Dave Sheehan
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
April 23, 2019

Thanks for catching my typos. I corrected them.

Glad I was able to help.

0 votes
sao bien August 6, 2019

Hi All, 

Have you any experiences in updating changes custom field when Indicator (TimeTOSLA field) changed?

I had below code to change value of custom field 2 when Indicator (TTS type) changed but it did work

Issue issue = event.getIssue()
def changeHolder = new DefaultIssueChangeHolder()

def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueService = ComponentAccessor.getIssueService()

def Indicator = "customfield_10815"

def change = event?.getChangeLog()?.getRelated("ChildChangeItem")?.find {it.field == "Indicator"}

def customField1 = customFieldManager.getCustomFieldObject("customfield_10815") ---Indicator field
def customField2 = customFieldManager.getCustomFieldObject("customfield_13007")
def customField1Value = customField1.getValue(event.issue).toString()
def customField2Value = customField2.getValue(event.issue).toString()

if (change) {
def issueInputParameters = issueService.newIssueInputParameters()
issueInputParameters.addCustomFieldValue(customField2.idAsLong, customField1Value)
def validationResult = issueService.validateUpdate(event.user, event.issue.id, issueInputParameters)
if (validationResult.isValid()) {
issueService.update(event.user, validationResult)
} else {
log.warn "Did not update issue: $validationResult.errorCollection.errors"
}
}

Br,

Sao

Suggest an answer

Log in or Sign up to answer