JIRA Rest JAVA Client API实现问题管理及自定义字段

JIRA是一个缺陷跟踪管理系统,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域,当我们需要把第三方业务系统集成进来时,可以调用他的API。

JIRA本身的API非常强大,但它是一个底层的API体系,并不是一个易用的接口,如果要开发和拓展,所以需要我们二次包装。

jira官方为解决这个问题,推出了方便强大的java client library(目前只有java客户端库,没有.Net类库)

jira的Rest API  最新文档官网.

JIRA 6.4.12 REST API documentation

https://docs.atlassian.com/jira/REST/latest/

JIRA REST API Tutorials:

https://developer.atlassian.com/jiradev/jira-apis/jira-rest-apis/jira-rest-api-tutorials

如果是编写java桌面或web应用,jira提供了更方便的方式(Client类库),JIRA REST Java Client is a Java library (usable from any JVM language) which allows to easily talk to any JIRA 4.2+ instance using new (and still evolving) REST API.

JIRA Java Client library

https://ecosystem.atlassian.net/wiki/display/JRJC/Home

如果使用Client类库,可以方便应用各种现成的jira实体类(如项目、问题、备注、自定义字段......),不需要再重复造轮子,大幅提升效率。

首先,必须要了解JIRA api的接口结构,其中<resource-name>可以理解成api的方法,比如project,就是项目信息,user就是用户信息,issue就是问题信息....

1

http://hostname/rest/<api-name>/<api-version>/<resource-name>

JIRA‘s REST API is provided by a plugin that is anchored under the URI path component /rest/. Hence, if your JIRA site is running at:

还先要搞清楚jira api的 认证体系,摘自官网:

the first step in using the JIRA REST API is to authenticate a user account with your JIRA site. For the purposes of this tutorial we will use HTTP BASIC Authentication, but any authentication that works against JIRA will work against the REST API. This includes:

  1. OAuth
  2. HTTP Cookies
  3. Trusted Applications
  4. os_username/os_password query parameters

为方便使用,我们采用Basic Auth

Basic Auth headers

If you need to you may construct and send basic auth headers yourself. To do this you need to perform the following steps:

  1. Build a string of the form username:password
  2. Base64 encode the string
  3. Supply an "Authorization" header with content "Basic " followed by the encoded string. For example, the string "fred:fred" encodes to "ZnJlZDpmcmVk" in base64, so you would make the request as follows.
一个curl的例子,注意红色字符串是对“username:password”的Base64编码curl -D- -X GET -H "Authorization: Basic ZnJlZDpmcmVk" -H "Content-Type: application/json" "http://kelpie9:8081/rest/api/2/issue/QA-31"

JAVA Client类库实现的API DEMO

package jiraTEST;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.apache.commons.codec.binary.Base32;
import org.joda.time.DateTime;

import com.atlassian.jira.rest.client.IssueRestClient;
import com.atlassian.jira.rest.client.JiraRestClient;
import com.atlassian.jira.rest.client.SearchRestClient;
import com.atlassian.jira.rest.client.domain.BasicIssue;
import com.atlassian.jira.rest.client.domain.BasicProject;
import com.atlassian.jira.rest.client.domain.BasicUser;
import com.atlassian.jira.rest.client.domain.Comment;
import com.atlassian.jira.rest.client.domain.Field;
import com.atlassian.jira.rest.client.domain.Issue;
import com.atlassian.jira.rest.client.domain.Project;
import com.atlassian.jira.rest.client.domain.SearchResult;
import com.atlassian.jira.rest.client.domain.Transition;
import com.atlassian.jira.rest.client.domain.input.ComplexIssueInputFieldValue;
import com.atlassian.jira.rest.client.domain.input.FieldInput;
import com.atlassian.jira.rest.client.domain.input.IssueInput;
import com.atlassian.jira.rest.client.domain.input.IssueInputBuilder;
import com.atlassian.jira.rest.client.internal.async.AsynchronousJiraRestClientFactory;
import com.atlassian.util.concurrent.Promise;
import com.google.common.collect.Lists;

public class CvteJiraDemo {

    public static String BaseURL = "http://jira-test:8080/";
    public static String User = "admin";
    public static String Password = "admin";
    private static URI jiraServerUri = URI
            .create("http://jira-test:8080/rest/api/2/");
    private static boolean quiet = false;
    private static final long BUG_TYPE_ID = 1L; // JIRA magic value
    private static final long TASK_TYPE_ID = 3L; // JIRA magic value
    private static final DateTime DUE_DATE = new DateTime();
    private static final String PRIORITY = "Trivial";
    private static final String DESCRIPTION = "description";

    public static void main(String[] args) throws InterruptedException,
            ExecutionException {

        final AsynchronousJiraRestClientFactory factory = new AsynchronousJiraRestClientFactory();
        URI jiraServerUri;
        try {
            jiraServerUri = new URI(BaseURL);
            final JiraRestClient restClient = (JiraRestClient) factory
                    .createWithBasicHttpAuthentication(jiraServerUri, User,
                            Password);
            getAllProjects(restClient);
            getProject(restClient, "DEMO");
            getIssue(restClient, "FEEDBACK-14");
            getIssueFields(restClient, "FEEDBACK-27");
            addIssue(restClient, "FEEDBACK", "AAAAB");
            addIssueComplex(restClient, "FEEDBACK",DUE_DATE.toString());

        } catch (URISyntaxException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {

        }
    }

    private static void println(Object o) {
        if (!quiet) {
            System.out.println(o);
        }
    }

    private static void parseArgs(String[] argsArray) throws URISyntaxException {
        final List<String> args = Lists.newArrayList(argsArray);
        if (args.contains("-q")) {
            quiet = true;
            args.remove(args.indexOf("-q"));
        }

        if (!args.isEmpty()) {
            jiraServerUri = new URI(args.get(0));
        }
    }

    private static Transition getTransitionByName(
            Iterable<Transition> transitions, String transitionName) {
        for (Transition transition : transitions) {
            if (transition.getName().equals(transitionName)) {
                return transition;
            }
        }
        return null;
    }

    // 得到所有项目信息
    private static void getAllProjects(final JiraRestClient restClient)
            throws InterruptedException, ExecutionException {
        try {

            Promise<Iterable<BasicProject>> list = restClient
                    .getProjectClient().getAllProjects();
            Iterable<BasicProject> a = list.get();
            Iterator<BasicProject> it = a.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }

        } finally {
        }
    }

    // 得到单一项目信息
    private static void getProject(final JiraRestClient restClient,
            String porjectKEY) throws InterruptedException, ExecutionException {
        try {

            Project project = restClient.getProjectClient()
                    .getProject(porjectKEY).get();
            System.out.println(project);

        } finally {
        }
    }

    // 得到单一问题信息
    private static void getIssue(final JiraRestClient restClient,
            String issueKEY) throws InterruptedException, ExecutionException {
        try {

            Promise<Issue> list = restClient.getIssueClient()
                    .getIssue(issueKEY);
            Issue issue = list.get();
            System.out.println(issue);

        } finally {
        }
    }

    // 创建问题
    public static BasicIssue createIssue(final JiraRestClient jiraRestClient,
            IssueInput newIssue) {
        BasicIssue basicIssue = jiraRestClient.getIssueClient()
                .createIssue(newIssue).claim();
        return basicIssue;
    }

    //添加备注到问题
    public static void addCommentToIssue(final JiraRestClient jiraRestClient,Issue issue, String comment) {
        IssueRestClient issueClient = jiraRestClient.getIssueClient();
        issueClient.addComment(issue.getCommentsUri(), Comment.valueOf(comment)).claim();
    }

    //删除问题,目前找不到对应API
    public static void deleteIssue(final JiraRestClient jiraRestClient, Issue issue) {
        IssueRestClient issueClient = jiraRestClient.getIssueClient();
        //issueClient.deleteIssue(issue.getKey(), false).claim();
    }

    //通过标题获取问题
    public static Iterable findIssuesByLabel(final JiraRestClient jiraRestClient, String label) {
        SearchRestClient searchClient = jiraRestClient.getSearchClient();
        String jql = "labels%3D"+label;
        com.atlassian.jira.rest.client.domain.SearchResult results = ((SearchRestClient) jiraRestClient).searchJql(jql).claim();
        return results.getIssues();
    }

    //通过KEY获取问题
    public static Issue findIssueByIssueKey(final JiraRestClient jiraRestClient, String issueKey) {
        SearchRestClient searchClient = jiraRestClient.getSearchClient();
        String jql = "issuekey = \"" + issueKey + "\"";
        SearchResult results = searchClient.searchJql(jql).claim();
        return (Issue) results.getIssues().iterator().next();
    }

    // 创建问题 :仅有简单问题名称
    private static void addIssue(final JiraRestClient restClient,
            String porjectKEY, String issueName) throws InterruptedException,
            ExecutionException {
        try {
            IssueInputBuilder builder = new IssueInputBuilder(porjectKEY,
                    TASK_TYPE_ID, issueName);
            builder.setDescription("issue description");
            final IssueInput input = builder.build();

            try {
                // create issue
                final IssueRestClient client = restClient.getIssueClient();
                final BasicIssue issue = client.createIssue(input).claim();
                final Issue actual = client.getIssue(issue.getKey()).claim();
                System.out.println(actual);
            } finally {
                if (restClient != null) {
                    // restClient.close();
                }
            }

        } finally {
        }
    }

    // 创建问题 :包含自定义字段
    private static void addIssueComplex(final JiraRestClient restClient,
            String porjectKEY, String issueName) throws InterruptedException,
            ExecutionException {
        try {
            IssueInputBuilder builder = new IssueInputBuilder(porjectKEY,
                    TASK_TYPE_ID, issueName);
            builder.setDescription("issue description");
            // builder.setFieldValue("priority", ComplexIssueInputFieldValue.with("name", PRIORITY));
            //单行文本
            builder.setFieldValue("customfield_10042", "单行文本测试");

            //单选字段
            builder.setFieldValue("customfield_10043", ComplexIssueInputFieldValue.with("value", "一般"));

            //数值自定义字段
            builder.setFieldValue("customfield_10044", 100.08);

            //用户选择自定义字段
            builder.setFieldValue("customfield_10045", ComplexIssueInputFieldValue.with("name", "admin"));
            //用户选择自定义字段(多选)
            Map<String, Object> user1 = new HashMap<String, Object>();
            user1.put("name", "admin");
            Map<String, Object> user2 = new HashMap<String, Object>();
            user2.put("name", "wangxn");
            ArrayList peoples = new ArrayList();
            peoples.add(user1);
            peoples.add(user2);
            builder.setFieldValue("customfield_10047", peoples); 

            //设定父问题
            Map<String, Object> parent = new HashMap<String, Object>();
            parent.put("key", "FEEDBACK-25");
            FieldInput parentField = new FieldInput("parent", new ComplexIssueInputFieldValue(parent));
            builder.setFieldInput(parentField);

            final IssueInput input = builder.build();
            try {
                final IssueRestClient client = restClient.getIssueClient();
                final BasicIssue issue = client.createIssue(input).claim();
                final Issue actual = client.getIssue(issue.getKey()).claim();
                System.out.println(actual);
            } finally {
                if (restClient != null) {
                    // restClient.close();
                }
            }

        } finally {
        }
    }

    //获取问题的所有字段
    private static void getIssueFields(final JiraRestClient restClient,
            String issueKEY) throws InterruptedException, ExecutionException {
        try {

            Promise<Issue> list = restClient.getIssueClient()
                    .getIssue(issueKEY);
            Issue issue = list.get();
            Iterable<Field> fields = issue.getFields();
            Iterator<Field> it = fields.iterator();
            while (it.hasNext()) {
                System.out.println(it.next());
            }

        } finally {
        }
    }

}
时间: 2024-08-02 18:40:35

JIRA Rest JAVA Client API实现问题管理及自定义字段的相关文章

JIRA REST java client API实际应用

前提 1.需要安装maven环境: 2.在本地创建maven项目并修改maven配置文件“pom.xml”,添加如下内容: <dependency> <groupId>com.atlassian.jira</groupId> <artifactId>jira-rest-java-client</artifactId> <version>0.5-m6</version> </dependency> <dep

Memcached Java Client API详解

针对Memcached官方网站提供的java_memcached-release_2.0.1版本进行阅读分析,Memcached Java客户端lib库主要提供的调用类是SockIOPool和MemCachedClient?,关键类及方法整理说明如下. SockIOPool 这个类用来创建管理客户端和服务器通讯连接池,客户端主要的工作包括数据通讯.服务器定位.hash码生成等都是由这个类完成的. public static SockIOPool getInstance() 获得连接池的单态方法.

JAVA HDFS API Client 连接HA

如果Hadoop开启HA,那么用Java Client连接Hive的时候,需要指定一些额外的参数 package cn.itacst.hadoop.hdfs; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URI; import org.apache.hadoop.conf.Configuration; import org.apac

Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新Client API的使用要点,高可用性测试,以及各种坑 (转载)

Kafka 0.9版本对java client的api做出了较大调整,本文主要总结了Kafka 0.9在集群搭建.高可用性.新API方面的相关过程和细节,以及本人在安装调试过程中踩出的各种坑. 关于Kafka的结构.功能.特点.适用场景等,网上到处都是,我就不再赘述了,直接进入正文 Kafka 0.9集群安装配置 操作系统:CentOS 6.5 1. 安装Java环境 Zookeeper和Kafka的运行都需要Java环境,所以先安装JRE,Kafka默认使用G1垃圾回收器,如果不更改垃圾回收器

Java 2D API - 1. 基本概念

Java 2D API扩展AWT包,对二维图形.文本及成像功能提供了支持,可用于开发复杂的界面.绘图软件和图像编辑器.Java 2D对象位于用户坐标空间(User coordinate space),当对象呈现在屏幕或打印机,用户空间坐标转换为设备空间坐标(device space coordinate).下面两个类对 Java 2D API十分重要: Graphics Graphics2D Java 2D API提供了如下功能: 为显示设备和打印机等提供了统一的渲染模型: 提供了大量的几何图元

浅析Java servlet Api

Java Servlet 开发工具(JSDK)提供了多个软件包,在编写 Servlet 时需要用到这些软件包.其中包括两个用于所有 Servlet 的基本软件包:javax.servlet 和 javax.servlet.http.可从sun公司的Web站点下载 Java Servlet 开发工具. 下面主要介绍javax.servlet.http提供的HTTP Servlet应用编程接口. HTTP Servlet 使用一个 HTML 表格来发送和接收数据.要创建一个 HTTP Servlet

HBase Client API使用入门(二)---查询及过滤器

相关知识 创建表插入数据删除等见:http://www.cnblogs.com/wishyouhappy/p/3735077.html HBase API简介见:http://www.cnblogs.com/wishyouhappy/p/3753347.html 按行.列簇等查询 package wish.hbase; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org

Java Servlet API中文说明文档

Java Servlet API中文说明文档译者前言:       近来在整理有关Servlet资料时发现,在网上竟然找不到一份中文的Java Servlet API的说明文档,而在有一本有关JSP的书后面附的Java Servlet API说明竟然不全,而这份文档的2.1a版在1998年的11月份就已定稿.所以我决定翻译一份中文的文档(其中一些与技术关系不大的部分已被略去),有兴趣的读者可以从http: //java.sun.com/products/servlet/2.1/servletsp

Kafka 0.9+Zookeeper3.4.6集群搭建、配置,新版Java Client的使用要点,高可用性测试,以及各种坑(二)

上一节中(点此传送),我们完成了Kafka集群的搭建,本节中我们将介绍0.9版本中的新API,以及Kafka集群高可用性的测试 1. 使用Kafka的Producer API来完成消息的推送 1) Kafka 0.9.0.1的java client依赖: <dependency>     <groupId>org.apache.kafka</groupId>     <artifactId>kafka-clients</artifactId>