Skip to content

Chavaillaz/jira-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

63 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Jira Client

Dependency Check Maven Central License

This library allows you to interact with a Jira instance and choose which HTTP client to use. It is also easily extendable, allowing you to have custom clients and issues classes. All requests are performed asynchronously and return a CompletableFuture. The serialization and deserialization of domain objects are performed using Jackson.

Presently, it supports the following HTTP clients:

Note that this library has been tested with a Jira instance version 8.20.

Installation

The dependency is available in maven central (see badge for version):

<dependency>
    <groupId>com.chavaillaz</groupId>
    <artifactId>jira-client</artifactId>
</dependency>

Don't forget to also declare the HTTP client you want to use as a dependency (see below), as it is only indicated as optional in the project, to avoid gathering them all together despite the fact that only one is needed.

Java HTTP client

It does not require any dependency (already in Java).

Apache HTTP client

It requires the following dependency:

<dependency>
    <groupId>org.apache.httpcomponents.client5</groupId>
    <artifactId>httpclient5</artifactId>
    <version>5.3.x</version>
</dependency>

OkHttp client

It requires the following dependency:

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.12.x</version>
</dependency>

Vert.x client

It requires the following dependency:

<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-web-client</artifactId>
    <version>4.5.x</version>
</dependency>

Usage

Features

  • IssueApi - Everything for issues, including comments, links, transitions, attachments and work logs
    • Issues
      • addIssue(Issue issue)
      • getIssue(String issueKey)
      • getIssue(String issueKey, Set<IssueExpand> flags)
      • getIssue(String issueKey, Set<IssueExpand> flags, Set<String> fields)
      • getIssueOptional(String issueKey)
      • getIssueOptional(String issueKey, Set<IssueExpand> flags)
      • getIssueOptional(String issueKey, Set<IssueExpand> flags, Set<String> fields)
      • updateIssue(Issue issue)
      • deleteIssue(String issueKey)
      • assignIssue(String issueKey, User user)
      • unassignIssue(String issueKey)
      • getTransitions(String issueKey)
      • doTransition(String issueKey, IssueTransition transition)
    • Comments
      • getComments(String issueKey)
      • getComments(String issueKey, Integer startAt, Integer maxResults)
      • getComments(String issueKey, Integer startAt, Integer maxResults, Set<CommentExpand> flags)
      • getComment(String issueKey, String id)
      • getComment(String issueKey, String id, Set<CommentExpand> flags)
      • getCommentOptional(String issueKey, String id)
      • getCommentOptional(String issueKey, String id, Set<CommentExpand> flags)
      • addComment(String issueKey, Comment comment)
      • updateComment(String issueKey, Comment comment)
      • deleteComment(String issueKey, String id)
    • Votes
      • addVote(String issueKey)
      • getVotes(String issueKey)
    • Watchers
      • getWatchers(String issueKey)
      • addWatcher(String issueKey, String username)
      • deleteWatcher(String issueKey, String username)
    • Work Logs
      • addWorkLog(String issueKey, WorkLog workLog)
      • getWorkLogs(String issueKey)
      • getWorkLog(String issueKey, String id)
      • getWorkLogOptional(String issueKey, String id)
      • updateWorkLog(String issueKey, WorkLog workLog)
      • deleteWorkLog(String issueKey, String id)
    • Attachments
      • getAttachment(String id)
      • getAttachmentOptional(String id)
      • getAttachmentContent(String url)
      • addAttachment(String issueKey, File... files)
      • deleteAttachment(String id)
    • Remote Links
      • getRemoteLinks(String issueKey)
      • getRemoteLink(String issueKey, String id)
      • getRemoteLinkOptional(String issueKey, String id)
      • addRemoteLink(String issueKey, RemoteLink remoteLink)
      • updateRemoteLink(String issueKey, RemoteLink remoteLink)
      • deleteRemoteLink(String issueKey, String id)
    • Issue Links
      • getIssueLink(String id)
      • getIssueLinkOptional(String id)
      • addIssueLink(Link link)
      • deleteIssueLink(String id)
  • SearchApi - Everything for searches, including filters
    • Searches
      • searchIssues(String jql)
      • searchIssues(String jql, Integer startAt, Integer maxResults)
      • searchIssues(String jql, Integer startAt, Integer maxResults, Set<IssueExpand> expand)
      • searchIssues(String jql, Integer startAt, Integer maxResults, Set<IssueExpand> expand, Set<String> fields)
    • Filters
      • addFilter(Filter filter)
      • getFilter(String id)
      • getFilterOptional(String id)
      • getFavoriteFilters()
      • updateFilter(String id, Filter filter)
      • deleteFilter(String id)
  • ProjectApi - Everything for projects, including components, versions, statuses and roles
    • addProject(ProjectChange project)
    • getProjects()
    • getProjects(boolean includeArchived, String expand)
    • getProject(String projectKey)
    • getProjectOptional(String projectKey)
    • getProjectVersions(String projectKey)
    • getProjectComponents(String projectKey)
    • getProjectStatuses(String projectKey)
    • getProjectRoles(String projectKey)
    • updateProject(String projectKey, ProjectChange project)
    • deleteProject(String projectKey)
  • UserApi - Everything for users
    • getUsers(String search)
    • getUsers(String search, Integer startAt, Integer maxResults, Boolean includeInactive)
    • getAssignableUsers(String search, String key)
    • getAssignableUsers(String search, String key, Integer startAt, Integer maxResults, Boolean includeInactive)
    • getUser(String username)
    • getUserOptional(String username)
    • getCurrentUser()

