How to detect if a field value was changed

Guilherme Nogueira
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.
January 21, 2015

Hi guys,

I want to know how can I check if a field value was changed, i.e:

CustomField1 has value "21/01/2015" (DateField), and the user changed to "20/01/2015".

I want to execute a postfunction only if user change the field value, I'm using "Only if condition is true" and groovy.

I'm studying about  "transientVars" but no success yet.

The postfunction is: "Transition linked issues"

 

Thank you guys

4 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

4 votes
Answer accepted
JamieA
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.
January 21, 2015

For a post-function condition you want something like this:

import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.Issue


Issue issue = issue


def customFieldManager = ComponentAccessor.getCustomFieldManager()
def issueManager = ComponentAccessor.getIssueManager()
def customField = customFieldManager.getCustomFieldObjectByName("Some Date")
def originalIssue = issueManager.getIssueObject(issue.id)


return issue.getCustomFieldValue(customField) != originalIssue.getCustomFieldValue(customField)

This is only going to work if your post-function is first, or at least before the system post-functions that store the issue.

Sascha's answer is for listeners.

Guilherme Nogueira
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.
January 21, 2015

Hi Jamie, Thank you for your answer! I'm having this error: No signature of method: com.innovalog.jmwe.IssueProxy.getCustomFieldValue() is applicable for argument types: (com.atlassian.jira.issue.fields.CustomFieldImpl) values: [Approval Date] Using the same code as yours: import com.atlassian.jira.component.ComponentAccessor def customFieldManager = ComponentAccessor.getCustomFieldManager() def cf = customFieldManager.getCustomFieldObjectByName("Approval Date") issue.getCustomFieldValue(cf) != originalIssue.getCustomFieldValue(cf)

Guilherme Nogueira
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.
January 21, 2015

When I remove "issue.getCus...", i got this error: No such property: originalIssue for class: Script1

JamieA
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.
January 22, 2015

> The postfunction is: "Transition linked issues" Which one is that... can you attach a screenshot of the configuration?

Guilherme Nogueira
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.
January 22, 2015

I'm using this postfunction: https://innovalog.atlassian.net/wiki/display/JMWE/Post-functions "Transition linked issues" In this postfunction you inform which transaction (Closed, open etc) you want to execute and with witch link (bloks/relates to etc) and also has an option "Only if condition is true" in this field you insert your groovy code. Thank you Jamie.

Guilherme Nogueira
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.
January 22, 2015

Im using JIRA v6.3.12

JamieA
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.
January 22, 2015

I've updated my answer, which is for Script Runner plugin.

Guilherme Nogueira
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.
January 22, 2015

Thank you for your fast answer, I think it's close but still doesn't working: Error occurred while creating issue. This could be due to a plugin being incompatible with this version of JIRA. For more details please consult the logs, and see: http://confluence.atlassian.com/x/3McB Cannot cast object 'com.innovalog.jmwe.IssueProxy@4f935563' with class 'com.innovalog.jmwe.IssueProxy' to class 'com.atlassian.jira.issue.Issue' I'm sure my ad-on is updated and working properly. Im right now searching on google for any solution. Thank you again

JamieA
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.
January 22, 2015

I think the problem is you're not actually using Script Runner, you are using some other plugin. If you'd put the JMWE label on your question I wouldn't have bothered answering.

Guilherme Nogueira
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.
January 22, 2015

It works JAMIE !!! thank you :) I just made a few changes, I'm using this code: import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.Issue def customFieldManager = ComponentAccessor.getCustomFieldManager() def issueManager = ComponentAccessor.getIssueManager() def customField = customFieldManager.getCustomFieldObjectByName("SKU Approval") def originalIssue = issueManager.getIssueObject(issue.issueObject.key) return issue.get("customfield_11960") != originalIssue.getCustomFieldValue(customField) I'll accept your answer :)

3 votes
Sascha Becker January 21, 2015

First you create a Listener Class which in this case is listening to issue events. The class registers itself to the eventPublisher so it can listen to events. In the onIssueEvent() method you get all issue events. You can filter between updated, created etc. Once you you have an issue event you can extract the changelog which holds everything you need to determine which fields changed and handle it accordingly. I left some of my logic in so you can see how i did it.

 

