<!--[if !supportLists]-->一、<!--[endif]-->系统架构介绍
<!--[if !supportLists]-->1.1 <!--[endif]-->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 stack。Jira 支持 SOPA,XML-RPC 以
及 REST(表征状态转移,英文:Representational State Transfer,简称REST,
是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。)。
JIRA 与 SVN,CVS,Git,Clearcase,Visual SourceSafe,Mercurial 和 Perforce 等 source control 程序集成。可以使用多种语言,包括英语、日语、德语、法语、西班牙语。
JIRA 拥有灵活的插件架构,可以调用 JIRA 开发者社区和第三方开发的插件,与 IDE 集成,比如 Eclipse和 IntelliJ IDEA using the Atlassian IDE Connector. JIRA API[10]允许开发者向 JIRA 中继承第三方开发的应用程序。
<!--[if !supportLists]-->1.2 <!--[endif]-->涉及到的主要技术
JIRA使用的技术主要有:J2ee、Spring、工作流、freemarker等。
<!--[if !supportLists]-->二、<!--[endif]-->数据库模型
2.1 实体引擎模型
实体引擎是用于模型化和管理具体数据的一套工具和模式。实体是一块由一组字段和其他实体之间的关系定义的数据。这个定义来自关系数据库管理系统的标准实体 - 关系模型概念。实体引擎的目标是为了简化企业实体数据的广泛使用。这包括定义,维护,质量保证,以及相关的功能实体的发展。
2.2 数据库模型描述文件
数据库描述文件entitymodel.xml,您可以在 JIRA Web应用程序目录
WEB-INF/classes/entitydefs下找到他。他定义了JIRA数据库中所有的表、列和列的数据类型,以及部分表之间的关系。
2.3 部分数据库表关系介绍
<!--[if !supportLists]-->§ <!--[endif]-->问题域
<!--[if !supportLists]-->§ <!--[endif]-->简单字段(表:jiraissue存放问题的字段)
SQL:desc 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';
<!--[if !supportLists]-->§ <!--[endif]-->用户详细信息(表:cwd_user)
<!--[if !supportLists]-->§ <!--[endif]-->组件和版本
每个问题都有多个版本或者组件,表 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')
);
<!--[if !supportLists]-->§ <!--[endif]-->问题链接
问题的链接存储在表: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;
<!--[if !supportLists]-->§ <!--[endif]-->自定义字段
系统中用户自定义字段存储在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');
<!--[if !supportLists]-->§ <!--[endif]-->自定义字段配置操作
<!--[if !supportLists]-->§ <!--[endif]-->自定义字段配置默认值 (表:genericconfiguration)
自定义字段的默认值是存储在genericconfiguration表中。由于此表必须存
储任何自定义字段类型的值(级联选择,多选择等),该值被编码为XML如:
<string>2</string>。
<!--[if !supportLists]-->§ <!--[endif]-->自定义字段配置方案
JIRA允许每一个项目或者问题有不同的默认值,可以通过在页面上点击‘config’按钮来定义。
<!--[if !supportLists]-->§ <!--[endif]-->自定义字段配置域(表:fieldconfigscheme)
<!--[if !supportLists]-->§ <!--[endif]-->历史更改记录
在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');
<!--[if !supportLists]-->§ <!--[endif]-->工作日志
工作日志记录在worklog 表中。
每当worklog添加条目,jiraissue的timespent和timeestimate值分别递增和递减。
<!--[if !supportLists]-->§ <!--[endif]-->用户和组
用户存储在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来查询一个user,sql如下:
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表中。
<!--[if !supportLists]-->§ <!--[endif]-->问题状态和工作流
JIRA的问题包括:状态(如:开启,关闭,正在处理等)和工作流。
<!--[endif]-->
<!--[if !supportLists]-->§ <!--[endif]-->问题状态
JIRA的问题存储在jiraissue 表中。
<!--[if !supportLists]-->§ <!--[endif]-->问题工作流步骤
在早些版本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');
<!--[if !supportLists]-->§ <!--[endif]-->状态和步骤怎样关联的
一个问题的状态和工作流步骤是保持同步的。它是通过一个方法(UpdateIssueStatusFunction)来保持同步。
<!--[if !supportLists]-->三、<!--[endif]-->插件开发
3.1插件概览
3.1.1 JIRA支持的插件模型类型
Custom Field Plugin Module,
Gadget Plugin Module
Issue Link Renderer Plugin Module
sue 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
常用类型介绍:
<!--[if !supportLists]-->1. <!--[endif]-->Custom Field Plugin Module
自定义字段插件模块允许你添加新的自定义字段类型和搜索的JIRA。
1自定义字段类型 - 这些定义的自定义字段类型
2自定义字段seachers - 这些定义可以搜索自定义字段类型的方法.
自定义字段类型配置
自定义字段类型的插件模块的根元素是 customfield型。它允许用于配置以下属性和子元素:
Name | Required | Description | Default |
class | <!--[if gte vml 1]><v:shape id="_x0000_i1050" type="#_x0000_t75" alt="https://developer.atlassian.com/images/icons/emoticons/check.gif" style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square" mce_style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" o:title="check" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> | 实现了这个插件模块,您需要提供的类,取决于模块类型 。自定义字段类型模块的Java类 。类必须实现com.atlassian.jira.issue.customfields.CustomFieldType |
|
key | <!--[if gte vml 1]><v:shape id="_x0000_i1049" type="#_x0000_t75" alt="https://developer.atlassian.com/images/icons/emoticons/check.gif" style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square" mce_style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" o:title="check" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> | 插件模块的标识符 。此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)
<customfield-type key="userpicker" name="User Picker"
class="com.atlassian.jira.issue.customfields.impl.UserCFType">
<description>
Choose a user from the user base via a popup picker window.
</description>
<!-- this template is used on the view issue page -->
<resource type="velocity" name="view"
location="templates/plugins/fields/view-user.vm" />
<!-- this template is used on the create/edit issue pages -->
<resource type="velocity" name="edit"
location="templates/plugins/fields/edit-userpicker.vm" />
<!-- this template is used when viewing an issue as XML -->
<resource type="velocity" name="xml"
location="templates/plugins/fields/xml-user.vm" />
</customfield-type>
<!--[if !supportLists]-->2. <!--[endif]-->Issue Tab Panel Plugin Module
发行标签面板插件模块允许你添加新的选项卡面板,查看发行屏幕。
一个插件可以添加一个新的标签,显示单一的问题(最有可能被拉从外部源)的信息 。这是Subversion 和 Perforce 的集成是如何工作的。
下面是一个例子描述
<!--[if gte vml 1]><v:shapetype id="_x0000_t202" coordsize="21600,21600" o:spt="202" path="m,l,21600r21600,l21600,xe"> <v:stroke joinstyle="miter" /> <v:path gradientshapeok="t" o:connecttype="rect" /> </v:shapetype><v:shape id="_x0000_s1026" type="#_x0000_t202" style="position:absolute; left:0;text-align:left;margin-left:5.55pt;margin-top:1.65pt;width:480.45pt; height:244.95pt;z-index:1;mso-height-percent:200;mso-height-percent:200; mso-width-relative:margin;mso-height-relative:margin" mce_style="position:absolute; left:0;text-align:left;margin-left:5.55pt;margin-top:1.65pt;width:480.45pt; height:244.95pt;z-index:1;mso-height-percent:200;mso-height-percent:200; mso-width-relative:margin;mso-height-relative:margin"> <v:textbox style="mso-fit-shape-to-text:t" mce_style="mso-fit-shape-to-text:t" /> </v:shape><![endif]--><!--[if !vml]-->
<issue-tabpanel key="subversion-commits-tabpanel" name="Subversion Changes Tab Panel"
class="com.atlassian.jira.plugin.ext.subversion.issuetabpanels.changes.SubversionRevisionsTabPanel">
<resource type="i18n" name="i18n"
location="templates.plugins.subversion.issuetabpanels.subversion_jira_plugin"/>
<description>Show Subversion commits related to an issue in an issue tab panel.</description>
<label>Subversion Commits</label>
<resource type="velocity" name="view" location="templates/plugins/subversion/issuetabpanels/subversion-commits-view.vm"/>
</issue-tabpanel>
class="..." 属性在指定的模块类必须实现IssueTabPanel的接口 。
插件可以指定他们的标签可以加载在一个AJAX请求,这是在JIRA 5.0和更高版本支持。下面就是一个例子的问题“选项卡上,使AJAX加载XML片段。
<!--[if gte vml 1]><v:shape id="_x0000_s1027" type="#_x0000_t202" style="position:absolute; left:0;text-align:left;margin-left:30.05pt;margin-top:11.4pt;width:379.2pt; height:127.95pt;z-index:2;mso-height-percent:200;mso-height-percent:200; mso-width-relative:margin;mso-height-relative:margin" mce_style="position:absolute; left:0;text-align:left;margin-left:30.05pt;margin-top:11.4pt;width:379.2pt; height:127.95pt;z-index:2;mso-height-percent:200;mso-height-percent:200; mso-width-relative:margin;mso-height-relative:margin"> <v:textbox style="mso-fit-shape-to-text:t" mce_style="mso-fit-shape-to-text:t" /> </v:shape><![endif]--><!--[if !vml]--> <!--[endif]--> <issue-tabpanel key="example-tabpanel" name="A tab panel"
class="com.example.AjaxCapableTabPanel">
<!-- enable fast tab switch -->
<supports-ajax-load>true</supports-ajax-load>
</issue-tabpanel>
<!--[if !supportLists]-->3. <!--[endif]-->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 | <!--[if gte vml 1]><v:shape id="_x0000_i1047" type="#_x0000_t75" alt="https://developer.atlassian.com/images/icons/emoticons/check.gif" style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square" mce_style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" o:title="check" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> | 插件模块的标识符 。必须在它被定义的插件是唯一 的,有时在其他情况下,您可能需要唯一地标识一个模块。 | N/A |
location |
| <!--[if !supportLists]-->§ <!--[endif]-->在应用程序的过滤器链的过滤器的位置。如果两个插件提供过滤器在相同的位置, <!--[if !supportLists]-->§ <!--[endif]-->after-encoding – <!--[if !supportLists]-->§ <!--[endif]-->before-login – <!--[if !supportLists]-->§ <!--[endif]-->before-decoration – <!--[if !supportLists]-->§ <!--[endif]-->before-dispatch – | before-dispatch |
name |
| 插件模块的名称。即过滤器的可读名称。 | The plugin key |
system |
| 仅适用于非OSGi的插件 | false |
weight |
| 100 |
Example:
atlassian-plugin.xml文件
<atlassian-plugin name="Hello World Filter" key="example.plugin.helloworld" plugins-version="2">
<plugin-info>
<description>A basic Servlet filter module test - says "Hello World!</description>
<vendor name="Atlassian Software Systems" url="http://www.atlassian.com"/>
<version>1.0</version>
</plugin-info>
<servlet-filter name="Hello World Servlet" key="helloWorld" class="com.example.myplugins.helloworld.HelloWorldFilter" location="before-dispatch" weight="200">
<description>Says Hello World, Australia or your name.</description>
<url-pattern>/helloworld</url-pattern>
<init-param>
<param-name>defaultName</param-name>
<param-value>Australia</param-value>
</init-param>
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</servlet-filter>
</atlassian-plugin>
<!--[if !supportLists]-->4. <!--[endif]-->Servlet Plugin Module
Servlet的插件模块使您部署的Java servlet为你的插件的一部分。
配置
Servlet的插件模块的根元素是 servlet。它允许用于配置以下属性和子元素:
属性
Name | Required | Description | Default |
class | <!--[if gte vml 1]><v:shape id="图片_x0020_25" o:spid="_x0000_i1045" type="#_x0000_t75" alt="https://developer.atlassian.com/images/icons/emoticons/check.gif" style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square" mce_style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" o:title="check" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> | 该servlet的Java类 。必须是子类javax.servlet.http.HttpServlet |
|
state |
| 指示是否应该被默认禁用的插件模块,默认启用 | enabled |
i18n-name-key |
| 本地化 |
|
key | <!--[if gte vml 1]><v:shape id="图片_x0020_26" o:spid="_x0000_i1044" type="#_x0000_t75" alt="https://developer.atlassian.com/images/icons/emoticons/check.gif" style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square" mce_style="width:12pt;height:12pt;visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image003.gif" o:title="check" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]--> | 插件模块的标识符 | N/A |
name |
| 可读的servlet名称 | The plugin key. |
system |
| 指示是否这个插件模块是一个系统插件模块 | false |
下面是一个例子atlassian - plugin.xml的文件,其中包含一个单独的servlet:
<atlassian-plugin name="Hello World Servlet" key="example.plugin.helloworld" plugins-version="2">
<plugin-info>
<description>A basic Servlet module test - says "Hello World!</description>
<vendor name="Atlassian Software Systems" url="http://www.atlassian.com"/>
<version>1.0</version>
</plugin-info>
<servlet name="Hello World Servlet" key="helloWorld" class="com.example.myplugins.helloworld.HelloWorldServlet">
<description>Says Hello World, Australia or your name.</description>
<url-pattern>/helloworld</url-pattern>
<init-param>
<param-name>defaultName</param-name>
<param-value>Australia</param-value>
</init-param>
</servlet>
</atlassian-plugin>
<!--[if !supportLists]-->5. <!--[endif]-->
3.1.2内置的JIRA系统插件介绍
运行插件后可以看到所有的系统插件
3.2使用Plugin SDK开发插件
3.2.1插件开发环境准备
操作系统要求:
JIRA的运行需要Java环境,Java是一个跨平台的编程语言,因此所有支持Java的操作系统上都可以运行JIRA,当然也需要考虑操作系统上是否支持您选择的应用服务器软件。目前Sun的JDK有Windows(32位和64位),Solaris(APARC 32位和64位),Linux平台(32位和64位)。
JIRA支持的应用服务:
Tomcat,JBoss,Weblogic,Resin
IRA支持的数据库:
Oracle,DB2,MySQL,SQL Server ,Sybase等。
浏览器要求:
JIRA支持各种主流的web浏览器,如:IE6以上、Mozilla、Firefox、Opera、Safari等。
3.2.1.1 安装JAVA
3.2.1.1.1下载并安装JDK
最好选择JDK1.6版本安装。
3.2.1.1. 2设置你的JAVA_HOME环境变量
操作:鼠标右击我的电脑—>属性,选择高级选项卡,再选择环境变量跳出如图1.1.2.1对话框:
<!--[if gte vml 1]><v:shape id="_x0000_i1042" type="#_x0000_t75" style="width:267.75pt;height:123pt;visibility:visible;mso-wrap-style:square" mce_style="width:267.75pt;height:123pt;visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image006.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image006.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
图1.1.2.1
点击新建按钮,跳出如图1.1.2.2对话框,填写变量名为:JAVA_HOME,变量值为:jdk安装的路径。填写完成后点击确定按钮,然后测试安装信息填写的正确性。
<!--[if gte vml 1]><v:shape id="图片_x0020_13" o:spid="_x0000_i1041" type="#_x0000_t75" style="width:260.25pt;height:104.25pt;visibility:visible; mso-wrap-style:square" mce_style="width:260.25pt;height:104.25pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image008.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image008.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
图1.1.2.2
测试:在运行中输入cmd命令,打开命令行窗口,运行java –version命令,如果命令行窗口出现安如图1.1.2.3装jdk的版本信息,则说明安装jdk成功。
<!--[if gte vml 1]><v:shape id="图片_x0020_19" o:spid="_x0000_i1040" type="#_x0000_t75" style="width:390pt;height:153.75pt;visibility:visible; mso-wrap-style:square" mce_style="width:390pt;height:153.75pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image010.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image010.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
图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对话框:
<!--[if gte vml 1]><v:shape id="图片_x0020_22" o:spid="_x0000_i1039" type="#_x0000_t75" style="width:260.25pt;height:104.25pt; visibility:visible;mso-wrap-style:square" mce_style="width:260.25pt;height:104.25pt; visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image012.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image012.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
图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:
<!--[if gte vml 1]><v:shape id="_x0000_i1038" type="#_x0000_t75" style="width:259.5pt;height:105.75pt;visibility:visible; mso-wrap-style:square" mce_style="width:259.5pt;height:105.75pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image014.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image014.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
变量值:指定到SDK所在的目录。
3.2.1. 4 配置你的IDE
我们推荐您使用Eclipse,MyEclipse,IntelliJ IDEA的 或NetBeans等IDE。因为所有这些支持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=<path to your Eclipse workspace>
红色部分需要修改,需要指定到myEclipse的工作空间
如:atlas-mvn eclipse:add-maven-repo -Declipse.workspace= E:\workspace_jira
运行中如果出现如下错误
<!--[if gte vml 1]><v:shape id="图片_x0020_2" o:spid="_x0000_i1037" type="#_x0000_t75" style="width:415.5pt;height:57pt; visibility:visible;mso-wrap-style:square" mce_style="width:415.5pt;height:57pt; visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image016.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image016.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
需要把atlas-mvn替换成%ATLAS_HOME%\apache-maven\bin\mvn然后再运行。
3.2.2创建插件框架
进入myEclipse工作空间,如下:
<!--[if gte vml 1]><v:shape id="图片_x0020_3" o:spid="_x0000_i1036" type="#_x0000_t75" style="width:130.5pt;height:45.75pt;visibility:visible; mso-wrap-style:square" mce_style="width:130.5pt;height:45.75pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image018.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image018.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
执行:atlas-create-jira-plugin
<!--[if gte vml 1]><v:shape id="图片_x0020_9" o:spid="_x0000_i1035" type="#_x0000_t75" style='width:415.5pt; height:72.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image020.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image020.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
1:jira5
2:jira4
选择jira5,输入1,回车
<!--[if gte vml 1]><v:shape id="_x0000_i1034" type="#_x0000_t75" style='width:415.5pt;height:55.5pt; visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image022.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image022.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
artifactId:工程名称
version: 当前版本信息
package: 包路径
然后到myEclipse的workspace目录中找到生成的jira工程,找到pom.xml文件,修改
<organization>
<name>Example Company</name>
<url></url>
</organization>
<description>This plugin implements a simple issue event listener for JIRA using atlassian-event.</description>
是一些描述信息,不修改也是可以的。
还有一些版本信息,
<properties>
<!-- TODO: Update to 5.0 after release of 5.0 final -->
<jira.version>5.0-beta1</jira.version>
<amps.version>3.7.2</amps.version>
</properties>
目前生成的是5.0-beta1,当然如果有其他版本,则需要修改为其他版本,如5.0-sc2,或4.0版本等。
执行:cmd命令:
进入到工程的所在目录,执行:atlas-mvn eclipse:eclipse,如下:
<!--[if gte vml 1]><v:shape id="图片_x0020_11" o:spid="_x0000_i1033" type="#_x0000_t75" style='width:414.75pt; height:42.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image024.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image024.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
此命令是创建myEclipse的描述文件,为jira的支持,如.classpath 和.project。
启动myEclipse,导入生成的工程:new-listener-plugin
就可以在myEclipse中看到生成的工程了,目录结构如下:
<!--[if gte vml 1]><v:shape id="图片_x0020_14" o:spid="_x0000_i1032" type="#_x0000_t75" style='width:211.5pt; height:230.25pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image026.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image026.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
3.2.3启动应用
运行atlas-run ,启动应用
<!--[if gte vml 1]><v:shape id="图片_x0020_15" o:spid="_x0000_i1031" type="#_x0000_t75" style='width:414.75pt; height:26.25pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image028.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image028.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
首次启动时jira会加载很多jia包,包括编译和下载运行服务器,会较慢!
启动成功后:打开浏览器,需要用ie7以上的版本,或google浏览器,建议使用google浏览器。
输入访问路径:http://localhost:2990/jira/,
<!--[if gte vml 1]><v:shape id="图片_x0020_16" o:spid="_x0000_i1030" type="#_x0000_t75" style='width:414.75pt; height:154.5pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image030.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image030.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
用admin/admin登陆,登陆成功后就可以看到我们开发的插件了。
<!--[if gte vml 1]><v:shape id="图片_x0020_17" o:spid="_x0000_i1029" type="#_x0000_t75" style='width:414.75pt; height:243.75pt;visibility:visible;mso-wrap-style:square'> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image032.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image032.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
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中的配置,
<component-import key="eventPublisher" interface="com.atlassian.event.api.EventPublisher"/>
<component key="eventListener"
class="com.example.plugins.tutorial.IssueCreatedResolvedListener">
<description>Class that processes the incoming JIRA issue events.</description>
</component>
添加log4j支持,在pom.xml文件中添加
<configuration>
<productVersion>${jira.version}</productVersion>
<productDataVersion>${jira.version}</productDataVersion>
<log4jProperties>src/log4j.properties</log4jProperties>
<!-- configure our own logging -->
</configuration>
添加log4j.jar。
3.2.6插件的编译及打包
运行atlas-run ,会在target目录下生产项目的发布包。
<!--[if !supportLists]-->四、<!--[endif]-->插件开发例子介绍
<!--[if !supportLists]-->五、<!--[endif]-->JIRA远程API介绍
5.1 REST API
概述
无论你想建立的,我们的目的是提供平台。新的Web或桌面应用,移动应用程序,集成,基于浏览器的扩展或附加,Atlassian插件,不管你可以梦想。Atlassian的REST API提供一个标准的接口与JIRA和其他应用程序进行交互。
REST API的访问资源(数据实体)可以通过URI路径。要使用一个REST API,应用程序将一个HTTP请求,并解析响应。你的方法将标准的HTTP GET,PUT,POST和DELETE方法。REST API的工作在HTTP(S)很容易地使用任何编程语言或框架。
JIRA的REST API的输入和输出格式是JSON。
JIRA使用的Atlassian REST插件实施的JIRA的API 。REST插件是捆绑在一起的JIRA。您可以添加您自己的REST API来创建一个JIRA插件,包括REST插件模块的JIRA 。
<!--[if !supportLists]-->§ <!--[endif]-->输入文件是由' --data @filename “语法表示。数据显示分开,并使用JSON格式。
<!--[if !supportLists]-->§ <!--[endif]-->确保请求的内容类型设置为“ application/json “,如在本例中所示。
<!--[if !supportLists]-->§ <!--[endif]-->到您的JIRA服务器的JSON。在这个例子中,服务器是:http://localhost:8090/rest/api/2/issue/。
<!--[if !supportLists]-->§ <!--[endif]-->例如使用基本身份验证,用户名“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 - RPC和SOAP.This文件的远程访问包含对RPC插件的说明
通过一个Java SOAP客户端(需要的JIRA3.1或以上)如何执行各种操作(如创建问题)。
要远程调用的JIRA操作,你应该确保你的目标上JIRA安装启用的RPC插件。如果您
只是想创建一个客户端,那么你可以跳过这一步。首先,你需要检查一下,如果接受远程API调用http://jira.atlassian.com/一般配置全局设置已启用“(在左侧菜单)
<!--[if gte vml 1]><v:shape id="图片_x0020_1" o:spid="_x0000_i1028" type="#_x0000_t75" style="width:261pt;height:200.25pt;visibility:visible; mso-wrap-style:square" mce_style="width:261pt;height:200.25pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image034.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image034.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
然后,您需要启用的JIRA的RPC插件“
<!--[if gte vml 1]><v:shape id="图片_x0020_4" o:spid="_x0000_i1027" type="#_x0000_t75" style="width:282.75pt;height:234.75pt;visibility:visible; mso-wrap-style:square" mce_style="width:282.75pt;height:234.75pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image036.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image036.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
如果插件没有出现如上,那么您的RPC JAR没有被正确安装。从下载的jar
并将其复制到您的JIRA的安装文件夹。执行重新启动,和你的资料库atlassian-jira/WEB-INF/lib插件应该出现
您的服务器现在应该准备接受远程过程调用。
WSDL的描述符
无论语言或SOAP API的使用,您将需要为您的JIRA安装的WSDL描述。这是发现在http:// your_installation / rpc/soap/jirasoapservice-v2?WSDL。例如,http://jira.atlassian.com的WSDL文件是:
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及以上版本附随JIRA的XML - RPC插件,它可以通过XML- RPC和SOAP的远程访问。Utilising此功能
使用XML - RPC无法与一些从包中的帮助下要容易得多。在本教程中,我们写一个基本的XML- RPC客户端的Apache XML - RPC的
(使用)记录,检索项目,然后再次登录。还展示了一个Python客户端。的Apache XML- RPC
启用RPC插件同上:如下图
<!--[if gte vml 1]><v:shape id="图片_x0020_7" o:spid="_x0000_i1026" type="#_x0000_t75" style="width:273.75pt;height:206.25pt; visibility:visible;mso-wrap-style:square" mce_style="width:273.75pt;height:206.25pt; visibility:visible;mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image038.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image038.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
然后,您需要启用JIRA的RPC插件如下
<!--[if gte vml 1]><v:shape id="图片_x0020_10" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:315.75pt;height:215.25pt;visibility:visible; mso-wrap-style:square" mce_style="width:315.75pt;height:215.25pt;visibility:visible; mso-wrap-style:square"> <v:imagedata src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image040.png" mce_src="file:///C:\Users\ADMINI~1\AppData\Local\Temp\msohtmlclip1\01\clip_image040.png" o:title="" /> </v:shape><![endif]--><!--[if !vml]--><!--[endif]-->
现在,您的服务器已准备好接受远程过程调用,我们开始创建一个Java的XML - RPC客户端。
5.4 JSON-RPC
5.4.1 JIRA的远程API概述
这里是一个快速指导,JIRA的远程API的主要。
JIRA的远程API | 状态 |
推荐和支持。 REST的建议和支持,在JIRA 5.0和更高版本的远程API。这是Atlassian将其注意力集中从这时开始,新增功能和修正错误。 | |
支持,但没有发展前途。 Atlassian将继续支持SOAP API,直到REST API提供了一个更换所有现有的SOAP功能 。但是,我们不会增加新的功能到现有的SOAP接口。 | |
支持,但没有发展前途。 JIRA仍然支持XML - RPC的客户,但我们建议无论是SOAP,它提供了更多的功能,或REST,这是我们今后的发展将重点。 | |
过渡。 Atlassian 的JSON - RPC功能的JIRA,以帮助您从SOAP API对REST API的方式,一种机制,使用更多的JSON和JavaScript。我们建议您尽快移动到休息。 |
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方法调用之间的映射 。例如,为JIRA的SOAP API的Javadoc显示这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介绍等相信信息。