JIRA Scripting API

Last modified by Vincent Massol on 2026/07/27 21:23

Reference

The jira Script Service hands a script Atlassian's own JIRA REST Java Client, already pointed at a JIRA instance and carrying that instance's authentication. Everything beyond obtaining the client, that is searching, reading and writing issues, is done through the client's own API.

The API is usable from Groovy, which can construct the objects it needs. Velocity cannot, so a Velocity script has no way to call it.

Obtaining a Client

CallReturns
$services.jira.getJiraRestClient($jiraServer)A client connected to the instance described by the passed org.xwiki.contrib.jira.config.JIRAServer, authenticated with that instance's authenticator when it has one, and anonymous otherwise. null when the instance URL is not a valid URI.

The client holds threads and must be closed by the caller once it is no longer needed. In Groovy, withCloseable does it on every exit path.

Designating the Instance

A JIRAServer either is built in the script, for a public instance, or is taken from the wiki configuration, which is what carries credentials.

ExpressionUse
new JIRAServer(url, id)An instance built on the spot from its URL. The id is free and only used to build the cache key of asynchronous Macro rendering, so it may be empty. The connection is anonymous.
services.component.getInstance(JIRAConfiguration.class).getJIRAServers().get(id)The instance an administrator configured under that id, with its authentication. This is the only way for a script to reach issues that are not public.

The JIRAServer(url) and JIRAServer(url, username, password) constructors are deprecated: pass an authenticator, or take the instance from the configuration.

Reading an Issue of a Public Instance

{{groovy}}
import org.xwiki.contrib.jira.config.JIRAServer

services.get("jira").getJiraRestClient(new JIRAServer("https://jira.xwiki.org", "")).withCloseable { client ->
  def issue = client.getIssueClient().getIssue("XWIKI-1000").claim()
  println "Summary: ${issue.getSummary()}"
}
{{/groovy}}

Reading an Issue of a Configured Instance

{{groovy}}
import org.xwiki.contrib.jira.config.JIRAConfiguration

def jiraServer = services.component.getInstance(JIRAConfiguration.class).getJIRAServers().get("xwikiorg")

services.get("jira").getJiraRestClient(jiraServer).withCloseable { client ->
  def issue = client.getIssueClient().getIssue("XWIKI-1000").claim()
  println "Summary: ${issue.getSummary()}"
}
{{/groovy}}

Searching with a JQL Query

{{groovy}}
import org.xwiki.contrib.jira.config.JIRAConfiguration

def jiraServer = services.component.getInstance(JIRAConfiguration.class).getJIRAServers().get("xwikiorg")

services.get("jira").getJiraRestClient(jiraServer).withCloseable { client ->
  println "|=Key|=Summary"
  client.getSearchClient().searchJql("project = XWIKI AND status = Closed ORDER BY priority DESC").claim().getIssues().each { issue ->
    println "|${issue.getKey()}|${issue.getSummary()}"
  }
}
{{/groovy}}

FAQ

Can I use this API from Velocity?

No. The API needs a JIRAServer instance, and Velocity can neither construct one nor obtain the Component that holds them, so Groovy is the only supported scripting language.

Why does my script leak threads?

Because the client was not closed. Wrap the client in withCloseable, or call close() on it in a finally block.

Does the API respect the rights of the user viewing the page?

No. It queries JIRA with the credentials of the instance it was given, exactly like the JIRA Macros, so a script must not expose data its readers should not see.

Is there an alternative to this API?

Yes, calling JIRA's REST API directly from Groovy, which needs no extension at all and is often shorter.

Related

Get Connected