JBoss.orgCommunity Documentation

Chapter 7. Errai JAX-RS

7.1. Server-Side JAX-RS Implementation
7.2. Shared JAX-RS Interface
7.3. Creating Requests
7.3.1. Proxy Injection
7.4. Handling Responses
7.4.1. Handling Errors
7.5. Accesssing and aborting requests
7.6. Client-side Interceptors
7.6.1. Annotating the JAX-RS Interface
7.6.2. Implementing an Interceptor
7.6.3. Annotating the Interceptor (alternative)
7.6.4. Interceptors and IOC
7.7. Wire Format
7.8. Path
7.9. CSRF Protection

JAX-RS (Java API for RESTful Web Services) is a Java EE standard (JSR-311) for implementing REST-based Web services in Java. Errai JAX-RS brings this standard to the browser and simplifies the integration of REST-based services in GWT client applications. Errai can generate proxies based on JAX-RS interfaces which will handle all the underlying communication and serialization logic. All that’s left to do is to invoke a Java method.

Errai’s JAX-RS support consists of the following:

Manual Setup

Checkout the Manual Setup Section for instructions on how to manually add JAX-RS to your project. You can also go to the Errai tutorial project or the demo collection for an example of JAX-RS.

Errai’s JAX-RS support consists mostly of features that make the client side easier and more reliable to maintain. You will need to use an existing third-party JAX-RS implementation on the server side. All Java EE 6 application servers include such a module out-of-the-box. If you are developing an application that you intend to deploy on a plain servlet container, you will have to choose a JAX-RS implementation (for example, RestEasy) and configure it properly in your web.xml.

Alternatively, you could keep your REST resource layer in a completely separate web application hosted on the same server (perhaps build an Errai JAX-RS client against an existing REST service you developed previously). In this case, you could factor out the shared JAX-RS interface into a shared library, leaving the implementation in the non-Errai application.

Finally, you can take advantage of the cross-origin resource sharing (CoRS) feature in modern browsers and use Errai JAX-RS to send requests to a third-party server. The third-party server would have to be configured to allow cross-domain requests. In this case, you would write a JAX-RS-Annotated interface describing the remote REST resources, but you would not create an implementation of that interface.

Errai JAX-RS works by leveraging standard Java interfaces that bear JAX-RS annotations. You will also want these interfaces visible to server-side code so that your JAX-RS resource classes can implement them (and inherit the annotations). This keeps the whole setup typesafe, and reduces duplication to the bare minimum. The natural solution, then is to put the JAX-RS interfaces under the client.shared package within your GWT module:

The contents of the server-side files would be as follows:


The above interface is visible both to server-side code and to client-side code. It is used by client-side code to describe the available operations, their parameter types, and their return types. If you use your IDE’s refactoring tools to modify this interface, both the server-side and client-side code will be updated automatically.


The above class implements the shared interface. Since it performs database and/or filesystem operations to manipulate the persistent data store, it is not GWT translatable, and it’s therefore kept in a package that is not part of the GWT module.

Save typing and reduce duplication

Note that all JAX-RS annotations (@Path, @GET, @Consumes, and so on) can be inherited from the interface. You do not need to repeat these annotations in your resource implementation classes.

This section assumes you have already set up the CustomerService JAX-RS endpoint as described in the previous section.

To create a request on the client, all that needs to be done is to invoke RestClient.create(), thereby providing the JAX-RS interface, a response callback and to invoke the corresponding interface method:


For details on the callback mechanism see Handling Responses.

An instance of Errai’s RemoteCallback<T> has to be passed to the RestClient.create() call, which will provide access to the JAX-RS resource method’s result. T is the return type of the JAX-RS resource method. In the example below it’s just a Long representing a customer ID, but it can be any serializable type (see Marshalling).

RemoteCallback<Long> callback = new RemoteCallback<Long>() {

  public void callback(Long id) {
    Window.alert("Customer created with ID: " + id);
  }
};

One special use case for the RemoteCallback is for JAX-RS interface methods that return a javax.ws.rs.core.Response type. Errai does not provide a client implementation of the javax.ws.rs.core.Response class. Instead calls to methods returning a javax.ws.rs.core.Response should use a RemoteCallback<com.google.gwt.http.client.Response>. The MarshallingWrapper class can be used to manually deserialize an entity from the body of a response.

