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
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000wg9bS'));
Populate Issue fields in the template:
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:
zsfjira.ZCBeans.IssueUpsertResult ir = zsfjira.ZC.Issues.createIssue(issue);
Obtain the newly created Issue Key and Issue ID
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
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate(Id.valueOf('500i000000weOJe'));
...
issue.setPriority(new zsfjira.ZCBeans.NameIssueFieldValue('Lowest'));
or by its Jira field ID
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
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
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:
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
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
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
issue.addComponent(new zsfjira.ZCBeans.NameIssueFieldValue('SELCOMP1'));
issue.addComponent(new zsfjira.ZCBeans.NameIssueFieldValue('SELCOMP2'));
Components by ID:
issue.addComponent(new zsfjira.ZCBeans.IdIssueFieldValue('10000'));
Fix Versions and Affect Versions by name:
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:
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:
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.
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.
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
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:
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:
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’
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’
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.
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:
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.
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateBulkCreateIssuesInput(lstIssues);
To check if the issues contain errors:
...
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).
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:
...
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:
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
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:
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();
after populating the templates, add them to the list.
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:
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:
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.
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:
zsfjira.ZCBeans.IssueTemplate issue = new zsfjira.ZCBeans.IssueTemplate('SEL-101');
Populate Issue fields in the template:
issue.setSummary('Test Issue(edited)');
Currently, the API does not support modifying the Jira Project to which the Issue is assigned
Update the issue:
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.
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:
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.
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.
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.
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateBulkUpdateIssuesInput(lstIssues);
Also, similar to the Create operation, you can remove/sanitize invalid data during validation.
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);
...
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:
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:
List<zsfjira.ZCBeans.IssueTemplate>lstIssues = new List<zsfjira.ZCBeans.IssueTemplate>();
after populating the templates, add them to the list.
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
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:
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.