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'));
CODE

Populate Issue fields in the template:

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

Create the issue using this populated template:

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

Obtain the newly created Issue Key and Issue ID

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

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'));
CODE

or by its Jira field ID

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

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')
CODE

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'));
CODE

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'));
CODE

Due date

Populating a date field

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

Populating a date field from a string

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

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'));
CODE

Components by ID:

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

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'));

CODE

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'));
CODE

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');
CODE

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);
    }
}
CODE

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){
    ...
}
CODE


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);
CODE

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);
CODE

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);

CODE

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);
CODE

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);
CODE

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'));
CODE

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);
CODE

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

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

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);
CODE

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);
CODE

The following method will validate and sanitize:

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

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);
			...
		}	
	}
}
CODE

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);
CODE

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>();
CODE

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);
CODE

and finally use the method:

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

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')});

CODE

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);
CODE

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');
CODE

Populate Issue fields in the template:

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

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);
CODE

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');

CODE

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);

CODE

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){
	... 
}

CODE

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);
CODE

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);

CODE

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);
CODE
... 
List<zsfjira.ZCBeans.IssueUpsertResult> iresults = zsfjira.ZC.Issues.validateAndSanitizeBulkUpdateIssuesInput(lstIssues);
...
CODE

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); 
			... 
		}
	 }
 }
CODE

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>();
CODE

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);
CODE

Finally use the method

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

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'});
CODE

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.