Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

What is the recommended way to send REST requests from a custom JIRA plugin?

Glenn Verrijkt December 15, 2014

Hello,

In my custom plugin I need to send REST requests to an external api (not jira).

JIRA already bundles jersey (version 1.0.2?) to allow you to add REST resources (endpoints) to your own plugin. It does not seem to include the jersey-client library though.

I've had some difficulties with dependency conflicts and JIRA's OSGI container before.

What is the recommended approach?

  • Should I add a dependency to jersey-client 1.0.2? This is quite old.
  • Is there another suitable client library?
  • Should I just stick with something basic that can send http requests and build my own rest client library on top of it?

Any help appreciated,

Glenn

2 answers

1 accepted

Comments for this post are closed

Community moderators have prevented the ability to post new answers.

Post a new question

7 votes
Answer accepted
Glenn Verrijkt December 21, 2014

Travis's answer is a starting point, but there is little documentation about all of this. I spend some time reading through the rest-api-module source code and tests and played with it for a bit. Here is some more useful info:

 

To make the requestFactory component available in your plugin, add this to your attlassian-plugin.xml:

<component-import key="requestFactory" interface="com.atlassian.sal.api.net.RequestFactory" />

 

In your rest client class, you then create a Request object:

Request request = requestFactory.createRequest(Request.MethodType.GET, URL_PATH_TO_YOUR_REST_RESOURCE);

 

The Request interface has several methods to execute your request:

/**
 * Executes the request.
 *
 * @param responseHandler Callback handler of the response.
 * @throws ResponseProtocolException If the server returned a malformed response
 * @throws ResponseTimeoutException If a connection timeout or read timeout occurred
 * @throws ResponseTransportException If an I/O error occurred in request transport
 * @throws ResponseException For all errors not otherwise specified
 */
void execute(ResponseHandler<RESP> responseHandler) throws ResponseException;

/**
 * Executes a request and if response is successful, returns response as a string. @see {@link Response#getResponseBodyAsString()}
 *
 * @return response as String
 * @throws ResponseStatusException If the server returned a response that contained an error code
 * @throws ResponseProtocolException If the server returned a malformed response
 * @throws ResponseTimeoutException If a connection timeout or read timeout occurred
 * @throws ResponseTransportException If an I/O error occurred in request transport
 * @throws ResponseException For all errors not otherwise specified
 */
String execute() throws ResponseException;

/**
 * Executes the request and returns a result value.
 *
 * @param responseHandler Callback handler of the response.
 * @throws ResponseProtocolException If the server returned a malformed response
 * @throws ResponseTimeoutException If a connection timeout or read timeout occurred
 * @throws ResponseTransportException If an I/O error occurred in request transport
 * @throws ResponseException For all errors not otherwise specified
 * @since   v2.2.0
 */
<RET> RET executeAndReturn(ReturningResponseHandler<RESP, RET> responseHandler) throws ResponseException;

 

If you want the reponse as a String, you can simply call request.execute(). However, if you want to leverage atlassian-rest-module's automatic unmarshalling of JAXB annotated entities, then you need to call request.executeAndReturn(ReturningResponseHandler<RESTP, RET> responseHandler).

Afaik, the SAL api does not provide an implementation of a ReturningResponseHandler, so you need to roll your own. For example:

public class MyReponseHandler&lt;RET&gt; implements ReturningResponseHandler&lt;Response, RET&gt; {

    private final Class&lt;RET&gt; entity;

    public MyReponseHandler(Class&lt;RET&gt; entity) {
        this.entity = entity;
    }

    @Override
    public RET handle(Response response) throws ResponseException {
        return response.getEntity(entity);
    }
}

 

Then in your rest client class, you can create an instance of your ReturningResponseHandler that is typed for your entity (in this example, the entity class is Hello, which contains JAXB annotations):

this.responseHandler = new MyReponseHandler(Hello.class);

and you can execute your request:

Hello hello = (Hello)request.executeAndReturn(responseHandler);

Note that you still have to cast the result to the correct type, but it wil unmarshal correctly. 

 

Hopefully this saves someone some time wink

Sparsh Gupta April 19, 2016

How to authenticate the REST call for the logged in user before sending them when I tried using addTrustedTokenAuthentication() function, i get this error saying "method lookup failed for selector". What can be the problem?

Florian Maupas February 19, 2018

I am trying to use the requestFactory, but I fail to properly instantiate it. The only example I find on Google are with Application Link ( to target Jira end point or confluence ).

 

Would someone a code snippet to properly instantiate it ? 

Ladislav Kšír February 20, 2018

@Florian Maupas
Working for me:



@Scanned
@Component
public class ARTService {

private final RequestFactory requestFactory;


@Inject
public ARTService(@ComponentImport RequestFactory requestFactory) {
this.requestFactory = requestFactory;
}
}

 

Florian Maupas February 22, 2018

@Ladislav Kšír Thanks a lot, I missed the dependency injection. 

1 vote
Travis Smith
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
December 18, 2014

Atlassian ships Shared Access Layer with all the products, guidance would to be leverage SAL's RequestFactory to handle remote communications, including REST calls. 

You are welcomed to try and bundle jersey-client as a private module for your add-on, but it's not impossible you will run into issues doing so. 

Sparsh Gupta April 19, 2016

How to authenticate the REST call for the logged in user before sending them when I tried using addTrustedTokenAuthentication() function, i get this error saying "method lookup failed for selector". What can be the problem?

TAGS
AUG Leaders

Atlassian Community Events