public class IssueChangeListener implements InitializingBean, DisposableBean {
    private final EventPublisher eventPublisher;

    public IssueLinkSuspectChangeListener (EventPublisher eventPublisher) {
        this.eventPublisher = eventPublisher;
    }

    @Override
    public void destroy() throws Exception {
        eventPublisher.unregister(this);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        eventPublisher.register(this);
    }

   @EventListener
    public void onIssueEvent(IssueEvent issueEvent) {

        Long eventTypeId = issueEvent.getEventTypeId();
        Issue issue = issueEvent.getIssue();
        User user = issueEvent.getUser();
       
           List<GenericValue> changeItems = null;
            
           try {
                GenericValue changeLog = issueEvent.getChangeLog();

                HashMap<String, Object> fields = new HashMap<String,Object>();
              fields.put("group", changeLog.get("id"));
            
                changeItems = changeLog.internalDelegator.findByAnd("ChangeItem", fields);

                for(GenericValue changeVal : changeItems)
                {
                    String field = changeVal.getString("field");
                }
                
           } catch (Exception e) {
           }
    }
}

 

After creating your class you need to register it in your atlasssian-plugin.xml

<component key="issueChangeListener"         class="<your.path.to.the.listener.in.jira>.IssueChangeListener"/>
 
<component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher"/>

 

That should do the trick. If that helps you, please mark my answer as accepted.

Thanks

Guilherme Nogueira
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.
January 21, 2015

One question, how I explained before, I need to use that in a groovy validator... how can I connect they? Thanks :)

1 vote
Rusi Popov
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.
January 13, 2016

If you have a Listener created, then follow the idiom:

/**
 * Injected
 */
private final ChangeHistoryManager changeManager;
  
@EventListener
public void onIssueEvent(IssueEvent issueEvent) {
  ...
  eventTypeId = issueEvent.getEventTypeId();
  issue = issueEvent.getIssue();
  ...
  if ( EventType.ISSUE_UPDATED_ID.equals(eventTypeId) ) { // issue fields changed
    changeLog = issueEvent.getChangeLog();
    
    if ( changeLog != null ) { // a real change (not just a comment)
      customFieldsToReplicate = <retrieve the list of custom fields>
      
      if ( !customFieldsToReplicate.isEmpty() ) {
        changeId = changeLog.getLong( "id" );
        if ( changeId != null ) {
          change = changeManager.getChangeHistoryById( changeId );
          changedCustomFieldsToReplicate = new ArrayList<>();
          for (ChangeItemBean bean : change.getChangeItemBeans() ) {
            // find ALL fields with the change name and transfer its value among the
            for (CustomField field : customFieldsToReplicate) {
              if ( field.getName().equals( bean.getField() )
                   && ChangeItemBean.CUSTOM_FIELD.equals( bean.getFieldType() )) {
                   
                changedCustomFieldsToReplicate.add( field );
              }
            }
          } // changedCustomFieldsToReplicate holds only fields that have changed their value in the issue
        }        
      }
    }
    ...
  }
}

This approach:

  • identifies the history record for the ISSUE UPDATED event
  • inspects the listed changed fields (referred as beans)
  • identifies those custom fields that have changed and participate in a list of "interesting" fields - in my case for additional replication

Of course, you could by-pass the latter. Anyway, note that the standard "static" fields also can change and are listed among the changed "beans", but in this example ChangeItemBean.CUSTOM_FIELD.equals( bean.getFieldType() ) skips them

Piyush_Annadate August 2, 2018

I've a case here wherein I'm updating PRIORITY to value 4. Which works on create screen, but if I change that to other, behavior runs again and change it to value 4. How do I inject on the create screen, NOT TO RUN AFTER 1ST TIME?

1 vote
Sascha Becker January 21, 2015

Do you have the possibility to set up a listener class in the JIRA backend?

Guilherme Nogueira
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.
January 21, 2015

Yes, I have.

Sascha Becker January 21, 2015

Alright then. Check my new reply for a solution

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

TAGS
AUG Leaders

Atlassian Community Events