Available: | Jira 4.1 and later. |
This page introduces concepts and techniques for working with Jira issues in an app.
Jira 4.1 introduced an API level object called the IssueService. This service class is used to perform create, update, delete, and transition operations in Jira with issue. This services methods make sure that when dealing with issues all of Jira's business rules are enforced. This means that permissions and data validation will be checked, proper events will be fired, and notifications will be triggered.
App developers who want to perform any of these operations should use the IssueService
as it abstracts the normally
complicated issue operations into something a bit simpler and it ensures that you do not put corrupted data into Jira.
The general format of the service is that there are two methods per operation – validation and "do" method. The validation method generates a result object that is used as the parameter to the next "do" method. If validation does not pass, there is internationalized error message in the result object that explains what is wrong and you are not able to invoke the "do" method with this parameter.
The "do" methods also return a result object that contains the new state of the issue if the operation is successful and errors if something goes wrong during the action.
You can get an IssueService
object either by constructor injection using
Atlassian Spring Scanner or explicitly via a
getIssueService
call like:
1 2IssueService issueService = ComponentAccessor.getInstance().getIssueService();
Issues can be retrieved using the IssueService
either by ID or key:
1 2IssueService.IssueResult issueResult = issueService.getIssue(applicationUser, 10000L); MutableIssue mutableIssue = issueResult.getIssue(); //OR IssueService.IssueResult issueResult = issueService.getIssue(null, "JRA-1234"); MutableIssue mutableIssue = issueResult.getIssue();
To perform an operation on an issue, you need to use an instance of com.atlassian.jira.issue.IssueInputParameters as a builder that lets you tell Jira what you want the issue to look like.
Here is an example of how to use the builder object:
1 2IssueInputParameters issueInputParameters = issueService.newIssueInputParameters(); issueInputParameters.setProjectId(12345L) .setIssueTypeId("2"); .setSummary("This is a summary"); .setReporterId("joeuser"); .setAssigneeId("otheruser"); .setDescription("I am a description"); .setEnvironment("I am an environment"); .setStatusId("2"); .setPriorityId("2"); .setResolutionId("2"); .setSecurityLevelId(10000L); .setFixVersionIds(10000L, 10001L);
Sometimes you may need to set a field that is not present on create
or update
screens. To do so, you need
to use following method:
1 2issueInputParameters.setSkipScreenCheck(true);
This is used in issue creation, update, and transitions to specify new or updated values.
This builder can be used to add comments (with or without restrictions) to an issue and to set custom field values.
For full details, see the javadoc about IssueInputParameters
mentioned previously.
Custom fields values can be added via the com.atlassian.jira.issue.IssueInputParameters.addCustomFieldValue
methods.
Here some content describing how the values
strings should be formatted for the various field types.
1 2IssueInputParameters issueInputParameters = issueService.newIssueInputParameters(); issueInputParameters .addCustomFieldValue(myNumberField.getId(), "3") .addCustomFieldValue(myDateField.getId(), "3/Jan/2012") .addCustomFieldValue(myDateTime.getId(), "30/Jan/13 10:53 PM") .addCustomFieldValue(mySelectList.getId(), "1234") // 1234 is option id as string .addCustomFieldValue(myMultiSelectList.getId(), "1234, 5678") // 1234 and 5678 are option id's as strings .addCustomFieldValue(myMultiSelectUserList.getId(), "uname1, uname2") .addCustomFieldValue(myCascadingSelectList.getId(), <parent option id as string>) .addCustomFieldValue(myCascadingSelectList.getId() + ":1", <child option id as string>);
After you set up the issue builder in the way you would like, you need to get an instance of the issue service.
To validate that your issue can be created as specified, you must invoke the validateCreate
method. If there
are any errors (for example, insufficient permissions, missing required fields, referencing values that do not
exist, and so on), there will be i18n'ed messages in the returned result object.
Once you have a valid CreateValidationResult
, you can pass this object to the issue service create
method.
This will create the issue and perform all the related tasks (event publication, issue indexing, and so on).
The create result will only have errors if there is a severe problem with Jira (for example, can't communicate with
the database, the workflow has changed since you invoked validate, and so on).
For full details, see the javadoc.
Here is an example of how to invoke the service to create the issue we setup above:
1 2IssueService issueService = ComponentAccessor.getInstance().getIssueService(); CreateValidationResult createValidationResult = issueService.validateCreate(user, issueInputParameters); if (createValidationResult.isValid()) { IssueResult createResult = issueService.create(user, createValidationResult); if (!createResult.isValid()) { // Do something } }
Editing an existing issue is very similar to creating an issue.
You need to use the same com.atlassian.jira.issue.IssueInputParameters
as a builder that lets you tell Jira what you want to change in the issue.
You must invoke the validateUpdate
method with the issue ID you wish to update and the IssueInputParameters
that contains the changes that you want to apply. This will produce an UpdateValidationResult
that you can
provide to the update
method.
If there are any errors (for example, insufficient permissions, missing required fields, referencing values that do not exist, and so on), there will be i18n'ed messages in the returned result object.
Once you have a valid UpdateValidationResult
, you can pass this object to the issue service update
method.
This will update the issue and perform all the related tasks (event publication, issue indexing, and so on).
The update result will only have errors if there is a severe problem with Jira (for example, can't communicate
with the database, the workflow has changed since you invoked validate, etc.).
For full details, see the javadoc.
Here is an example of how to invoke the service to update the summary of an issue with an ID of 12345:
1 2IssueInputParameters issueInputParameters = issueService.newIssueInputParameters(); issueInputParameters.setSummary("I am a new summary"); IssueService issueService = ComponentAccessor.getInstance().getIssueService(); UpdateValidationResult updateValidationResult = issueService.validateUpdate(user, 12345L, issueInputParameters); if (updateValidationResult.isValid()) { IssueResult updateResult = issueService.update(user, updateValidationResult); if (!updateResult.isValid()) { // Do something } }
Transitioning an issue is much like editing an issue. You need to specify an additional parameter, the transition
action ID, which identifies the transition the issue should make, along with the IssueInputParameters
object
specifying any values you wish to set while transitioning. You must invoke the validateTransition
method on
the issue service to generate a TransitionValidationResult
.
If there are any errors (for example, insufficient permissions, missing required fields, referencing values that do not exist, and so on) then there will be i18n'ed messages in the returned result object.
Once you have a valid TransitionValidationResult
, you can pass this object to the issue service transition method.
This will transition the issue and perform all the related tasks (event publication, issue indexing, workflow post
functions, and so on). The transition result will only have errors if there is a severe problem with Jira
(for example, can't communicate with the database, the workflow has changed since you invoked validate, and so on).
For full details, see the javadoc.
Here is an example of how to invoke the service to transition an issue with an ID of 12345 to an ID of 10000 while also setting the assignee:
1 2IssueInputParameters issueInputParameters = issueService.newIssueInputParameters(); issueInputParameters.setAssigneeId("newdude"); IssueService issueService = ComponentAccessor.getInstance().getIssueService(); TransitionValidationResult transitionValidationResult = issueService.validateTransition(user, 12345L, 10000L, issueInputParameters); if (transitionValidationResult.isValid()) { IssueResult transitionResult = issueService.transition(user, transitionValidationResult); if (!transitionResult.isValid()) { // Do something } }
To delete an issue, you need to provide the issue service with the ID of the issue you wish to
delete. You must invoke the validateDelete
method and it will generate a DeleteValidationResult
.
This can be used to invoke the delete
method.
If there are any errors (for example, insufficient permissions, the issue no longer exists, and so on), then there will be i18n'ed messages in the returned result object.
Once you have a valid DeleteValidationResult
, you can pass this object to the issue service delete method
.
This will delete the issue and perform all the related tasks (delete associated attachments, comments, worklogs, and so on).
The delete result will only have errors if there is a severe problem with Jira.
For full details, see the javadoc.
Here is an example of how to invoke the service to delete an issue with an ID of 12345:
1 2IssueService issueService = ComponentAccessor.getInstance().getIssueService(); DeleteValidationResult deleteValidationResult = issueService.validateDelete(user, 12345L); if (deleteValidationResult.isValid()) { ErrorCollection deleteErrors = issueService.delete(user, deleteValidationResult); if (deleteResult.hasAnyErrors()) { // Do something } }
If, for some reason, you do not want to use the IssueService
class, then you should look at the javadoc
for the IssueManager
class for create, delete, and update, and also at the
WorkflowManager
for the transition.
However, we highly recommend using the IssueService
class for these operations since there is a lot of business
logic associated with issue operations.
The following sample iterates over a list of issues and for each issue retrieves its linked issues. This code can be useful if you create a custom report that shows linked issues.
Remember that each link has a direction and a type. Therefore the issues in the Link Collection
are grouped
by link type and direction.
1 2// A list of Issues representing issues List<Issue> issues = ... for (Issue issue: issues ) { // Retrieve a collection of all linked issues and their link types LinkCollection linkCollection = issueLinkManager.getLinkCollection(issue, authenticationContext.getLoggedInUser()); Set<IssueLinkType> linkTypes = linkCollection.getLinkTypes(); if (linkTypes != null) { // For each link type for (IssueLinkType linkType : linkTypes) { // Get the outward linked issues List<Issue> outwardIssues = linkCollection.getOutwardIssues(linkType.getName()); if (outwardIssues != null) { for (Issue outwardIssue : outwardIssues) { System.out.println("outwardIssue = " + outwardIssue); } } // And the inward linked issues List<Issue> inwardIssues = linkCollection.getInwardIssues(linkType.getName()); if (inwardIssues != null) { for (Issue inwardIssue : inwardIssues) { System.out.println("inwardIssue = " + inwardIssue); } } } } }
One way to retrieve a list of issues is to make and run a Search Request.
Note that the code above uses JiraAuthenticationContext
to retrieve the application user. The easiest way to get
access to an instance of the JiraAuthenticationContext
is to declare it as a dependency in the constructor of your class.
1 2@Named public class ExampleClass { @JiraImport private JiraAuthenticationContext authenticationContext; @Inject public ExampleClass(JiraAuthenticationContext authenticationContext) { this.authenticationContext = authenticationContext; } }
Also read about Creating a Jira issue CRUD servlet and issue search.
Rate this page: