Skip to main content
Skip table of contents

zAgileConnect API – Create and Update Jira Issues from Salesforce – Usage & Examples

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

Create a Jira issue

Create an Issue template related to a Salesforce entity ID

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000wg9bS'));

Populate Issue fields in the template:

CODE
issue.setSummary('Test Issue');
issue.setProject(new zsfjira.ZCBeans.KeyIssueFieldValue('SEL'));
issue.setIssueType(new zsfjira.ZCBeans.NameIssueFieldValue('Bug'));

Create the issue using this populated template:

CODE
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.createIssue(issue);

Obtain the newly created Issue Key and Issue ID

CODE
System.debug(System.LoggingLevel.INFO,ir.getIssueKey());
System.debug(System.LoggingLevel.INFO,ir.getIssueId());

The created Issue is automatically associated with the Case from which it was created (specified via the Salesforce entity ID above).

Populating Standard Issue Fields

The following section shows examples of populating various types of standard Jira Issue fields

Priority

A field may be populated in the template either by name

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setPriority(new zsfjira.ZCBeans.NameIssueFieldValue('Lowest'));

or by its Jira field ID

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setPriority(new zsfjira.ZCBeans.IdIssueFieldValue('4'));

Description and Environment

Populating Description and Environment fields

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setDescription('this is a test description');
issue.setEnvironment('this is a test environment')

Assignee and Reporter

Populating fields with Jira user

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setIssueReporter(new zsfjira.ZCBeans.NameIssueFieldValue('sromero'));
issue.setIssueAssignee(new zsfjira.ZCBeans.NameIssueFieldValue('sromero'));

using User Ids:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setIssueReporter(new zsfjira.ZCBeans.IdIssueFieldValue('5e36f0e24512b80ca4317bf4'));
issue.setIssueAssignee(new zsfjira.ZCBeans.IdIssueFieldValue('5e36f0e24512b80ca4317bf4'));

Due date

Populating a date field

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setDuedate(Date.newInstance(2018, 5, 22));

Populating a date field from a string

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setDuedateString('2018-05-22');

Components, Affect versions and Fix Versions

You can use the following methods to populate the template, with the Component/Version name or ID.

Components by name

CODE
issue.addComponent(new zsfjira.ZCBeans.NameIssueFieldValue('SELCOMP1'));
issue.addComponent(new zsfjira.ZCBeans.NameIssueFieldValue('SELCOMP2'));

Components by ID:

CODE
issue.addComponent(new zsfjira.ZCBeans.IdIssueFieldValue('10000'));

Fix Versions and Affect Versions by name:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.addFixVersion(new zsfjira.ZCBeans.NameIssueFieldValue('SELVER1'));
issue.addFixVersion(new zsfjira.ZCBeans.NameIssueFieldValue('SELVER2'));

issue.addAffectVersion(new zsfjira.ZCBeans.NameIssueFieldValue('SELVER1'));
issue.addAffectVersion(new zsfjira.ZCBeans.NameIssueFieldValue('SELVER1'));

Fix Versions and Affect Versions by ID:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.addFixVersion(new zsfjira.ZCBeans.IdIssueFieldValue('10100'));
issue.addFixVersion(new zsfjira.ZCBeans.IdIssueFieldValue('10101'));

issue.addAffectVersion(new zsfjira.ZCBeans.IdIssueFieldValue('10100'));
issue.addAffectVersion(new zsfjira.ZCBeans.IdIssueFieldValue('10101'));

Labels

Use the following method for adding labels to the template:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.addLabel('salesforce');
issue.addLabel('assistance');

Error handling

The method hasError() return true if issue creation fails. The method getErrorMessages() returns a list of errors.

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
zsfjira.ZCBeans.IssueUpsertResult iresult = zsfjira.ZC.Issues.createIssue(issue);
...
if(iresult.hasError()){
    for(String errorMessage:iresult.getErrorMessages()){
        System.debug(System.LoggingLevel.ERROR,errorMessage);
    }
}

License Handling

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

