Skip to content

A simple JIRA REST client for Java

License

GPL-2.0, LGPL-2.1 licenses found

Licenses found

GPL-2.0
LICENSE.md
LGPL-2.1
LICENSE-LESSER.md
Notifications You must be signed in to change notification settings

vgropp/jira-client

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jira-client

Build Status

jira-client is a simple and lightweight JIRA REST client library for Java.

The goal of the project is to provide simple and clean English idiomatic expressions for interacting with JIRA. In pursuit of this goal, jira-client lacks the usual verbose and cumbersome contortions often found in Java applications. And since the implementation isn't buried under 57 layers of complicated abstractions, jira-client is easy to extend and debug.

jira-client depends on Apache HttpComponents, json-lib, and joda-time.

Features

jira-client is still under heavy development. Here's what works:

  • Retrieve issues by key
  • Search for issues with JQL
  • Create issues
  • Update issues (both system fields and custom fields)
  • Finding allowed values for components and custom fields
  • Transition issues to new states
  • Add comments to issues
  • Add attachments to issues
  • Vote on issues
  • Add and remove issue watchers
  • Add and remove issue links
  • Create sub-tasks
  • Retrieval of Rapid Board backlog and sprints

Maven Dependency

Point your settings.xml at Maven Central and add jira-client to your project.

    <dependency>
      <groupId>net.rcarz</groupId>
      <artifactId>jira-client</artifactId>
      <version>0.5</version>
      <scope>compile</scope>
    </dependency>

Contributing

Patches are welcome and appreciated. Please try to follow existing styles, and strive for simplicity. Make sure to add yourself to AUTHORS!

Quick Start Example

import java.util.ArrayList;
import java.util.List;

import net.rcarz.jiraclient.BasicCredentials;
import net.rcarz.jiraclient.CustomFieldOption;
import net.rcarz.jiraclient.Field;
import net.rcarz.jiraclient.Issue;
import net.rcarz.jiraclient.JiraClient;
import net.rcarz.jiraclient.JiraException;

public class Example {

