Please note that zAgileConnect license is required for a user to invoke this API. The methods will throw a zsfjira.ZC.ZCApiLicenceException when executed by a user without a zAgileConnect license

Summary Steps

1. Retrieve the available Transitions for an Issue

zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('SEL-1');
CODE

2. Create a Transition Issue Bean

zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('In Progress');
CODE

3. Execute the Transition

zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue('SEL-1', transitionIssueBean);
CODE

1. Retrieve Available Transitions for an Issue

You can get the Available Transitions Names as follows:

zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('SEL-1');
List<String> transtionsNames = availableTransitionsResult.getAvailableTransitionsNames();
CODE

In some scenarios you may want to retrieve all the available transitions metadata returned by Jira API. It can be done using the method getTransitionsData(), it will return the metadata as a Map<String, Object>

ZCBeans.AvailableTransitionsResult availableTransitionsResult = ZC.Issues.getAvailableTransitions('SEL-1019');
Map<String, Object> transtionsData = availableTransitionsResult.getTransitionsData();
CODE

The retrieved metadata looks like:

{    
       "transitions": [ 
              { 
                     "fields": {}, 
                     "to": {
                                    //...
                            },
                     "name": "Stop Progress",
                     "id": "301"      
               }, 
               {
                     "fields": 
                      { 
                          "assignee": {
                                        "operations": ["set"],
                                        "autoCompleteUrl": "....",
                                        "name": "Assignee",
                                        "schema": {
                                           "system": "assignee",
                                           "type": "user"
                                         },
                                        "required": false
                                        }
                       },
                       "to": {
                                     //..
                       },
                       "name": "Resolve Issue",
                       "id": "5"
               }    ],
        "expand": "transitions"
}
CODE

2. Create a Transition Issue Bean

There are two different ways of creating the Transition Issue Bean:

  • From the AvailableTransitionsResult, where you first retrieve the available transitions for the Issue and then create the Transition Bean for a particular Transition Name.
zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('SEL-1');
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('In Progress');
CODE
  • From scratch specifying the Transition ID.

You can execute transition without calling first the getAvailableTransitions() method that retrieves Jira metadata, if you know the ID of the transition you want to try to execute. Please note the transitions that can be executed for an Issue depends on the Jira workflow, so it is possible that a transition can only be executed if the Issue has a specific status (for example an Issue can not execute the transitions “Close” if the issue is already closed).

You can create a IssueTransitionBean directly with the transition ID. Please note when setting transition screen field values (as described below) without retrieving the metadata for available Transitions you will need to set field values by its field ID (using setFieldById() method).

Integer transitionId = 41;//"Done" transition Id
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = new zsfjira.ZCBeans.TransitionIssueBean(transitionId);
transitionIssueBean.setFieldById('resolution', new Map<String, String>{'name' => 'Fixed'});
transitionIssueBean.setFieldById('summary', 'The new summary');
zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue('OP-3165', transitionIssueBean);
CODE

2.1 Transition Screen Fields

Some Issue transitions may have a screen of fields configured in Jira, some of them may be required for the transition to be executed. You can set values for the Issue fields in the transition screen before executing the transition.

Getting Transition Screen Fields Names
zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('OP-3165'); 
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('Done');
List<String> fieldsNames = transitionIssueBean.getFieldsNames();
CODE
Getting Required Transition Screen Fields Names
zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('OP-3165'); 
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('Done');
List<String> requiredFeldsNames = transitionIssueBean .getRequiredFieldsNames();
CODE
Populating Transition Issue Screen Fields

You can populate transition Issue screen fields by using the ‘Issue Template’, just like the issue template used for creating or updating issues.

zsfjira.ZCBeans.IssueTemplate issueTemplate = new zsfjira.ZCBeans.IssueTemplate('OP-3165');
issueTemplate.setFixVersions(new zsfjira.ZCBeans.NameOrIdIssueFieldValue[]{new zsfjira.ZCBeans.NameIssueFieldValue('1.0.4')}); 
issueTemplate.setSummary('new summary for issue transitioned');
issueTemplate.setReporter(new zsfjira.ZCBeans.NameIssueFieldValue('zagile'));

zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('OP-3165');
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('Done');
transitionIssueBean.populateFieldsWith(issueTemplate);
transitionIssueBean.setFieldByName('Resolution', new Map<String, String>{'name' => 'Fixed'});//you can also add more fields not supported in the issue template using the setFielByName or setFieldById
transitionIssueBean.setComment('A sample transition comment');
zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue('OP-3165', transitionIssueBean);
CODE