CODE
try{
    zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
	...
    zsfjira.ZCBeans.IssueUpsertResult iresult = zsfjira.ZC.Issues.createIssue(issue);
}catch(Exception exe){
    ...
}


Publish errors to Case object

You can publish the errors to the related Case object by invoking the method postCreateIssueErrorMessage of the API

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
zsfjira.ZCBeans.IssueUpsertResult iresult = zsfjira.ZC.Issues.createIssue(issue);
...
zsfjira.ZC.Issues.postCreateIssueErrorMessage(iresult);

Customizing error messages

To add a custom prefix to the error messages:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
zsfjira.ZCBeans.IssueUpsertResult iresult = zsfjira.ZC.Issues.createIssue(issue);
...
zsfjira.ZC.Issues.postCreateIssueErrorMessage('INVALID INPUT',iresult);

Custom fields

Populating Issue custom fields requires access to the issue metadata. The following REST method may be used to access the Jira Issue metadata in JSON format:

/rest/api/2/issue/createmeta?expand=projects.issuetypes.fields

The metadata describes the Issue fields and values allowed for the fields.

locate the section ‘fields’ in the JSON:

Custom fields will have the prefix “customfield”

Populating a string custom field

We locate the custom field ‘case origin’ which has the identifier ‘customfield_10500’:

Since the field is a string, we simply pass a string value to the template:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('5000H00000xfLfI'));
...
issue.addCustomField('customfield_10500','String example');
...
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.createIssue(issue);

The following screenshot shows the populated custom field in the Jira Issue:

Populating a single list custom field

We locate the custom field ‘JPSingleSelect’ which has the identifier ‘customfield_10401’

Based on picklist values available for this field, we are going to populate the field with “one”.

To achieve that, we send the value as a map containing the desired ID (‘10308’) that belongs to the value ‘one’

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('5000H00000xfLfI'));
...
issue.addCustomField('customfield_10401',new Map<String,String>{'id'=>'10308'});
...
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.createIssue(issue);

This results in the following:

Populating a multi list custom field:

We locate the custom field ‘ZMULTIPICKLIST‘ which has the identifier ‘customfield_10600

As in the former example we have allowed values, we are going to fill the field with “TURCO” and “ANDROIDE”, in order to achieve that we are going to send the value as List of Maps containing the desired id’s that belongs to the values “TURCO” and “ANDROIDE” that are ‘10402’ and ‘10403’

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('5000H00000xfLfI'));
...
List<Map<String,String>> lstMultipickList= new List<Map<String,String>>();
lstMultipickList.add(new Map<String,String>{'id'=>'10402'});
lstMultipickList.add(new Map<String,String>{'id'=>'10403'});

issue.addCustomField('customfield_10600',lstMultipickList);
...
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.createIssue(issue);

This results in the following:

Pre-populate issues with Case data

You can build populated templates with the Case information according to the Case/Issue field mapping. This will allow you to build templates and manipulate fields before creating the issues. To achieve this, pass Case ID to the method for which you want to create the issue and the method will return the template.

CODE
zsfjira.ZCBeans.IssueTemplate issue = zsfjira.ZC.IssueFactory.buildCreateTemplateFromMapping(Id.valueOf('500i000000weOJe'));

You can modify the template by adding/removing issue standard/custom fields, as well as, process error handling, as discussed earlier.

Validate Issue data before creating

To perform a validation before creating the issues to ensure fields are populated as required by Jira:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
issue.setProject(new zsfjira.ZCBeans.KeyIssueFieldValue('SEL'));
issue.setIssueType(new zsfjira.ZCBeans.NameIssueFieldValue('Bug'));

List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();
lstIssues.add(issue);

The method ZC.Issues.validateBulkCreateIssuesInput() is used with a list of issues as parameter.

CODE
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateBulkCreateIssuesInput(lstIssues);

To check if the issues contain errors:

