REST Fragment Plugin Module

Introduction

A REST fragment module defines a Java component that can extend the functionality of a REST endpoint. The REST fragment will be executed in conjunction with any other REST fragments registered to the same location.

Only REST endpoints that are configured to execute REST fragments can be extended. A list of locations that a REST fragment module can extend, and the context that they provide, is included below.

Configuration

The root element for the REST fragment plugin module is <rest-fragment/>. It allows the following four attributes for configuration:

Attributes

NameRequiredDescriptionDefault
keyYesThe unique identifier of the plugin module. This key must be unique within the plugin where it is defined.N/A
locationYesThe REST endpoint location to register the REST fragment to.N/A
classYesThe fully qualified Java class name of REST fragment. This class must implement RestFragment.N/A
weightDetermines the order in which the REST fragments execute. The 'lightest' weight fragment executes first, and the 'heaviest' executes last.100

Locations

LocationDescriptionREST URIContextSince
bitbucket.repository.settings.pullRequestsPull request settings for a repository/rest/api/1.0/projects/{projectKey}/repos/{repositorySlug}/settings/pull-requestsrepository4.7

Example

Here is an example atlassian-plugin.xml file containing a single REST fragment:

1
2
3
4
5
6
7
8
9
<atlassian-plugin name="My Rest Fragment" key="example.plugin.fragment" plugins-version="2">
    <plugin-info>
        <description>A basic component import module test</description>
        <vendor name="My Company" url="http://www.mycompany.com"/>
        <version>1.0</version>
    </plugin-info>

    <rest-fragment key="myRestFragment" location="bitbucket.repository.settings.pullRequests" class="com.mycompany.example.plugin.fragment.MyRestFragment"/>
</atlassian-plugin>

and the corresponding implementation of the REST fragment.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class MyRestFragment implements RestFragment {

    @Nonnull
    @Override
    public Map<String, Object> validate(@Nonnull RestFragmentContext fragmentContext,
                                        @Nonnull Map<String, Object> requestContext) {
        if (fragmentContext.getMethod().equals("POST")) {
            // Validate request body for this fragment. If any fragment fails validation then no fragments will execute.
            // A request is still valid if it doesn't contain any information about this fragment, as it may be just
            // updating other fragments.

            // If the request was not valid, return the errors.
            // return new RestErrorMessage("myRestFragment", "Invalid request");
        }

        return new HashMap<String, Object>();
    }

    @Nonnull
    @Override
    public Map<String, Object> execute(@Nonnull RestFragmentContext fragmentContext,
                                       @Nonnull Map<String, Object> requestContext) {
        // The "bitbucket.repository.settings.pullRequests" location provides the context repository from the request.
        Repository repository = (Repository) requestContext.get("repository");

        // What the fragment does depends on the HTTP method of the request.
        String httpMethod = fragmentContext.getMethod();
        if (httpMethod.equals("GET")) {
            return doGet(repository);
        } else if (httpMethod.equals("POST")) {
            return doPost(fragmentContext, repository);
        }

        // Return a message indicating that the HTTP method is unsupported by this fragment. This is not an error,
        // because other fragments registered to the same endpoint may use this HTTP method. It is possible to return an
        // empty Map here, but specifically noting that the request had no effect on this fragment can be useful to
        // consumers of the endpoint.
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("WARNING-myInternalProjectTrackingDescription", "myRestFragment does not support the HTTP method " + httpMethod);
        return map;
    }

    private Map<String, Object> doGet(Repository repository) {
       // retrieve settings for this plugin
       return new HashMap<String, Object>();
    }

    private Map<String, Object> doPost(RestFragmentContext fragmentContext, Repository repository) {
        // update settings for this plugin
        return doGet(repository);
    }
}

See also the Auto Unapprove Pull Request plugin for an example of how to implement a REST fragment.