RemoteCallback<Response> callback = new RemoteCallback<Response>() {

  public void callback(Response response) {
    Window.alert("HTTP status code: " + response.getStatusCode());
    Window.alert("HTTP response body: " + response.getText());
    Window.alert("Demarshalled entity: " + MasrhallingWrapper.fromJSON(response.getText()));
  }
};

For handling errors, Errai’s error callback mechanism can be reused and an instance of ErrorCallback can optionally be passed to the RestClient.create() call. In case of an HTTP error, the ResponseException provides access to the Response object. All other Throwables indicate a communication problem.

ErrorCallback errorCallback = new RestErrorCallback() {

  public boolean error(Request request, Throwable throwable) {
    try {
      throw throwable;
    }
    catch (ResponseException e) {
      Response response = e.getResponse();
      // process unexpected response
      response.getStatusCode();
    }
    catch (Throwable t) {
      // process unexpected error (e.g. a network problem)
    }
    return false;
  }
};

To provide more customized error handling, Errai also defines client side exception handling via the ClientExceptionMapper interface. The client exception mapper allows developers to process a REST Response into a Throwable prior to the error being delivered to the ErrorCallback described above. The exception mapper class must be annotated with javax.ws.rs.ext.Provider as well as implement the ClientExceptionMapper interface.

@Provider

public class MyAppExceptionMapper implements ClientExceptionMapper {
  /**
   * @see org.jboss.errai.enterprise.client.jaxrs.ClientExceptionMapper#fromResponse(com.google.gwt.http.client.Response)
   */
  @Override
  public Throwable fromResponse(Response response) {
    if (response.getStatusCode() == 404)
      return new MyAppNotFoundException();
    else
      return new MyAppServerError(response.getStatusText());
  }
}

The ClientExceptionMapper will, by default, be invoked for every error response. However, Errai also provides the org.jboss.errai.enterprise.shared.api.annotations.MapsFrom annotation which provides for additional granularity. An exception mapper can be annotated so that it is only invoked for methods on specific REST interfaces.

@Provider

@MapsFrom({ SomeRestInterface.class })
public class SpecificClientExceptionMapper implements ClientExceptionMapper {
  /**
   * @see org.jboss.errai.enterprise.client.jaxrs.ClientExceptionMapper#fromResponse(com.google.gwt.http.client.Response)
   */
  @Override
  public Throwable fromResponse(Response response) {
     ... // Do something specific here
  }
}

An instance of Errai’s RequestCallback can optionally be passed to the RestClient.create() call, which will provide access to the underlying HTTP request. The callback is invoked synchronously after the HTTP request has been initiated. This means that you will have access to the request immediately after the call.

RequestCallback requestCallback = new RequestCallback() {

  @Override
  public void callback(Request request) {
    this.request = request;
  }
};
RestClient.create(SearchService.class, callback, requestCallback).find(query);

This allows you to cancel a pending request. Alternatively, a RequestHolder can be used instead.

RequestHolder searchRequestHolder = new RequestHolder();

RestClient.create(SearchService.class, callback, searchRequestHolder).find(query);
...
if (searchRequestHolder.isAlive()) {
  searchRequestHolder.getRequest().cancel();
}

Client-side remote call interceptors provide the ability to manipulate or bypass the request before it’s being sent. This is useful for implementing crosscutting concerns like caching or security features e.g:

Errai’s JSON format will be used to serialize/deserialize your custom types. See Marshalling for details.

Alternatively, a Jackson compatible JSON format can be used on the wire. See Configuration for details on how to enable Jackson marshalling.

All paths specified using the @Path annotation on JAX-RS interfaces are by definition relative paths. Therefore, by default, it is assumed that the JAX-RS endpoints can be found at the specified paths relative to the GWT client application’s context path.

Errai provides a filter for protecting REST endpoints from Cross Site Request Forgery (CSRF) attacks. The filter org.jboss.errai.bus.server.servlet.CSRFTokenFilter generates a CSRF token for every HTTP session that is required as an HTTP header for all POST, PUT, and DELETE requests. Requests made with an Errai Caller<T> will automatically negotiate for a CSRF token, or the same filter can be added to the host page, where it will inject the token onto the page as a JavaScript variable.