CODE
...
for(zsfjira.ZCBeans.IssueUpsertResult iresult:iresults){
    if(iresult.hasError()){
        System.debug(System.LoggingLevel.ERROR,'Mistakes in the Issue Template:');
        for(String errorMessage:iresult.getErrorMessages()){
            System.debug(System.LoggingLevel.ERROR,errorMessage);
        }
    }
}
...
zsfjira.ZC.Issues.postCreateIssueErrorMessages(iresults);

Debugging invalid data during validation

During the validation you can remove invalid data via the method validateAndSanitizeBulkCreateIssuesInput. This method removes fields that are not present in the Issue metadata or are deemed invalid based on the metadata.

Example 1:

Creating an issue with priority value ‘more or less urgent’ (invalid value).

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));

issue.setSummary('Test Issue');
issue.setProject(new zsfjira.ZCBeans.KeyIssueFieldValue('SEL'));
issue.setIssueType(new zsfjira.ZCBeans.NameIssueFieldValue('Bug'));
issue.setPriority(new zsfjira.ZCBeans.NameIssueFieldValue('More or Less Urgent'));

List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();
lstIssues.add(issue);

The following method will validate and sanitize:

CODE
...
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateAndSanitizeBulkCreateIssuesInput(lstIssues);
...

If field values are removed as a result of the validation, warnings are provided and may be accessed as shown below:

CODE
for(zsfjira.ZCBeans.IssueUpsertResult iResult:iresults){
	if(iResult.hasWarnings()){
		for(String warningMessage:iResult.getWarningMessages()){
   			System.debug(System.LoggingLevel.WARN,warningMessage);
			...
		}	
	}
}

A warning that removes an invalid field looks as follows:

16:56:24:071 USER_DEBUG [16]|WARN|Field “priority” does not allow an entry with value “More or Less Urgent”


Example 2:

To create an issue with a non existent custom field

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));

issue.setSummary('Test Issue');
issue.setProject(new zsfjira.ZCBeans.KeyIssueFieldValue('SEL'));
issue.setIssueType(new zsfjira.ZCBeans.NameIssueFieldValue('Bug'));
issue.addCustomField('custom_1','custom string value');

List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();
lstIssues.add(issue);

using the same methods as in the previous example, the custom field will be removed from the template and a warning will be returned as below:

16:56:24:071 USER_DEBUG [16]|WARN|Issue type metadata does not hold field “custom_1”

Bulk Operations

This section describes processing of multiple Issues via the API

Please use the bulk operations if you want to create multiple issues. You can not create multiple issues by iterating through the single create operations since each single operation consumes Web service calls and DML operations and Salesforce does not allow a sequences of those operations in a single request.

Since creating an issue implies many Web Service operations, due to Salesforce limits, the creation method will only allow you to create a few number of issues at a time. We recommend not exceeding 10 issues per request. If you need to create larger number of issues, then you may want to consider other approaches, such as Apex Batch jobs.

Create issues in bulk

To create multiple issues, define a list of templates as follows:

CODE
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();

after populating the templates, add them to the list.

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
lstIssues.add(issue);
...
zsfjira.ZCBeans.IssueTemplate issue2 = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weAjo'));
...
lstIssues.add(issue);

and finally use the method:

CODE
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.bulkCreateIssues(lstIssues);

You can iterate the list to for specific errors related to an Issue.

Build issues templates in bulk

Templates may be pre-populated using entity (Case) fields. You can generate multiple templates using the following method:

CODE
 List<zsfjira.ZCBeans.IssueTemplate>lstIssues = zsfjira.ZC.IssueFactory.buildCreateTemplateFromMapping(new List<Id>{Id.valueOf('500i000000weOJe')});

Publishing Bulk operation errors

To publish the errors in the Cases associated with the Bulk Issue create operation, invoke the method postCreateIssueErrorMessages with the list of issues.

CODE
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();
...
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.bulkCreateIssues(lstIssues);
...
zsfjira.ZC.Issues.postCreateIssueErrorMessages(iresults);

Create Issues using Process builder

You can create an Issue when a new Salesforce record is created or updated by using Process Builder and adding an Apex action to your process:

By adding a new Action, select a new Action of Type Apex, set a proper name and choose our Apex Class Create Issue:

