{"id":617,"date":"2013-01-18T17:53:44","date_gmt":"2013-01-18T17:53:44","guid":{"rendered":"http:\/\/shivdev.com\/blog\/?p=617"},"modified":"2013-01-18T17:57:37","modified_gmt":"2013-01-18T17:57:37","slug":"jira-xmlrpc-sample-java-code","status":"publish","type":"post","link":"http:\/\/shivdev.com\/blog\/2013\/01\/18\/jira-xmlrpc-sample-java-code\/","title":{"rendered":"JIRA XMLRPC Sample Java Code"},"content":{"rendered":"<p>If you&#8217;re on an older version of JIRA with XMLRPC being the only option (since REST is not available), Atlassian&#8217;s XMLRPC APIs are pretty simple to use. For my use case, I wanted a listing of total issues in my filters with individual breakdowns as illustrated below. <em><strong>JIRA Filter (Total Count) : assignee_1(count) assignee_2(count) &#8230;<\/strong><\/em><\/p>\n<blockquote><p>\nTennis Project Open Jiras (4) : rfederer(1) rnadal(1) nole(1) andym(1)<br \/>\nNFL Project Open Items (0) :<br \/>\nTennis Project FRs Ready for Verification (36) : andym(1) rfederer(17) nole(7) rnadal(11)<br \/>\nNFL Project FRs Fixed in Branch (25) :  tbrady(5) manning(7) asmith(12) dbrees(1)\n<\/p><\/blockquote>\n<p>So I wrote some code for which I needed the following.<\/p>\n<ul>\n<li><a href=\"http:\/\/ws.apache.org\/xmlrpc\/\">XMLRPC libraries<\/a><\/li>\n<li><a href=\"https:\/\/devcentral.f5.com\/blogs\/us\/ssl-trust-provider-for-java#.UPmKf3fonlM\">XTrustProvider <\/a>class : to bypass the <a href=\"http:\/\/shivdev.com\/blog\/2011\/09\/08\/making-jre-trust-certificates\/\">JRE certificate<\/a> business <\/li>\n<li>Atlassian Docs on <a href=\"https:\/\/developer.atlassian.com\/display\/JIRADEV\/Creating+an+XML-RPC+Client\">Creating an XML-RPC Client<\/a> <\/li>\n<li>Atlassian <a href=\"http:\/\/docs.atlassian.com\/software\/jira\/docs\/api\/rpc-jira-plugin\/latest\/com\/atlassian\/jira\/rpc\/xmlrpc\/XmlRpcService.html\">XMLRPC javadocs<\/a><\/li>\n<\/ul>\n<p>Then simply use the inefficient code below to get what you need.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npackage com.shivdev.jira;\r\n\r\nimport java.net.URL;\r\nimport java.util.HashMap;\r\nimport java.util.Map;\r\nimport java.util.Vector;\r\n\r\nimport javax.net.ssl.HostnameVerifier;\r\nimport javax.net.ssl.HttpsURLConnection;\r\nimport javax.net.ssl.SSLSession;\r\n\r\nimport org.apache.xmlrpc.client.XmlRpcClient;\r\nimport org.apache.xmlrpc.client.XmlRpcClientConfigImpl;\r\n\r\nimport com.shivdev.util.XTrustProvider;\r\n\r\npublic class JiraXMLRPC4Blog {\r\n\t\/\/ Our business logic would iterate over these filters and display the total counts and individual breakdowns \r\n\t\/\/ To get the Filter IDs, navigate the filter from JIRA and copy the requestId  \r\n\t\/\/ https:\/\/jira.hostname.com:8443\/secure\/IssueNavigator.jspa?mode=hide&amp;requestId=13611\r\n\tstatic String [][] FILTERS = new String[][] {\r\n\t\t\t{&quot;13584&quot;, &quot;Tennis Project Open Jiras&quot;}, \r\n\t\t\t{&quot;13661&quot;, &quot;NFL Project Open Items&quot;},\r\n\t\t\t{&quot;13611&quot;, &quot;Tennis Project FRs Ready for Verification&quot;}, \r\n\t\t\t{&quot;13583&quot;, &quot;NFL Project FRs Fixed in Branch&quot;}, \r\n\t};\r\n\t\r\n\t\/\/ This hostname verification step can be omitted if your not on HTTPS\r\n\tstatic {\r\n\t\tHttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {\r\n\t\t\tpublic boolean verify(String hostname, SSLSession session) {\r\n\t\t\t\t\/\/ Make sure that hostname is valid\r\n\t\t\t\treturn true;\r\n\t\t\t}\r\n\t\t});\r\n\t}\r\n\r\n\t\/\/ Constants\r\n\tpublic static final String JIRA_URI = &quot;https:\/\/jira.hostname.com:8443&quot;; \/\/ JIRA hostname\r\n\tpublic static final String RPC_PATH = &quot;\/rpc\/xmlrpc&quot;; \/\/ JIRA path to xmlrpc\r\n\tpublic static final String METHOD = &quot;getIssuesFromFilter&quot;; \/\/ JIRA xmlrpc method\r\n\t\r\n\tpublic static void main(String[] args) {\r\n\t\tif (args.length == 2) {\r\n\t\t\tString user = args[0];\r\n\t\t\tString passwd = args[1];\r\n\t\t\tJiraXMLRPC4Blog.printIssueDetails(user, passwd);\r\n\t\t} else {\r\n\t\t\tSystem.err.print(&quot;Provide username and password as arguments.&quot;);\r\n\t\t}\r\n\t}\r\n\t\r\n\t\/\/ Business Logic - Inefficiently callJIRARPC - Just for Demo purpose\r\n\t\/\/ Ideally 1 login multiple RPCs and 1 logout should have been enough  \r\n\tpublic static void printIssueDetails(String user, String passwd) {\r\n\t\t\r\n\t\t\/\/ Go over all the filters\r\n\t\tfor (int filterIdx = 0; filterIdx &lt; FILTERS.length; filterIdx++) {\r\n\t\t\tString filterID = FILTERS[filterIdx][0];\r\n\t\t\tString filterName = FILTERS[filterIdx][1];\r\n\t\t\t\r\n\t\t\tVector&lt;String&gt; params = new Vector&lt;String&gt;(0);\r\n\t\t\tparams.add(filterID); \r\n\t\t\t\r\n\t\t\t\/\/ Construct assignees and counts for each filter\r\n\t\t\tMap&lt;String, Integer&gt; assignees = new HashMap&lt;String, Integer&gt; ();\r\n\t\t\tObject issues[] = JiraXMLRPC.callJiraRPC(user, passwd, METHOD, params);\r\n\t\t\tif (issues != null) {\r\n\t\t\t\tfor (int i = 0; i &lt; issues.length; i++) {\r\n\t\t\t\t\tMap&lt;String, Object&gt; issue = (Map) issues[i];\r\n\t\t\t\t\t\/\/ summary, status, votes, assignee, customFieldValues, fixVersions, type, id, reporter, project, created, updated, description, priority, components, affectsVersions, key\r\n\r\n\t\t\t\t\tString assignee = (issue.get(&quot;assignee&quot;)).toString();\r\n\t\t\t\t\tInteger bugCount = assignees.get(assignee);\r\n\t\t\t\t\tassignees.put(assignee, bugCount == null ? 1 : bugCount + 1);\r\n\t\t\t\t}\r\n\t\t\t}\r\n\t\t\t\r\n\t\t\t\/\/ Print details\r\n\t\t\tStringBuffer buf = new StringBuffer();\r\n\t\t\tbuf.append(filterName + &quot; (&quot; + issues.length + &quot;) : &quot;);\r\n\t\t\tfor (String assignee : assignees.keySet()) {\r\n\t\t\t\tbuf.append(assignee + &quot;(&quot; + assignees.get(assignee) + &quot;) &quot;);\r\n\t\t\t}\r\n\t\t\tlog(buf.toString());\r\n\t\t}\r\n\t}\r\n\t\r\n\t\/\/ Actual Sample Code for making XMLRPC calls \r\n\tpublic static Object[] callJiraRPC(String user, String passwd, String method, Vector methodParams) {\r\n\t\ttry {\r\n\t\t\tXTrustProvider.install();\r\n\t\r\n\t\t\tXmlRpcClient rpcClient;\r\n\t\t\tXmlRpcClientConfigImpl config;\r\n\t\r\n\t\t\tconfig = new XmlRpcClientConfigImpl();\r\n\t\t\tconfig.setServerURL(new URL(JIRA_URI + RPC_PATH));\r\n\t\t\trpcClient = new XmlRpcClient();\r\n\t\t\trpcClient.setConfig(config);\r\n\t\t\t\r\n\t\t\t\/\/ login\r\n\t\t\tVector&lt;String&gt; loginParams = new Vector&lt;String&gt;(2);\r\n\t\t\tloginParams.add(user);\r\n\t\t\tloginParams.add(passwd);\r\n\t\t\tString loginToken = (String) rpcClient.execute(&quot;jira1.login&quot;, loginParams);\r\n\t\t\tlog(&quot;Logged in.&quot;);\r\n\t\t\t\r\n\t\t\t\/\/ Create the Authentication Token to be passed with every JiraXMLRPC call\r\n\t\t\tVector&lt;String&gt; loginTokenVector = new Vector&lt;String&gt;(1);\r\n\t\t\tloginTokenVector.add(loginToken);\r\n\t\t\t\r\n\t\t\t\/\/ Create a list of loginToken + methodParams\r\n\t\t\tint size = 1 + ((methodParams != null) ? methodParams.size() : 0);  \r\n\t\t\tVector paramsVector = new Vector(size);\r\n\t\t\tparamsVector.addAll(loginTokenVector);\r\n\t\t\tparamsVector.addAll(methodParams);\r\n\t\t\t\t\t\t\r\n\t\t\t\/\/ Make the RPC call\r\n\t\t\tObject[] result = (Object[]) rpcClient.execute( &quot;jira1.&quot; + method, paramsVector);\r\n\t\t\tlog(method + &quot; sucess.&quot;);\r\n\t\t\t\r\n\t\t\t\/\/ Log out\r\n\t\t\tBoolean bool = (Boolean) rpcClient.execute(&quot;jira1.logout&quot;, loginTokenVector);\r\n\t\t\tlog(&quot;Logged out.&quot;);\r\n\t\t\t\r\n\t\t\t\/\/ Return the result\r\n\t\t\treturn result;\r\n\t\t\t\r\n\t\t} catch (Throwable e) {\r\n\t\t\te.printStackTrace();\r\n\t\t}\r\n\t\t\r\n\t\treturn null;\r\n\t}\r\n\t\r\n\t\/\/ Custom Logging Code\r\n\tpublic static void log(String msg) {\r\n\t\tSystem.out.println(msg);\r\n\t}\r\n\t\r\n}\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>If you&#8217;re on an older version of JIRA with XMLRPC being the only option (since REST is not available), Atlassian&#8217;s XMLRPC APIs are pretty simple to use. For my use case, I wanted a listing of total issues in my filters with individual breakdowns as illustrated below. JIRA Filter (Total Count) : assignee_1(count) assignee_2(count) &#8230; [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/posts\/617"}],"collection":[{"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/comments?post=617"}],"version-history":[{"count":4,"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/posts\/617\/revisions"}],"predecessor-version":[{"id":621,"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/posts\/617\/revisions\/621"}],"wp:attachment":[{"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/media?parent=617"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/categories?post=617"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/shivdev.com\/blog\/wp-json\/wp\/v2\/tags?post=617"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}