This page describes how to use the REST plugin module to expose a REST API from a plugin.
Plugin Framework 2 Only
The REST plugin module described below is available only for OSGi-based plugins using version 2.2 or later of the Atlassian Plugin Framework.
You can use the REST plugin module to expose services and data entities as REST APIs. The Atlassian REST plugin module is bundled with our applications.
REST APIs provide access to resources via URI paths. To use a REST API, your plugin or script will make an HTTP request and parse the response. You can choose JSON or XML for the response format. Your methods will be the standard HTTP methods like GET, PUT, POST and DELETE. Because the REST API is based on open standards, you can use any web development language to access the API.
A REST resource is exposed at a URL such as this:
1 2http://myhost.com:port/myapp/rest/api-name/api-version/resource-name
Here's how the parts of the URL are composed and used:
http://myhost.com:port
- The operating system directs the request to the application server (e.g. Tomcat) that handles the specified port.
/myapp
- Tomcat directs the request to the application myapp.
/rest
- The application's web.xml deployment descriptor file maps the URLs to the relevant servlets. So in this case, it maps /rest to our REST servlet, which points to our REST plugin module type.
/api-name/api-version
- Now the REST plugin module takes over. The relevant part of the URL (api-name
and api-version
) are defined as the path
and version
in the atlassian-plugin.xml
file. For example:
1 2<rest key="helloWorldRest" path="/helloworld" version="1.0"> <description>Provides hello world services.</description> </rest>
/resource-name
- The final part of the URL mapping (resource-name
and sub-elements) is done via annotations on the class, used to declare the URI path, the HTTP method and the media type. Jersey (based on JAX-RS) reads the @Provider
and @Path
annotations and maps them to classes and methods, so that we know which method is called for each REST resource and method. See the Jersey documentation.
JAXB converts the Java classes to XML or JSON and vice versa, making use of JAXB annotations. (Available in Java 1.5 and later.)
For example a Java User
object with JAXB annotations may look something like this:
1 2import javax.xml.bind.annotation.*; @XmlRootElement public class User { @XmlElement private String firstName; @XmlElement private String lastName; // This private constructor isn't used by any code, but JAXB requires any // representation class to have a no-args constructor. private User() { } public User(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } ... }
The XML response content for user John Smith would be:
1 2<user> <firstName>John</firstName> <lastName>Smith</lastName> </user>
By default, on conversion the XML element name will be the same as the object name. Alternatively, you can add the XML element name to the annotation. Something like this: @XmlRootElement(name="principal")
. There are specific annotations for arrays, etc. See JAXB's documentation for more details on this.
We have no schema or DTD.
Jersey also handles JSON based on the same JAXB objects as in the example above. The JSON for the example would be:
1 2{ "firstName":"John", "lastName":"Smith" }
A trivial REST service class with a single URL returning an instance of User
would look like this:
1 2import javax.ws.rs.*; import javax.ws.rs.core.*; @Path("/") @Consumes({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON}) public class RestHelloWorldService { @GET @Path("users") public Response getUncompletedUsers() { return Response.ok(new User("Fred","Bloggs")).build(); } }
The root element for the REST plugin module is rest
. It allows the following attributes and child elements for configuration.
Name | Description |
---|---|
key | The identifier of the plugin module, i.e. the identifier of the REST module. This key must be unique within the plugin where it is defined. Sometimes you will need to uniquely identify a module. Do this with the complete module key. A module with key Requred. Default: N/A |
path | The path to the REST API exposed by this module. For example, if set to Requred. Default: N/A |
version | This is the version of the REST API. This is not the same thing as the plugin version. Different versions of the same API can be provided by different plugins. Version numbers follow the same pattern as OSGi versions, i.e. Requred. Default: N/A |
Name | Description |
---|---|
description | The description of the plugin module, i.e. the description of the REST module. The 'key' attribute can be specified to declare a localisation key for the value instead of text in the element body. Default: N/A |
package | The package from which to start scanning for resources and providers. Can be specified multiple times. Defaults to scanning the whole plugin. Since 2.0 Default: N/A |
dispatcher | Determines when the filter is triggered. You can include multiple Default: Filter will be triggered on |
Here is an example atlassian-plugin.xml
file containing a single public component:
1 2<atlassian-plugin name="Hello World" key="example.plugin.helloworld" plugins-version="2"> <plugin-info> <description>A basic REST module test</description> <vendor name="Atlassian Software Systems" url="http://www.atlassian.com"/> <version>1.0</version> </plugin-info> <rest key="helloWorldRest" path="/helloworld" version="1.0"> <description>Provides hello world services.</description> </rest> </atlassian-plugin>
Here is some information to be aware of when developing a REST plugin module:
You can include the REST plugin module as a Maven dependency from our Maven repository.
To develop a REST API and deploy it into an Atlassian application, you will follow the same process as for any other Jersey application:
@Path
, @Provider
, etc.atlassian-plugin.xml
.See Set up the Atlassian Plugin SDK and Build a Project and Configuring the Plugin Descriptor.
Your REST resources will be available at this URL:
1 2http://host:port/context/rest/helloworld/1.0
host
and port
define the host and port where the application lives.context
is the servlet context of the application. For example, for Confluence this would typically be confluence
.helloworld
is the path declared in the REST module type in the plugin descriptor.1.0
is the API version.If 1.0
is the latest version of the helloworld API installed, this version will also be available at this URL:
1 2http://host:port/context/rest/helloworld/latest
The REST plugin module scans your plugin for classes annotated with the @Provider
and @Path
annotation. The @Path
annotations can be simply declared on a method within a class and do not need to be present at the entity level.
For those not familiar with the JAX-RS specification, the @Path annotation can be declared at a package, class, or method level. Furthermore, their effects are cumulative. For example, if you define this at the package level:
1 2@Path("/admin") package myPackage;
then this at the class level:
1 2package myPackage; @Path("/myGroup") public class MyGroup {...};
then this at the method level:
1 2@Path("/myResource") public void getResource() {...};
The final URL would be for the helloWorld plugin above:
1 2http://host:port/context/rest/helloworld/1.0/admin/myGroup/myResource
Notes:
META-INF/lib
directory of the JAR. So make sure you put all providers and resources at the top level in your plugin JAR. When using JAX-RS (and Jersey), the standard way to specify the content type of the response is to use the HTTP Accept header. While this is a good solution, it's not always a convenient one.
The REST plugin module allows you to use an extension to the resource name in the URL when requesting JSON or XML.
For example, let's assume I want to request JSON data for the resource at this address:
1 2http://host:port/context/rest/helloworld/latest/myresource
I have two options:
Option 1: Use the HTTP Accept header set to application/json
.
**Option 2:**Simply request the resource via this URL:
1 2http://host:port/context/rest/helloworld/latest/myresource.json
If I want content of type application/xml
, I will simply change the extension to .xml
. Currently the REST plugin module supports only application/json
and application/xml
.
A handy tool: The JSONView add-on for Firefox allows you to view JSON documents in the browser, with syntax highlighting. Here is a link to the Firefox add-on page.
By default, JSON responses include any object fields which are explicitly annotated with a JAXB annotation, while XML responses include public fields and fields with public getters.
To get the same behaviour for JSON you need to either annotate each field with @XmlElement
or @XmlAttribute
, or annotate the class or package with @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
.
Developing a REST Service Plugin
Atlassian REST API Design Guidelines version 1
Guidelines for Atlassian REST API Design
Atlassian Plugin Framework Documentation
Rate this page: