jira插件开发学习

 

一、系统架构介绍

1.1   JIRA的技术架构

1.1.1 JIRA简介

JIRA 是澳大利亚Atlassian公司开发的一款优秀的问题跟踪及事务管理软件工具。可以对各种类型的问题进行跟踪管理,包括缺陷,需求、改进等。JIRA采用J2EE技术,因此可以跨平台部署。

JIRA作为一个专业的问题跟踪系统可以版主您把缺陷管理起来,让跟踪和管理在项目中发现的问题变得简单,而且充分利用JIRA的灵活配置和扩展性,可以将JIRA作为一个项目管理系统或者IT支持系统。

JIRA功能全面,界面友好,安装简单,配置灵活,权限管理以及可扩展性方面都十分出色,因此在全世界超过122个国家的14500个项目中使用,许多著名的开源项目也都采用了JIRA

1.1.2 JIRA架构

           JIRA  Java 语言编写,使用 Pico 容器,Apache OFBiz(阿帕奇开放的电

              子商务平台),以及 WebWork 1 technology stackJira 支持 SOPA,XML-RPC 

 REST表征状态转移,英文:Representational State Transfer,简称REST

Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。)。

JIRA  SVNCVSGitClearcase,Visual SourceSafeMercurial  Perforce  source control 程序集成。可以使用多种语言,包括英语、日语、德语、法语、西班牙语。

JIRA 拥有灵活的插件架构,可以调用 JIRA 开发者社区和第三方开发的插件,与 IDE 集成,比如 Eclipse IntelliJ IDEA using the Atlassian IDE Connector. JIRA API[10]允许开发者向 JIRA 中继承第三方开发的应用程序。

 

1.2   涉及到的主要技术

JIRA使用的技术主要有:J2eeSpring、工作流、freemarker等。

二、数据库模型

2.1 实体引擎模型

实体引擎是用于模型化和管理具体数据的一套工具和模式。实体是一块由一组字段和其他实体之间的关系定义的数据。这个定义来自关系数据库管理系统的标准实体 - 关系模型概念。实体引擎的目标是为了简化企业实体数据的广泛使用。这包括定义,维护,质量保证,以及相关的功能实体的发展。

2.2 数据库模型描述文件

数据库描述文件entitymodel.xml,您可以在 JIRA Web应用程序目录

WEB-INF/classes/entitydefs下找到他。他定义了JIRA数据库中所有的表、列和列的数据类型,以及部分表之间的关系。

2.3 部分数据库表关系介绍

§  问题域

§  简单字段(表:jiraissue存放问题的字段

SQLdesc jiraissue来查看表结构

字段
类型
是否为空
主键
默认值
扩展

ID

decimal(18,0)

NO

PRI

 

 

pkey

varchar(255)

YES 

MUL

NULL

 

PROJECT

decimal(18,0)

YES

MUL

NULL

 

REPORTER

varchar(255)

YES

 

NULL

 

ASSIGNEE

varchar(255)

YES

MUL

NULL

 

issuetype

varchar(255)

YES

 

NULL

 

SUMMARY

varchar(255)

YES

 

NULL

 

DESCRIPTION

longtext

YES

 

NULL

 

ENVIRONMENT

longtext

YES

 

NULL

 

PRIORITY

varchar(255)

YES

 

NULL

 

RESOLUTION

varchar(255)

YES

 

NULL

 

issuestatus

varchar(255)

YES

 

NULL

 

CREATED

datetime

YES

 

NULL

 

UPDATED

datetime

YES

 

NULL

 

DUEDATE

datetime

YES

 

NULL

 

VOTES

datetime

YES

 

NULL

 

TIMEORIGINALESTIMATE

decimal(18,0)

YES

 

NULL

 

TIMEESTIMATE

decimal(18,0)

YES

 

NULL

 

WORKFLOW_ID

decimal(18,0)

YES

 

NULL

 

SECURITY

decimal(18,0)

YES

 

NULL

 

FIXFOR

decimal(18,0)

YES

 

NULL

 

COMPONENT

decimal(18,0)

YES

 

NULL

 

 

通过select语句查询表如下:

                    select id, pkey, project, reporter, assignee, issuetype, summary from jiraissue where pkey='JRA-3166';

 

§  用户详细信息(表:cwd_user

§  组件和版本

每个问题都有多个版本或者组件,表 nodeassociation,是jiraissue 与版本/组件的关联表。

Nodeassociation结构如下:

字段
类型
是否为空
主键
默认值
扩展
SOURCE_NODE_ID
decimal(18,0)

NO

PRI

 

 

SOURCE_NODE_ENTITY
varchar(60)

NO

PRI

 

 

SINK_NODE_ID
decimal(18,0)

NO

PRI

 

 

SINK_NODE_ENTITY
varchar(60)

NO

PRI

 

 

ASSOCIATION_TYPE
varchar(60)

NO

PRI

 

 

SEQUENCE
decimal(18,0)
YES
 
NULL

 

                    获得修改后的版本的sql语句为:
                    select * from projectversion where id in (
select SINK_NODE_ID from nodeassociation where ASSOCIATION_TYPE='IssueFixVersion' and SOURCE_NODE_ID=(
select id from jiraissue where pkey='JRA-5351')
);

同样,查询影响的版本:

select * from projectversion where id in (
    select SINK_NODE_ID from nodeassociation where ASSOCIATION_TYPE='IssueVersion' and SOURCE_NODE_ID=(
        select id from jiraissue where pkey='JRA-5351')
    );

 

查询组件:

select * from component where id in (
    select SINK_NODE_ID from nodeassociation where ASSOCIATION_TYPE='IssueComponent' and SOURCE_NODE_ID=(
        select id from jiraissue where pkey='JRA-5351')
    );

 

§  问题链接

问题的链接存储在表:issuelink 中,其结构如下:

 

 

字段
类型
是否为空
主键
默认值
扩展
ID

decimal(18,0)

NO

PRI

 

 

LINKTYPE

decimal(18,0)

YES

MUL

NULL

 

SOURCE

decimal(18,0)

YES

MUL

NULL

 

DESTINATION

decimal(18,0)

YES

MUL

NULL

 

SEQUENCE

decimal(18,0)

YES

 

NULL

 

比如:查询两个问题的所有链接SQL

select * from issuelink where SOURCE=(select id from jiraissue where pkey='TP-1') and DESTINATION=(select id from jiraissue where pkey='TP-2');

查询链接的类型:

select j1.pkey, issuelinktype.INWARD, j2.pkey from jiraissue j1, issuelink, issuelinktype, jiraissue j2 where j1.id=issuelink.SOURCE and j2.id=issuelink.DESTINATION and issuelinktype.id=issuelink.linktype;

 

§  自定义字段

系统中用户自定义字段存储在customfield表中,实例存储在customfieldvalue表中。

Customfieldvalue表结构如下:

字段
类型
是否为空
主键
默认值
扩展
ID

decimal(18,0)

NO

PRI

 

 

ISSUE

decimal(18,0)

YES

MUL

NULL

 

CUSTOMFIELD

decimal(18,0)

YES

 

NULL

 

PARENTKEY
varchar(255)

YES

 

NULL

 

STRINGVALUE
varchar(255)

YES

 

NULL

 

NUMBERVALUE

decimal(18,0)

YES

 

NULL

 

TEXTVALUE
Longtext

YES

 

NULL

 

DATEVALUE
Datetime

YES

 

NULL

 

VALUETYPE
varchar(255)

YES

 

NULL

 

我们可以查询某个问题所有的用户自定义字段

           select * from customfieldvalue where issue=(select id from jiraissue where pkey='JRA-5448');

 

§  自定义字段配置操作

 

 

§  自定义字段配置默认值 (表:genericconfiguration

自定义字段的默认值是存储在genericconfiguration表中。由于此表必须存

储任何自定义字段类型的值(级联选择,多选择等),该值被编码为XML如:

2

§  自定义字段配置方案

JIRA允许每一个项目或者问题有不同的默认值,可以通过在页面上点击‘config’按钮来定义。

§  自定义字段配置域(表:fieldconfigscheme

§  历史更改记录

changegroup  changeitem 表中, JIRA存储了每个问题的历史更改记录。

changegroup 

ID 

issueid

AUTHOR

CREATED

changeitem 

ID   

groupid

FIELDTYPE

FIELD     

OLDVALUE

OLDSTRING

NEWVALUE

NEWSTRING

 

增加历史变更记录

当把数据导入JIRA时,通常需要导入历史变更记录。导入数据之前,请先在changegroup 表中插入一条有合法问题 id的记录(jiraissue 表)sql语句如下:

insert into changegroup values (20000,10000,'admin','2005-06-12')

 

然后在changeitem表中插入一条变更记录。Sql如下:

insert into changeitem values (11000, 20000, 'jira','status','1','Open','6','Closed');

 

§  工作日志

工作日志记录在worklog 表中。

每当worklog添加条目,jiraissuetimespenttimeestimate值分别递增和递减。

 

§  用户和组

用户存储在CWD_USER表中,结构如下:

COLUMN_NAME

DATA_TYPE

COMMENTS

ID

NUMBER(18,0)

 

DIRECTORY_ID

NUMBER(18,0)

Links to CWD_DIRECTORY

USER_NAME

VARCHAR(255)

 

LOWER_USER_NAME

VARCHAR(255)

used for case-insensitive search

ACTIVE

NUMBER(9,0)

 

CREATED_DATE

DATE

 

UPDATED_DATE

DATE

 

FIRST_NAME

VARCHAR(255)

Not used

LOWER_FIRST_NAME

VARCHAR(255)

Not used

LAST_NAME

VARCHAR(255)

Not used

LOWER_LAST_NAME

VARCHAR(255)

Not used

DISPLAY_NAME

VARCHAR(255)

 

LOWER_DISPLAY_NAME

VARCHAR(255)

 

EMAIL_ADDRESS

VARCHAR(255)

 

LOWER_EMAIL_ADDRESS

VARCHAR(255)

 

CREDENTIAL

VARCHAR(255)

 

我们可以通过一个用户名username来查询一个usersql如下:

select user_name, directory_id, display_name, email_address from cwd_user
where user_name = 'fred'
 

如果是有重名的可以用一下sql语句:

select user_name, directory_id, display_name, email_address, dir.directory_position as position from cwd_user usr join cwd_directory dir on dir.id = usr.directory_id where user_name = 'fred' order by dir.directory_position

 

CWD_USER_ATTRIBUTES存储针对于用户的任意的属性。

组存储在CWD_GROUP表中,结构如下:

COLUMN_NAME

DATA_TYPE

COMMENTS

ID

NUMBER(18,0)

 

GROUP_NAME

VARCHAR(255)

 

LOWER_GROUP_NAME

VARCHAR(255)

used for case-insensitive search

ACTIVE

NUMBER(9,0)

 

LOCAL

NUMBER(9,0)

 

CREATED_DATE

DATE

 

UPDATED_DATE

DATE

 

DESCRIPTION

VARCHAR(255)

 

LOWER_DESCRIPTION

VARCHAR(255)

 

GROUP_TYPE

VARCHAR(60)

 

DIRECTORY_ID

NUMBER(18,0)

Links to CWD_DIRECTORY

CWD_GROUP_ATTRIBUTES存储组任意的属性。

JIRA也可以有多个用户目录,这些用户目录定义在CWD_DIRECTORY表中。

§  问题状态和工作流

JIRA的问题包括:状态(如:开启,关闭,正在处理等)和工作流。


§  问题状态

JIRA的问题存储在jiraissue 表中。

 

§  问题工作流步骤

在早些版本JIRA只有问题的状态,到2.0版本时,加入了工作流,所以状态之间的转换就可以定制的了。

通过jiraissue 表中的pKey字段,在OS_WFENTRY表中查到一个workflow_id

语句如下:

select * from OS_WFENTRY where ID=(select workflow_id from jiraissue where pkey='TP-1')

 

再通过workflow_id OS_CURRENTSTEP表中查到这个workflow最新状态下的详细信息。语句如下:

select * from OS_CURRENTSTEP where ENTRY_ID=(select workflow_id from jiraissue where pkey='TP-1');

 

§  状态和步骤怎样关联的

一个问题的状态和工作流步骤是保持同步的。它是通过一个方法(UpdateIssueStatusFunction)来保持同步。

 

 

 

三、插件开发

3.1插件概览

3.1.1 JIRA支持的插件模型类型

Custom Field Plugin Module

Gadget Plugin Module

Issue Link Renderer Plugin Module

Issue Operations Plugin Module

Issue Tab Panel Plugin Module

JQL Function Plugin Module

Keyboard Shortcut Plugin Module

Module Type Plugin Module

Portlet Plugin Module - deprecated

Project Tab Panel Plugin Module

Report Plugin Module

REST Plugin Module Type

RPC Endpoint Plugin Module

Search Request View Plugin Module

Servlet Context Listener Plugin Module

Servlet Context Parameter Plugin Module

Servlet Filter Plugin Module

Servlet Plugin Module

User Format Plugin Module

Version Tab Panel Plugin Module

Web Item Plugin Module

Web Panel Plugin Module

Web Resource Plugin Module

Web Section Plugin Module

Webwork plugin module

Workflow Plugin Modules

常用类型介绍:

1.    Custom Field Plugin Module

自定义字段插件模块允许你添加新的自定义字段类型和搜索的JIRA

1自定义字段类型 - 这些定义的自定义字段类型

2自定义字段seachers - 这些定义可以搜索自定义字段类型的方法.

自定义字段类型配置

自定义字段类型的插件模块的根元素是 customfield型。它允许用于配置以下属性和子元素:

Name

Required

Description

Default

class

实现了这个插件模块,您需要提供的类,取决于模块类型 。自定义字段类型模块的Java 。类必须实现com.atlassian.jira.issue.customfields.CustomFieldType

 

key

插件模块的标识符 KEY必须在它被定义的插件是唯一 的,有时在其他情况下,您可能需要唯一地标识一个模块。

N/A

i18n-name-key

 

可读的插件模块名称的本地化的KEY

 

name

 

插件模块的human-readable可读的名称。

即自定义字段类型模块的可读名称。

The plugin key.

 

Elements

Name

Required

Description

description

 

一个human-readable可读的描述,这个自定义字段类型的插件模块。可以被指定为关键属性使用i18n的系统的一个关键的价值为纯文本或与该元素的值

resource type="velocity"

 

Velocity模板,实现了自定义字段。

范例

下面是自定义字段选择用户(system-customfieldtypes-plugin.xml

 



   

      Choose a user from the user base via a popup picker window.

   

 

   

   

   

   

   

   

 

 

2.       Issue Tab Panel Plugin Module

发行标签面板插件模块允许你添加新的选项卡面板,查看发行屏幕。


一个插件可以添加一个新的标签,显示单一的问题(最有可能被拉从外部源)的信息 。这是Subversion  Perforce 的集成是如何工作的。

下面是一个例子描述



    

        Show Subversion commits related to an issue in an issue tab panel.

        

    

       class="..." 属性在指定的模块类必须实现IssueTabPanel的接口

插件可以指定他们的标签可以加载在一个AJAX请求,这是在JIRA 5.0和更高版本支持。下面就是一个例子的问题选项卡上,使AJAX加载XML片段。

 

    class="com.example.AjaxCapableTabPanel">

    

    true

 

 

3.       Servlet Filter Plugin Module

本模块的目的类型

Servlet过滤器插件模块允许你为你的插件的一部分部署的Java Servlet过滤器,指定的位置和你的过滤器的顺序。这允许你构建的过滤器,可以解决分析和监测,以及内容的生成等任务。

配置

Servlet过滤器插件模块的根元素servlet过滤器。它允许用于配置以下属性和子元素:

属性

Name

Required

Description

Default

class

 

Servlet过滤器的Java类必须实现 javax.servlet.Filter

 

state

 

指示是否应该被默认禁用的插件模块 (value='disabled') ,默认启用 (value='enabled').

enabled

i18n-name-key

 

插件模块名称的本地化的KEY

 

key

插件模块的标识符 必须在它被定义的插件是唯一 的,有时在其他情况下,您可能需要唯一地标识一个模块。

N/A

location

 

§  在应用程序的过滤器链的过滤器的位置。如果两个插件提供过滤器在相同的位置,

§  after-encoding 

§  before-login 

§  before-decoration 

§  before-dispatch 

before-dispatch

name

 

插件模块的名称。即过滤器的可读名称。

The plugin key

system

 

仅适用于非OSGi的插件

false

weight

 

 

100

元素

 

Name

Required

Description

Default

description

 

即过滤器的描述

 

init-param

 

指定使用的过滤器,初始化参数参数的名称参数值的子元素,就像web.xml 。可重复该元素及其子元素。

N/A

resource

 

这个插件模块的资源 。这个元素可能被重复。一个资源是一个非Java文件,可能需要一个插件

N/A

url-pattern

URL模式相匹配。这个元素可能被重复。

Atlassian插件类型的URL模式的格式是用于将它们映射到的URL。整体而言,模式的规则是在Servlet 2.3 API定义的一致。支持以下通配符:

§  *匹配零个或多个字符,包括目录斜线

§  ?匹配零个或一个字符

Examples

§  /mydir/* matches /mydir/myfile.xml

§  /*/admin/*.??ml matches /mydir/otherdir/admin/myfile.html

N/A

dispatcher

 

过滤器被触发时确定。您可以包括多个调度元素
,如果该元素是存在的,其内容必须执行下列操作之一,相应的过滤器在Java Servlet 2.4规范中定义的调度选项:

§  REQUEST: 过滤器适用于直接来自客户端的请求

§  INCLUDE: 过滤器适用于服务器端,包括通过做RequestDispatcher.include ()

§  FORWARD: 过滤器适用于通过转发请求RequestDispatcher.forward

§  ERROR: 过滤器适用于处理的请求是由一个错误页

只有从客户端的请求过滤器将被触发

 

Example

atlassian-plugin.xml文件

 



    

        A basic Servlet filter module test - says "Hello World!

        

        1.0

    

 

    

        Says Hello World, Australia or your name.

        /helloworld

        

            defaultName

            Australia

        

        REQUEST

        FORWARD

    

 

 

 

 

4.       Servlet Plugin Module

Servlet的插件模块使您部署的Java servlet为你的插件的一部分。

配置

Servlet的插件模块的元素是 servlet。它允许用于配置以下属性和子元素:

属性

Name

Required

Description

Default

class

servletJava 。必须是子类javax.servlet.http.HttpServlet

 

state

 

指示是否应该被默认禁用的插件模块,默认启用

enabled

i18n-name-key

 

本地化

 

key

插件模块的标识符

N/A

name

 

可读的servlet名称          

The plugin key.

system

 

指示是否这个插件模块是一个系统插件模块

false

Elements

Name

Required

Description

Default

description

 

插件模块的描述。

 

init-param

 

servlet的初始化参数,使用参数名称参数值的子元素,就像在web.xml指定。可重复该元素及其子元素。

N/A

resource

 

这个插件模块的资源 。这个元素可能被重复。一个资源是一个非Java文件,可能需要一个插件

N/A

url-pattern

URL模式相匹配。这个元素可能被重复。

Atlassian插件类型的URL模式的格式是用于将它们映射到的URL。整体而言,模式的规则是在Servlet 2.3 API定义的一致。支持以下通配符:

§  *匹配零个或多个字符,包括目录斜线

§  ?匹配零个或一个字符

Examples

§  /mydir/* matches /mydir/myfile.xml

§  /*/admin/*.??ml matches /mydir/otherdir/admin/myfile.html

N/A

Example

下面是一个例子atlassian - plugin.xml文件,其中包含一个单独的servlet

 



    

        A basic Servlet module test - says "Hello World!

        

        1.0

    

 

    

        Says Hello World, Australia or your name.

        /helloworld

        

            defaultName

            Australia

        

    

 

 

5.     

 

 

3.1.2内置的JIRA系统插件介绍

                   运行插件后可以看到所有的系统插件

3.2使用Plugin SDK开发插件

3.2.1插件开发环境准备

         操作系统要求:

                   JIRA的运行需要Java环境,Java是一个跨平台的编程语言,因此所有支持Java的操作系统上都可以运行JIRA,当然也需要考虑操作系统上是否支持您选择的应用服务器软件。目前SunJDKWindows(32位和64)SolarisAPARC 32位和64位),Linux平台(32位和64)

JIRA支持的应用服务:

TomcatJBossWeblogicResin

IRA支持的数据库:

OracleDB2MySQLSQL Server Sybase等。

浏览器要求:

JIRA支持各种主流的web浏览器,如:IE6以上、MozillaFirefoxOperaSafari等。

           3.2.1.1 安装JAVA

3.2.1.1.1下载并安装JDK

                  最好选择JDK1.6版本安装。

3.2.1.1. 2设置你的JAVA_HOME环境变量

         操作:鼠标右击我的电脑—>属性,选择高级选项卡,再选择环境变量跳出如图1.1.2.1对话框:

1.1.2.1

 

点击新建按钮,跳出如图1.1.2.2对话框,填写变量名为:JAVA_HOME,变量值为:jdk安装的路径。填写完成后点击确定按钮,然后测试安装信息填写的正确性。

1.1.2.2

测试:在运行中输入cmd命令,打开命令行窗口,运行java –version命令,如果命令行窗口出现安如图1.1.2.3jdk的版本信息,则说明安装jdk成功。

1.1.2.3

3.2.1.1.3阅读如何指定的Java版本

学习如何使用Java版本特有的语言功能

3.2.1.2下载Atlassian插件SDK

         说明:Atlassian插件SDK包括Maven和一个正确配置的Maven settings.xml文件,以及一些shell脚本来加快和简化插件开发。

Atlassian插件SDK下载地址:

https://developer.atlassian.com/display/DOCS/Installing+the+Atlassian+Plugin+SDK

根据您机器的操作系统下载适合的sdk

3.2.1.3 安装Atlassian插件SDK

3.2.1.3.1 解压下载好的Atlassian插件SDK zip

3.2.1.3.2修改环境变量

Atlassian插件SDK bin 目录添加到PATH环境变量

操作:鼠标右击我的电脑—>属性,选择高级选项卡,再选择环境变量跳出如图1.3.2.1对话框:

1.3.2.1

 

把解压的sdk包的路径(到bin目录,如:D:\Program Files\atlassian-plugin-sdk-3.7.2\bin)添加到PATH环境变量中。如果没有PATH环境变量,可以新建,方式参见1.1.2设置的JAVA_HOME设置的一样。

配置ATLAS_HOME

变量值:指定到SDK所在的目录。

3.2.1. 4 配置你的IDE

我们推荐您使用EclipseMyEclipseIntelliJ IDEA NetBeansIDE。因为所有这些支持Maven 2

3.2.1. 4.1安装你选择的IDE

         MyEclipse为例,版本6.5

3.2.1. 4.2配置IDE使用Atlassian插件SDK

         MyEclipse为例,版本6.5

3.2.1. 5.1 MyEclipse中设置 Atlassian插件

         a. 打开一个windows运行窗口

         b. 更改您的Eclipse workspace目录,新建一个workspace目录,如:E:\workspace_jira

         c. 运行下面的命令:

         atlas-mvn eclipse:add-maven-repo -Declipse.workspace=

         红色部分需要修改,需要指定到myEclipse的工作空间

如:atlas-mvn eclipse:add-maven-repo -Declipse.workspace= E:\workspace_jira

运行中如果出现如下错误

需要把atlas-mvn替换成%ATLAS_HOME%\apache-maven\bin\mvn然后再运行。

 

3.2.2创建插件框架

                   进入myEclipse工作空间,如下:

                  

                   执行:atlas-create-jira-plugin

      

1jira5

2jira4

选择jira5,输入1,回车

artifactId:工程名称

version:    当前版本信息

package:  包路径

然后到myEclipseworkspace目录中找到生成的jira工程,找到pom.xml文件,修改

 


    Example Company
    

This plugin implements a simple issue event listener for JIRA using atlassian-event.
 

 

是一些描述信息,不修改也是可以的。

还有一些版本信息,

 


        
        5.0-beta1
        3.7.2
    
 

 

目前生成的是5.0-beta1,当然如果有其他版本,则需要修改为其他版本,如5.0-sc2,4.0版本等。

执行:cmd命令:

进入到工程的所在目录,执行:atlas-mvn eclipse:eclipse,如下:

此命令是创建myEclipse的描述文件,为jira的支持,如.classpath .project

 

启动myEclipse,导入生成的工程:new-listener-plugin

就可以在myEclipse中看到生成的工程了,目录结构如下:

3.2.3启动应用

运行atlas-run ,启动应用

首次启动时jira会加载很多jia包,包括编译和下载运行服务器,会较慢!

启动成功后:打开浏览器,需要用ie7以上的版本,或google浏览器,建议使用google浏览器。

输入访问路径:http://localhost:2990/jira/

admin/admin登陆,登陆成功后就可以看到我们开发的插件了。

3.2.4设置IDE(mylipse为例)

3.2.5插件代码编写

                   本插件是一个监听插件,要实现InitializingBean, DisposableBean两个接口

public class IssueCreatedResolvedListener implements InitializingBean, DisposableBean,然后写一个监听方法,onIssueEvent

 

@EventListener
    public void onIssueEvent(IssueEvent issueEvent) {
        Long eventTypeId = issueEvent.getEventTypeId();
        Issue issue = issueEvent.getIssue();
        System.out.println("===================fff======================");
        // if it's an event we're interested in, log it
        if (eventTypeId.equals(EventType.ISSUE_CREATED_ID)) {
            log.info("Issue {} has been created at {}.", issue.getKey(), issue.getCreated());
        } else if (eventTypeId.equals(EventType.ISSUE_RESOLVED_ID)) {
            log.info("Issue {} has been resolved at {}.", issue.getKey(), issue.getResolutionDate());
        }
}
 

 

,修改atlassian-plugin.xml中的配置,

 


     
         Class that processes the incoming JIRA issue events.
     
 

 

添加log4j支持,在pom.xml文件中添加

 


    ${jira.version}
${jira.version}
src/log4j.properties

 

 

添加log4j.jar

3.2.6插件的编译及打包

                   运行atlas-run ,会在target目录下生产项目的发布包。

四、插件开发例子介绍

五、JIRA远程API介绍

5.1  REST API

概述

无论你想建立的,我们的目的是提供平台。新的Web或桌面应用,移动应用程序,集成,基于浏览器的扩展或附加,Atlassian插件,不管你可以梦想。AtlassianREST API提供一个标准的接口与JIRA和其他应用程序进行交互。

REST API的访问资源(数据实体)可以通过URI路径。要使用一个REST API,应用程序将一个HTTP请求,并解析响应。你的方法将标准的HTTP GETPUTPOSTDELETE方法。REST API的工作在HTTPS)很容易地使用任何编程语言或框架。

JIRAREST API的输入和输出格式是JSON

JIRA使用Atlassian REST插件实施的JIRAAPI REST插件是捆绑在一起的JIRA。您可以添加您自己的REST API创建一个JIRA插件,包括REST插件模块的JIRA

 

§  输入文件是由' --data @filename ​​语法表示。数据显示分开,并使用JSON格式。

§  确保请求的内容类型设置为 application/json ,如在本例中所示。

§  到您的JIRA服务器的JSON。在这个例子中,服务器是:http://localhost:8090/rest/api/2/issue/

§  例如使用基本身份验证,用户名fred和密码fred

1:使用ID

第一个例子指定项目ID和问题类型ID创建一个问题。

 

Request
curl -D- -u fred:fred -X POST --data {see below} -H "Content-Type: application/json" http://localhost:8090/rest/api/2/issue/

Data
Here's the JSON:
{

    "fields": {

       "project":

       {

          "id": "10110"

       },

       "summary": "No REST for the Wicked.",

       "description": "Creating of an issue using ids for projects and issue types using the REST API",

       "issuetype": {

          "id": "1"

       }

   }

}
 

 

Response响应提供的问题编号,问题的关键,问题的URL(它可以被用来获得额外的数据,把更新等)。

 

{

   "id":"39001",

   "key":"TEST-102",

    "self":"http://localhost:8090/rest/api/2/issue/TEST-102"

}
 

 

 

 

5.2  JIRA SOAP Client

JIRA3.0及以更高的版本都附随RPC插件,它可以通过XML - RPCSOAP.This文件的远程访问包含对RPC插件的说明
通过一个Java SOAP客户端(需要的JIRA3.1或以上)如何执行各种操作(如创建问题)。

要远程调用的JIRA操作,你应该确保你的目标上JIRA安装启用的RPC插件。如果您
只是想创建一个客户端,那么你可以跳过这一步。首先,你需要检查一下,如果接受远程API调用http://jira.atlassian.com/一般配置全局设置已启用(在左侧菜单)

然后,您需要启用的JIRARPC插件

 

如果插件没有出现如上,那么您的RPC JAR没有被正确安装。从下载的jar
 
并将其复制到您的JIRA的安装文件夹。执行重新启动,和你的资料库atlassian-jira/WEB-INF/lib插件应该出现

您的服务器现在应该准备接受远程过程调用。

WSDL的描述符

无论语言或SOAP API的使用,您将需要为您的JIRA安装的WSDL描述。这是发现在http:// your_installation / rpc/soap/jirasoapservice-v2WSDL。例如,http://jira.atlassian.comWSDL文件是:

http://jira.atlassian.com/rpc/soap/jirasoapservice-v2?wsdl

示例Java SOAP客户端

 

private static RemoteIssue testCreateIssue(JiraSoapService jiraSoapService, String token)

            throws java.rmi.RemoteException

    {

        Timing timing = Timing.startTiming("CreateIssue");

        try

        {

            // Create the issue

            RemoteIssue issue = new RemoteIssue();

            issue.setProject(PROJECT_KEY);

            issue.setType(ISSUE_TYPE_ID);

 

            issue.setSummary(SUMMARY_NAME);

            issue.setPriority(PRIORITY_ID);

            issue.setDuedate(Calendar.getInstance());

            issue.setAssignee("");

 

            // Add remote compoments

            RemoteComponent component = new RemoteComponent();

            component.setId(COMPONENT_ID);

            issue.setComponents(new RemoteComponent[] { component });

 

            // Add remote versions

            RemoteVersion version = new RemoteVersion();

            version.setId(VERSION_ID);

            RemoteVersion[] remoteVersions = new RemoteVersion[] { version };

            issue.setFixVersions(remoteVersions);

 

            // Add custom fields

            RemoteCustomFieldValue customFieldValue = new RemoteCustomFieldValue(CUSTOM_FIELD_KEY_1, "", new String[] { CUSTOM_FIELD_VALUE_1 });

            RemoteCustomFieldValue customFieldValue2 = new RemoteCustomFieldValue(CUSTOM_FIELD_KEY_2, "", new String[] { CUSTOM_FIELD_VALUE_2 });

            RemoteCustomFieldValue[] customFieldValues = new RemoteCustomFieldValue[] { customFieldValue, customFieldValue2 };

            issue.setCustomFieldValues(customFieldValues);

 

            // Run the create issue code

            RemoteIssue returnedIssue = jiraSoapService.createIssue(token, issue);

            final String issueKey = returnedIssue.getKey();

 

            System.out.println("\tSuccessfully created issue " + issueKey);

            printIssueDetails(returnedIssue);

            return returnedIssue;

        }

        finally

        {

            timing.printTiming();

        }
 

 

Python的(SOAPpy的)客户端

 

#!/usr/bin/python

 

# Sample Python client accessing JIRA via SOAP. By default, accesses

# http://jira.atlassian.com with a public account. Methods requiring

# more than basic user-level access are commented out. Change the URL

# and project/issue details for local testing.

#

# Note: This Python client only works with JIRA 3.3.1 and above (see

# http://jira.atlassian.com/browse/JRA-7321)

#

# Refer to the SOAP Javadoc to see what calls are available:

# http://docs.atlassian.com/software/jira/docs/api/rpc-jira-plugin/latest/com/atlassian/jira/rpc/soap/JiraSoapService.html

 

import SOAPpy

import SOAPpy.Types

import getpass,

import datetime

import time

 

soap = SOAPpy.WSDL.Proxy('http://jira.atlassian.com/rpc/soap/jirasoapservice-v2?wsdl')

#soap = SOAPpy.WSDL.Proxy('http://localhost:8090/jira/rpc/soap/jirasoapservice-v2?wsdl')

 

#jirauser = raw_input("Username for jira [fred]: ")

#if jirauser == "":

#    jirauser = "fred"

#

#passwd = getpass.getpass("Password for %s: " % jirauser)

#passwd="fredspassword"

 

jirauser='soaptester'

passwd='soaptester'

 

# This prints available methods, but the WSDL doesn't include argument

# names so its fairly useless. Refer to the Javadoc URL above instead

#print 'Available methods: ', soap.methods.keys()

 

def listSOAPmethods():

    for key in soap.methods.keys():

        print key, ': '

        for param in soap.methods[key].inparams:

        print '\t', param.name.ljust(10), param.type

        for param in soap.methods[key].outparams:

        print '\tOut: ', param.name.ljust(10), param.type

 

 

auth = soap.login(jirauser, passwd)

 

issue = soap.getIssue(auth, 'TST-3410')

print "Retrieved issue:", issue

print

 

baseurl = soap.getServerInfo(auth)['baseUrl']

newissue = soap.createIssue(auth, {'project': 'TST', 'type': '1', 'summary': 'Issue created with Python!'})

print "Created %s/browse/%s" % (baseurl, newissue['key'])

 

print "Adding comment.."

soap.addComment(auth, newissue['key'], {'body': 'Comment added with SOAP'})

 

print 'Updating issue..'

soap.updateIssue(auth, newissue['key'], [

        {"id": "summary", "values": ['[Updated] Issue created with Python'] },

 

        # Change issue type to 'New feature'

        {"id":"issuetype", "values":'2'},

 

        # Setting a custom field. The id (10010) is discoverable from

        # the database or URLs in the admin section

 

        {"id": "customfield_10010", "values": ["Random text set in updateIssue method"] },

 

        {"id":"fixVersions", "values":['10331']},

        # Demonstrate setting a cascading selectlist. See  

                # http://confluence.atlassian.com/display/JIRA/Frequently+Asked+RPC+Questions+and+Known+Issues#FrequentlyAskedRPCQuestionsandKnownIssues-Settingthevalueofcascadingselectcustomfield

        {"id": "customfield_10061", "values": ["10098"]},

        {"id": "customfield_10061:1", "values": ["10105"]},

        {"id": "duedate", "values": datetime.date.today().strftime("%d-%b-%y")}

 

        ])

 

print 'Resolving issue..'

# Note: all fields prompted for in the transition (eg. assignee) need to

# be set, or they will become blank.

soap.progressWorkflowAction(auth, newissue['key'], '2', [

        {"id": "assignee", "values": "jefft" },

        {"id":"fixVersions", "values":['10331']},

        {"id": "resolution", "values": "2" }

        ])

 

 

# Re. 'assignee' above, see http://jira.atlassian.com/browse/JRA-9018

 

# This works if you have the right permissions

#user = soap.createUser(auth, "testuser2", "testuser2", "SOAP-created user", "newuser@localhost")

#print "Created user ", user

 

#group = soap.getGroup(auth, "jira-developers")

# Adding a user to a group. Naming the parameters may be required (see

# http://jira.atlassian.com/browse/JRA-7971). You may experience other

# problems (see http://jira.atlassian.com/browse/JRA-7920).

#soap.addUserToGroup(token=auth, group=group, user=user)

 

# Adding a version to a project.

dateObj = SOAPpy.Types.dateTimeType((int(2011), int(1), int(10), int(time.timezone/3600), 0, 0))

soap.addVersion(auth, "TST", remoteVersion = {'name': 'Version 1', 'releaseDate': dateObj})

 

print "Done!"

 

# vim set textwidth=1000:
 

 

5.3  XML-RPC

JIRA3.0及以上版本附随JIRAXML - RPC插件,它可以通过XML- RPCSOAP的远程访问。Utilising此功能
使用XML - RPC无法与一些从包中的帮助下要容易得多。在本教程中,我们写一个基本的XML- RPC客户端的Apache XML - RPC
(使用)记录,检索项目,然后再次登录。还展示了一个Python客户端。的Apache XML- RPC

启用RPC插件同上:如下图

然后,您需要启用JIRARPC插件如下

现在,您的服务器已准备好接受远程过程调用,我们开始创建一个JavaXML - RPC客户端。

5.4  JSON-RPC

5.4.1  JIRA的远程API概述

这里是一个快速指导,JIRA的远程API的主要。

JIRA的远程API

状态

REST

推荐和支持。 REST建议和支持,在JIRA 5.0和更高版本的远程API。这是Atlassian将其注意力集中从这时开始,新增功能和修正错误。

SOAP

支持,但没有发展前途。 Atlassian将继续支持SOAP API,直到REST API提供了一个更换所有现有的SOAP功能 。但是,我们不会增加新的功能到现有的SOAP接口。

XML - RPC

支持,但没有发展前途。 JIRA仍然支持XML - RPC客户,但我们建议无论是SOAP,它提供了更多的功能,或REST,这是我们今后的发展将重点。

JSON - RPC

过渡。 Atlassian JSON - RPC功能的JIRA,以帮助您从SOAP APIREST API的方式,一种机制,使用更多的JSONJavaScript。我们建议您尽快移动到休息。

5.4.2 为什么JSON - RPC

JIRA的远程API的未来在于与REST。然而,直到这些API的完全建成,到现在为止唯一的选择是使用的SOAP API的。

SOAP消息是不友好的许多开发商,尤其是那些想在浏览器的AJAX环境的JIRA调用。

出于这个原因,我们添加了JSON - RPC功能,使一个从目前的SOAP API的一个更友好的机制,JSON / JavaScript的过渡

代码使用Java服务器代码,使在JIRA现有的SOAP接口。之间的方法和参 ​​数在JIRA的一个一对一映射SOAP API和等效的JSON - RPC方法和参 ​​数。

的主要区别是JSON - RPC的有线格式

5.4.3 API是如何实现的

JSON - RPC API提供的JIRA 4.4和更高版本捆绑在一起的一个开源插件

该插件使用的代码,提供SOAP方法,并将其转换为JSON - RPC方法。它使用JSON库杰克逊提供一个Java方法和JSON - RPC调用该方法之间的映射

最初的代码写成一个汇流插件,然后移植到一个JIRA插件。该机制的工作原理非常类似的方式在这两个产品。

SOAP调用是作为以下路径POST

http://host:port/jira/rpc/soap/jirasoapservice-v2

发表这条道路上的JSON - RPC调用:

http://host:port/jira/rpc/json-rpc/jirasoapservice-v2

交付MIME类型的应用程序/ JSON 响应 。应您的要求太多,但不是由插件执行。

如上所述,有一个一个SOAP方法调用和JSON - RPC方法调用之间的映射 。例如,为JIRASOAP APIJavadoc显示getServerInfo )方法

其中RemoteServerInfo被定义为:

 

public RemoteServerInfo {

   java.lang.String getBaseUrl()

   java.util.Date getBuildDate()

   java.lang.String getBuildNumber() ;

   RemoteTimeInfo getServerTime() ;

   java.lang.String getVersion()

}
 

 

为了使相同的调用通过JSON - RPC,你需要POST request onto http://hostname:80/jira/rpc/json-rpc/jirasoapservice-v2:

 

REQUEST :

{

    "jsonrpc" : "2.0", 

    "method" :

    "getServerInfo",

    "params" :  ["l632EGg4Kc"],

    "id" : 12345

}

  

RESPONSE :

{ 

   "id":12345,

   "result": {

      "version":"4.4-SNAPSHOT",

      "buildNumber":"634",

      "baseUrl":"http://localhost:8090/jira",

      "buildDate":1303135200000,

      "serverTime":{

         "timeZoneId":"Australia/Sydney",

         "serverTime":"2011-04-19T12:36:11.540+1000"}

        }

      },

    "jsonrpc":"2.0"

}
 

 

让我们看看在JSON - RPC消息结构。它如下的JSON - RPC规范的格式

Property

Comments

jsonrpc

Required. Must have the value "2.0".

method

Specifies the method to call.

params

An array of parameters to be passed to the method. In this case the string "l632EGg4Kc" is a security token which we will discuss later.

id

A unique request ID of your choosing. It will be echoed back to you so that you can marry requests with response. This is particularly useful if you use an asynchronous fire and forget programming technique.

响应包含呼应的要求“ID”属性和结果是一个JSON对象映射的RemoteServerInfo对象的属性, 。它映射成JSON对象的属性的公共方法。

必须使用HTTP POST动词。您不能使用GET调用的JSON - RPC方法。

The Light Protocol

该插件还支持一个的协议,允许客户在URL编码方法的名称,只有方法的参数,并提供在请求主体。非错误响应,在光的协议也省略了RPC的信封,并只提供什么通常会在一个普通的JSON - RPC响应的结果的对象。

他们沉重的协议将返回错误响应。

因此,在轻协议的上述要求相当于如下。

记住方法的名称,现在进入的URL,而不是POST体。

 

5.5  API策略介绍

可参考文档

https://developer.atlassian.com/,包含所有的AIP介绍等相信信息。

 

你可能感兴趣的:(jira,插件)