    public static void main(String[] args) {

        BasicCredentials creds = new BasicCredentials("batman", "pow! pow!");
        JiraClient jira = new JiraClient("https://jira.example.com/jira", creds);

        try {
            /* Retrieve issue TEST-123 from JIRA. We'll get an exception if this fails. */
            Issue issue = jira.getIssue("TEST-123");

            /* Print the issue key. */
            System.out.println(issue);

            /* You can also do it like this: */
            System.out.println(issue.getKey());

            /* Vote for the issue. */
            issue.vote();

            /* And also watch it. Add Robin too. */
            issue.addWatcher(jira.getSelf());
            issue.addWatcher("robin");

            /* Open the issue and assign it to batman. */
            issue.transition()
                .field(Field.ASSIGNEE, "batman")
                .execute("Open");
                
            /* Assign the issue */
            issue.update()
                .field(Field.ASSIGNEE, "batman")
                .execute();

            /* Add two comments, with one limited to the developer role. */
            issue.addComment("No problem. We'll get right on it!");
            issue.addComment("He tried to send a whole Internet!", "role", "Developers");

            /* Print the reporter's username and then the display name */
            System.out.println("Reporter: " + issue.getReporter());
            System.out.println("Reporter's Name: " + issue.getReporter().getDisplayName());

            /* Print existing labels (if any). */
            for (String l : issue.getLabels())
                System.out.println("Label: " + l);

            /* Change the summary and add two labels to the issue. The double-brace initialiser
               isn't required, but it helps with readability. */
            issue.update()
                .field(Field.SUMMARY, "tubes are clogged")
                .field(Field.LABELS, new ArrayList() {{
                    addAll(issue.getLabels());
                    add("foo");
                    add("bar");
                }})
                .field(Field.PRIORITY, Field.valueById("1")) /* you can also set the value by ID */
                .execute();

            /* You can also update values with field operations. */
            issue.update()
                .fieldAdd(Field.LABELS, "baz")
                .fieldRemove(Field.LABELS, "foo")
                .execute();

            /* Print the summary. We have to refresh first to pickup the new value. */
            issue.refresh();
            System.out.println("New Summary: " + issue.getSummary());

            /* Now let's start progress on this issue. */
            issue.transition().execute("Start Progress");

            /* Add the first comment and update it */
            Comment comment = issue.addComment("I am a comment!");
            comment.update("I am the first comment!");
            issue.getComments().get(0).update("this works too!");

            /* Pretend customfield_1234 is a text field. Get the raw field value... */
            Object cfvalue = issue.getField("customfield_1234");

            /* ... Convert it to a string and then print the value. */
            String cfstring = Field.getString(cfvalue);
            System.out.println(cfstring);

            /* And finally, change the value. */
            issue.update()
                .field("customfield_1234", "new value!")
                .execute();

            /* Pretend customfield_5678 is a multi-select box. Print out the selected values. */
            List<CustomFieldOption> cfselect = Field.getResourceArray(
                CustomFieldOption.class,
                issue.getField("customfield_5678"),
                jira.getRestClient()
            );
            for (CustomFieldOption cfo : cfselect)
                System.out.println("Custom Field Select: " + cfo.getValue());
               
            /* Print out allowed values for the custom multi-select box. */
            List<CustomFieldOption> allowedValues = jira.getCustomFieldAllowedValues("customfield_5678", "TEST", "Task");
            for (CustomFieldOption customFieldOption : allowedValues)
                System.out.println(customFieldOption.getValue());

            /* Set two new values for customfield_5678. */
            issue.update()
                .field("customfield_5678", new ArrayList() {{
                    add("foo");
                    add("bar");
                    add(Field.valueById("1234")); /* you can also update using the value ID */
                }})
                .execute();
                
            /* Add an attachment */
            File file = new File("C:\\Users\\John\\Desktop\\screenshot.jpg");
            issue.addAttachment(file);

            /* And finally let's resolve it as incomplete. */
            issue.transition()
                .field(Field.RESOLUTION, "Incomplete")
                .execute("Resolve Issue");

            /* Create a new issue. */
            Issue newIssue = jira.createIssue("TEST", "Bug")
                .field(Field.SUMMARY, "Bat signal is broken")
                .field(Field.DESCRIPTION, "Commissioner Gordon reports the Bat signal is broken.")
                .field(Field.REPORTER, "batman")
                .field(Field.ASSIGNEE, "robin")
                .execute();
            System.out.println(newIssue);

            /* Link to the old issue */
            newIssue.link("TEST-123", "Dependency");

            /* Create sub-task */
            Issue subtask = newIssue.createSubtask()
                .field(Field.SUMMARY, "replace lightbulb")
                .execute();

            /* Search for issues */
            Issue.SearchResult sr = jira.searchIssues("assignee=batman");
            System.out.println("Total: " + sr.total);
            for (Issue i : sr.issues)
                System.out.println("Result: " + i);

            /* Search with paging (optionally 10 issues at a time). There are optional
               arguments for including/expanding fields, and page size/start. */
            Issue.SearchResult sr = jira.searchIssues("project IN (GOTHAM) ORDER BY id");
            while (sr.iterator().hasNext())
                System.out.println("Result: " + sr.iterator().next());

        } catch (JiraException ex) {
            System.err.println(ex.getMessage());

            if (ex.getCause() != null)
                System.err.println(ex.getCause().getMessage());
        }
    }
}

GreenHopper Example

import java.util.List;

import net.rcarz.jiraclient.BasicCredentials;
import net.rcarz.jiraclient.Issue;
import net.rcarz.jiraclient.JiraClient;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.greenhopper.Epic;
import net.rcarz.jiraclient.greenhopper.GreenHopperClient;
import net.rcarz.jiraclient.greenhopper.Marker;
import net.rcarz.jiraclient.greenhopper.RapidView;
import net.rcarz.jiraclient.greenhopper.Sprint;
import net.rcarz.jiraclient.greenhopper.SprintIssue;
import net.rcarz.jiraclient.greenhopper.SprintReport;

public class Example {