Client instantiation

Instantiate the Jira client of your choice by giving your Jira instance URL. Depending on your needs, you may also want to add authentication with a personal access token (PAT) using withTokenAuthentication or with username and password using withUserAuthentication method. If you need to connect via a proxy, you can specify it with withProxy. Below an example for each HTTP client:

JiraClient<Issue> client = JiraClient.javaClient("https://jira.mycompany.com")
    .withUserAuthentication("myUsername","myPassword")
    .withProxy("http://proxy.mycompany.com:1234");
JiraClient<Issue> client = JiraClient.apacheClient("https://jira.mycompany.com")
    .withUserAuthentication("myUsername","myPassword")
    .withProxy("http://proxy.mycompany.com:1234");
JiraClient<Issue> client = JiraClient.okHttpClient("https://jira.mycompany.com")
    .withUserAuthentication("myUsername","myPassword")
    .withProxy("http://proxy.mycompany.com:1234");
JiraClient<Issue> client = JiraClient.vertxClient("https://jira.mycompany.com")
    .withUserAuthentication("myUsername","myPassword")
    .withProxy("http://proxy.mycompany.com:1234");

From this JiraClient you will then be able to get the desired APIs described in the feature chapter.

Iterable results

When requesting a list of elements, the client returns an object encapsulating this list, sometimes with more pieces of information depending on the Jira endpoint called. From this object, you can iterate directly on its child elements as in the example below:

Consumer<Filter> deleteFilter = filter -> client.getSearchClient().deleteFilter(filter.getId());
client.getSearchClient().getFavoriteFilters()
    .thenAccept(filters -> filters.forEach(deleteFilter));

Issue custom fields

If your project has custom fields for issues, you have two choices in order to get and set them.

Use attribute containing all custom fields

First possibility, simply use issue.getFields().getCustomFields().get("customfield_12345") to get the field and issue.getFields().getCustomFields().put("customfield_12345", value) to set a value for this field.

Reimplement fields and issue class

Second possibility, create a new class extending Fields to hide the custom fields identifiers and interact with Jira in a more understandable way:

@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class CompanyFields extends Fields {

    @JsonProperty("customfield_12345")
    private User businessEngineer;
    
    ...

}

A new Issue class will also be needed to override the fields attribute:

@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class CompanyIssue extends Issue {

    private CompanyFields fields;

}

Finally, specify it when instantiating the JiraClient, for example with Apache HTTP client:

JiraClient<CompanyIssue> client = new ApacheHttpJiraClient<>("https://jira.mycompany.com", CompanyIssue.class);

Please be aware that both solutions cannot live together as when you have attributes in the class for your fields, it will then not be in the customFields map (containing all the unmapped fields).

Contributing

If you have a feature request or found a bug, you can:

  • Write an issue
  • Create a pull request

Code style

The code style is based on the default one from IntelliJ, except for the following cases:

Imports

Imports are ordered as follows:

  • All static imports in a block
  • Java non-static imports in a block
  • All non-static imports in a block

A single blank line separates every block. Within each block the imported names appear in alphabetical sort order. Wildcard imports, static or otherwise, are not used.

Arrangements

The attributes of domain classes are ordered alphabetically.

License

This project is under Apache 2.0 License.