I don’t think it is a coincidence that Atlassian JIRA is the issue tracking tool used in every project I’ve been part of up until now. Although there are quite a few similar products on the market, JIRA is one of the names recognized by most of the actors involved in software projects. Together with other renowned titles such as Bugzilla or Redmine, JIRA stands out thanks to its complete functionalities set, its quality, ease of use and also its extensibility.
Atlassian JIRA was designed as a flexible product, easily extensible via plug-ins. In addition, the system communicates with the outer world through a REST interface. By this means, the clients of the platform are able to perform various operations. In the next paragraphs we will focus on the features of this API, talking about a few classic use cases, such as searching for an issue or adding a work log. Also, we will spend some time looking both at the Java client provided by Atlassian and the implementation of a REST client using Jersey.
Atlassian provides us with a class library destined to ease our work with the REST API, suggestively called JIRA REST Java Client. This library publishes, in turn, an almost complete API for the operations we can perform in a JIRA project. For instance, using this client we are able to retrieve a project by its key, create issues, delete them, add attachments, add work logs and many more.
The methods that we can use are grouped in a few classes based on the business object that we’re talking about. For instance, we can call the methods pertaining to issue administration only after we get an object of the IssueRestClient
type. Before that, we need an object of the JiraRestClient
type, created by the means of an asynchronous implementation of the JiraRestClientFactory
interface.
The details mentioned above can be noticed in the JiraClient
class, which is part of the demo project that accompanies this article. The project can be downloaded from the address mentioned in the Resources section. We have to notice that this Java project has an educational purpose and the source code is minimal, not trying to follow the best practices.
Let’s assume we want to retrieve, using the JRJC library, an Issue object that models the details of a JIRA ticket. Now that we have a JiraRestClient
object, we can write the following:
Promise promise = jiraRestClient.getIssueClient().getIssue("JRA-9");
Issue issue = promise.claim();
We notice that the getIssue(String issueKey)
method returns a Promise
; therefore, in order to retrieve the Issue instance we have to call the claim() method. We have to proceed the same way when we want to retrieve other objects such as projects, work logs etc.
One of the advantages of using this library is the fact that we don’t have to take care of the subtleties of working with REST. In fact, up until now, the fact that we were dealing with a REST API was transparent for us. In order to obtain a better image of what JIRA REST API is, we have to create our own implementation of a REST client. We will do that using Jersey.
Jersey offers us a simple and quick way to create a REST client. We illustrate that in the following lines of code:
String auth = new String(Base64.encode(USERNAME + ":" + PASSWORD));
Client client = Client.create();
WebResource webResource = client.resource(JIRA_SERVER + REST_PATH + query);
Builder builder = webResource.header("Authorization", "Basic " + auth).type(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON);
Back to the scenario where we want to retrieve an issue based on the key, we assume that the query parameter contains a path such as issue/JRA-9, where JRA-9 is the key of the ticket. In order to get the Issue object we call the get()
method which matches the HTTP GET
method.
ClientResponse clientResponse = builder.get(ClientResponse.class);
Now we are able to retrieve the serialized JSON object, in the form of a String:
String json = clientResponse.getEntity(String.class);
This String can then be deserialized as a bean designed by us, using the Jackson library. This library offers us various tools for working with JSON.
This scenario is one of the simplest, but things get more complicated when we have to create a work log, for instance. In this case, first we have to create a bean to model a work log with and to populate an instance with the information we want to persist. Then, we have to serialize this object as a String and transmit it to the REST service using the pattern shown above, this time via the HTTP POST method. The answer of the service will contain the stored object in its serialized form, enriched with new information such as the id of the work log.
JIRA REST API is an interface for the outer world with real business value. This API offers organizations the possibility to easily integrate the tool in their ecosystem to define creative and complex processes. However, one can notice that JIRA REST API doesn’t cover 100% the use cases of JIRA. One of the aspects that the users are waiting a resolution to is the impossibility to work with saved filters. There is a ticket on this subject (JRA-36045), that is still open.
On the other hand, we have to mention that the REST API comes with important functionalities such as the possibility to retrieve the custom fields and their value, something that was impossible using the SOAP API.
JIRA REST API is at its second version and although there is room for improvement, we can say it’s a well-established product which comes with important functionalities compared to its predecessor.
https://jira-rest-client-ro-leje.googlecode.com/svn/trunk
https://docs.atlassian.com/jira/REST/latest/
http://www.j-tricks.com/tutorials/java-rest-client-for-jira-using-jersey