    public static void main(String[] args) {

        BasicCredentials creds = new BasicCredentials("batman", "pow! pow!");
        JiraClient jira = new JiraClient("https://jira.example.com/jira", creds);
        GreenHopperClient gh = new GreenHopperClient(jira);

        try {
            /* Retrieve all Rapid Boards */
            List<RapidView> allRapidBoards = gh.getRapidViews();

            /* Retrieve a specific Rapid Board by ID */
            RapidView board = gh.getRapidView(123);

            /* Print the name of all current and past sprints */
            List<Sprint> sprints = board.getSprints();
            for (Sprint s : sprints)
                System.out.println(s);

            /* Get the sprint report, print the sprint start date
               and the number of completed issues */
            SprintReport sr = board.getSprintReport();
            System.out.println(sr.getSprint().getStartDate());
            System.out.println(sr.getCompletedIssues().size());

            /* Get backlog data */
            Backlog backlog = board.getBacklogData();

            /* Print epic names */
            for (Epic e : backlog.getEpics())
                System.out.println(e);

            /* Print all issues in the backlog */
            for (SprintIssue si : backlog.getIssues())
                System.out.println(si);

            /* Print the names of sprints that haven't started yet */
            for (Marker m : backlog.getMarkers())
                System.out.println(m);

            /* Get the first issue on the backlog and add a comment */
            SprintIssue firstIssue = backlog.getIssues().get(0);
            Issue jiraIssue = firstIssue.getJiraIssue();
            jiraIssue.addComment("a comment!");
        } catch (JiraException ex) {
            System.err.println(ex.getMessage());

            if (ex.getCause() != null)
                System.err.println(ex.getCause().getMessage());
        }
    }
}

Agile API

https://docs.atlassian.com/jira-software/REST/cloud/

Agile supported calls

Class Method REST Call
AgileClient List<Board> getBoards() GET /rest/agile/1.0/board
Board getBoard(long id) GET /rest/agile/1.0/board/{boardId}
Sprint getSprint(long id) GET /rest/agile/1.0/sprint/{sprintId}
Epic getEpic(long id) GET /rest/agile/1.0/epic/{epicId}
Issue getIssue(long id) GET /rest/agile/1.0/issue/{issueId}
Issue getIssue(String key) GET /rest/agile/1.0/issue/{issueKey}
Board static List<Board> getAll(RestClient restclient) GET /rest/agile/1.0/board
static Board get(RestClient restclient, long id) GET /rest/agile/1.0/board/{boardId}
List<Sprint> getSprints() GET /rest/agile/1.0/board/{boardId}/sprint
* List<Epic> getEpics() GET /rest/agile/1.0/board/{boardId}/epic
* List<Issue> getBacklog() GET /rest/agile/1.0/board/{boardId}/backlog
* List<Issue> getIssuesWithoutEpic() GET /rest/agile/1.0/board/{boardId}/epic/none/issue
Sprint static Sprint get(RestClient restclient, long sprintId) GET /rest/agile/1.0/sprint/{sprintId}
static List<Sprint> getAll(RestClient restclient, long boardId) GET /rest/agile/1.0/board/{boardId}/sprint
* List<Issue> getIssues() GET /rest/agile/1.0/sprint/{sprintId}/issue
Epic static Epic get(RestClient restclient, long id) GET /rest/agile/1.0/epic/{epicId}
* List<Issue> getIssues() GET /rest/agile/1.0/epic/{epicId}/issue
Issue static Issue get(RestClient restclient, long id) GET /rest/agile/1.0/issue/{issueId}
static Issue get(RestClient restclient, String key) GET /rest/agile/1.0/issue/{issueKey}

Agile Example

To see more examples, look at AgileClientDemoTest

import java.util.List;

import net.rcarz.jiraclient.BasicCredentials;
import net.rcarz.jiraclient.Issue;
import net.rcarz.jiraclient.JiraClient;
import net.rcarz.jiraclient.JiraException;
import net.rcarz.jiraclient.agile.Board;
import net.rcarz.jiraclient.agile.AgileClient;

public class Example {

    public static void main(String[] args) {

        BasicCredentials creds = new BasicCredentials("batman", "pow! pow!");
        JiraClient jira = new JiraClient("https://jira.example.com/jira", creds);
        AgileClient agileClient = new AgileClient(jira);

        try {
            /* Retrieve all Boards */
            List<Board> allBoards = agileClient.getBoards();
        } catch (JiraException ex) {
            System.err.println(ex.getMessage());

            if (ex.getCause() != null) {
                System.err.println(ex.getCause().getMessage());
            }
        }
    }
}

About

A simple JIRA REST client for Java

Resources

License

GPL-2.0, LGPL-2.1 licenses found

Licenses found

GPL-2.0
LICENSE.md
LGPL-2.1
LICENSE-LESSER.md

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 86.7%
  • Groovy 13.3%