aroth
aroth

Reputation: 54836

Get previous issue status in event-handler (Jira 7.x)

I have a Jira plugin that needs to listen to IssueEvents and respond to various status transitions (as in "To Do -> In Progress", "In Progress -> Done", etc.). In most cases, doing this requires knowing both the current and the previous issue status. However there's no obvious API for getting the latter bit of information from the IssueEvent.

My setup is fairly simple:

@Named("myEventListener")
public class JiraChangeListener implements InitializingBean, DisposableBean {
    @ComponentImport
    private final EventPublisher eventPublisher;

    @ComponentImport
    private final CustomFieldManager fieldManager;

    @ComponentImport
    private final IssueManager issueManager;

    @Inject
    public JiraChangeListener(EventPublisher publisher, CustomFieldManager fieldManager, IssueManager issueManager) {
        this.eventPublisher = publisher;
        this.fieldManager = fieldManager;
        this.issueManager = issueManager;
    }

    @EventListener
    public void onIssueEvent(IssueEvent event) {
        Issue issue = event.getIssue();
        long eventType = event.getEventTypeId();
        String issueStatus = issue.getStatusId();  //the *current* issue status

        //[read various internal plugin settings]

        //now handle the event      
        if (eventType == EventType.ISSUE_CREATED_ID) {
            //triggered upon creation; we don't need the old status here
            if (apiAvailable && issueStatus.equals(triggerStatus)) {
                //we can do stuff (apiAvailable) and we should do stuff (issueStatus == triggerStatus)
                doStuff(issue);
            }
        }
        else if (eventType == EventType.ISSUE_GENERICEVENT_ID) {
            //triggered upon any status transition (and possibly other actions); 
            //need to see if the status has actually been modified
            String oldStatus = [???];  //FIXME:  need to get the previous status here
            boolean statusChanged = ! issueStatus.equals(oldStatus);
            if (apiAvailable && statusChanged && issueStatus.equals(triggerStatus)) {
                //we can do stuff (apiAvailable && statusChanged) and we should do stuff (issueStatus == triggerStatus)
                doStuff(issue);
            }
        }
    }
}

So the only catch is with the line that goes:

String oldStatus = [???];

What's the correct way to programmatically get the issue's previous status, or to otherwise identify that the event has been received because the issue's status has changed?

Note that I'm working with Jira 7.x. Support for previous Jira versions isn't a concern.

Upvotes: 1

Views: 430

Answers (1)

aroth
aroth

Reputation: 54836

Found some helpful information here, and put the following together:

private String getPreviousStatusId(Issue issue, IssueEvent event) {
    try {
        GenericValue changeLog = event.getChangeLog();

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

        List<GenericValue> changes = changeLog.internalDelegator.findByAnd("ChangeItem", fields);
        for(GenericValue changeVal : changes){
            String field = changeVal.getString("field");
            if ("status".equals(field)) {
                return changeVal.getString("oldvalue");
            }
        }
    }
    catch(Exception e) {
        e.printStackTrace();
    }

    //if no changes were made to the 'status' field (or we errored out), just return the issue's current status
    return issue.getStatusId();
}

Works like a charm.

Upvotes: 1

Related Questions