the entity ID is a required field specifying the entity to which the issue will be linked. Reference the ID by clicking on Value and adding the reference:

To create the issue, zAgileConnect will use the field mapping for filling the issue fields. You may optionally override these field values by adding them as parameters to the Apex code:

To populate custom fields for an Issue, use the parameter customFieldsJSON in which you can use a formula for building the JSON as string.

Errors during creation are sent via email to the configured email for notifications.

Update a Jira issue

Create a template related to a Jira issue key:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101');

Populate Issue fields in the template:

CODE
issue.setSummary('Test Issue(edited)');

Currently, the API does not support modifying the Jira Project to which the Issue is assigned

Update the issue:

CODE
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.updateIssue(issue);

Pre-populate issues with Case information

You can build populated templates with the existing issues using their parent (Case) entity data according to the Entity/Issue field mapping. Send to the method an Issue Key and it will return a template containing the JIRA Issue populated with their Salesforce parent data.

CODE
zsfjira.ZCBeans.IssueTemplate issue = zsfjira.ZC.IssueFactory.buildUpdateTemplateFromMapping('SEL-102');

Handle Errors

To publish errors to the parent entity, pass the Issue Key and Parent entity ID to the method:

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101');
 ... 
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.updateIssue(issue);
 ... 
zsfjira.ZC.Issues.postErrorMessageToEntity(Id.valueOf('5000H00000xfLfIQAU'),ir);

License Handling

The update API requires a valid zAgileConnect license for the user executing the operation. You can catch the exception, if needed.

CODE
try{ 
	zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101');
	 ... 
	zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.updateIssue(issue);
}catch(Exception exe){
	... 
}

Validate Issue data before updating

Same as the Create operation discussed earlier, you can validate the issues template before sending the update request to Jira.

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101');
 
issue.setEntityId('5000H00000xfLfIQAU'); 
issue.setProject(new zsfjira.ZCBeans.KeyIssueFieldValue('SEL')); 
issue.setIssueType(new zsfjira.ZCBeans.NameIssueFieldValue('Bug')); 

List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>(); 
lstIssues.add(issue);

Call the method zsfjira.ZC.Issues.validateAndSanitizeBulkUpdateIssuesInputt() and send the list of Issues as parameter.

CODE
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateBulkUpdateIssuesInput(lstIssues);

Also, similar to the Create operation, you can remove/sanitize invalid data during validation.

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101'); 
issue.setEntityId('5000H00000xfLfIQAU'); 
... 
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>(); 
lstIssues.add(issue);
CODE
... 
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateAndSanitizeBulkUpdateIssuesInput(lstIssues);
...

If the validation has removed values, then you can find those as warnings that can be accessed as follows:

CODE
for(zsfjira.ZCBeans.IssueUpsertResult iResult:iresults){ 
	if(iResult.hasWarnings()){ 
		for(String warningMessage:iResult.getWarningMessages(){ 
			System.debug(System.LoggingLevel.WARN,warningMessage); 
			... 
		}
	 }
 }

Bulk Operations for Issue Updates

To edit multiple issues, define a list of templates as follows:

CODE
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();

after populating the templates, add them to the list.

CODE
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101'); 
... 
lstIssues.add(issue); 
... 
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-103'); 
... 
lstIssues.add(issue);

Finally use the method

CODE
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.bulkUpdateIssues(lstIssues);

The error handling is individual for each template and keeps the same structure. You can iterate the list to find Issues with errors/warnings.

Build Issues templates in bulk

Similar to Issue creation, you can pre-populate templates for editing in bulk using the following method:

CODE
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = zsfjira.ZC.IssueFactory.buildUpdateTemplateFromMapping(new Set<String> {'SEL-102'});

Update Issues using Process builder

Add a new Action of type Apex and choose our Apex Class Update Issue. The issue key is required:

Errors during update are sent via email to the configured email for notifications.

JavaScript errors detected

Please note, these errors can depend on your browser setup.

If this problem persists, please contact our support.