3. Execute the Transition

To execute the transition you will need to pass the Issuekey and the Transition Issue Bean described above

zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue('SEL-1', transitionIssueBean);
CODE

The execution will return a transition issue result that can be used for error handling.

3.1 Validate Transition Issue data before executing transition

You can validate and sanitize your Issue transition bean before trying to execute the transition. This will detect problems in the bean and try to correct them if possible. For example it will remove all transition screen fields that are not listed in the metadata and will return warning messages if there is a required field that is not set in the bean.

Integer transitionId = 41;// To Done
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = new zsfjira.ZCBeans.TransitionIssueBean(transitionId);
try{
   String warningMessage = transitionIssueBean.validateAndSanitize();
}
catch (Exception e){
   System.debug(System.LoggingLevel.ERROR, e.getMessage()); 
}
CODE
zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('OP-3165'); 
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('Start Progress');
transitionIssueBean.setFieldById('resolution', null);
try{
   String warningMessage = transitionIssueBean.validateAndSanitize();
}
catch (Exception e){
   System.debug(System.LoggingLevel.ERROR, e.getMessage()); 
}
CODE

The validateAndSanitize() will raise an Exception when a field has an empty value or there is not the metadata.

3.2 Error handling

The method hasError() returns ‘true’ if issue transition fails. The method getErrorMessage() returns the error message.

Integer transitionId = 41;// To Done
zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = new zsfjira.ZCBeans.TransitionIssueBean(transitionId);
transitionIssueBean.setFieldById('resolution', new Map<String, String>{'name' => 'Fixed'});
zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue('OP-3165', transitionIssueBean);
if(transitionIssueResult.hasError()){ 
    System.debug(System.LoggingLevel.ERROR, transitionIssueResult.getErrorMessage()); 
}
CODE

It may be also possible to run into some errors when trying to retrieve the available transitions, you can handle them as follows

zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('SEL-1019');
if(availableTransitionsResult.hasError()){
    System.debug(System.LoggingLevel.ERROR, availableTransitionsResult.getErrorMessage());
}
CODE

3.3 License Handling

All operations included in this API require the user to have a valid zAgileConnect license. Try..Catch blocks below show how to catch license exceptions.

try{
    zsfjira.ZCBeans.AvailableTransitionsResult availableTransitionsResult = zsfjira.ZC.Issues.getAvailableTransitions('SEL-1019');
    zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitionsResult.buildIssueTransitionFromName('Start Progress');
    zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue('SEL-1019', transitionIssueBean);
}catch(Exception exe){
    System.debug(System.LoggingLevel.ERROR, transitionIssueResult.getMessage()); 
    // Will indicate: User [Username] does need a zAgileConnect Licence to perform this operation.
}
CODE

Close a Jira Issue on Case Closed Example

trigger OnCaseClosedJiraIssuesTrigger on Case (after update) {
    List<Case> cases = new List<Case>();

    for(Case oldCase: Trigger.old){
        Case newCase = Trigger.newMap.get(oldCase.Id);
        if(oldCase.Status != newCase.Status && newCase.Status == 'Closed'){
            cases.add(oldCase);
        }
    }

    for(Case scase: cases){
        for ( zsfjira__ZIssue_SF__c issueSf :[SELECT zsfjira__ZIssue__r.zsfjira__IssueKey__c FROM zsfjira__ZIssue_SF__c WHERE zsfjira__Case__c = :scase.Id] ){
            CaseClosedJiraIssuesHandler.closeIssue(issueSf.zsfjira__ZIssue__r.zsfjira__IssueKey__c);
        }
    }
}


public class CaseClosedJiraIssuesHandler {
    
    @future (callout = true)
    public static void closeIssue(String issueKey){
        zsfjira.ZCBeans.AvailableTransitionsResult availableTransitions = zsfjira.ZC.Issues.getAvailableTransitions(issueKey);

        if(availableTransitions.getAvailableTransitionsNames().contains('Close Issue')){
            zsfjira.ZCBeans.TransitionIssueBean transitionIssueBean = availableTransitions.buildIssueTransitionFromName('Close Issue');
            transitionIssueBean.setFieldByName('Resolution', new Map<String, String>{'name' => 'Done'});
            transitionIssueBean.setComment('Closed by case closed');
            zsfjira.ZCBeans.TransitionIssueResult transitionIssueResult = zsfjira.ZC.Issues.transitionIssue(issueKey, transitionIssueBean);
        }
    }
}
CODE