JBoss.orgCommunity Documentation

Chapter 7. Errai JAX-RS

7.1. Getting Started
7.1.1. Dependencies
7.1.2. GWT Module
7.1.3. Server-Side JAX-RS Implementation
7.1.4. Shared JAX-RS Interface
7.2. Creating Requests
7.2.1. Proxy Injection
7.3. Handling Responses
7.4. Client-side Interceptors
7.5. Wire Format
7.6. Configuration
7.6.1. Configuring the default root path of JAX-RS endpoints
7.6.2. Enabling Jackson marshalling

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:

If you want to get started right away with a working Errai JAX-RS CRUD application, you can use our jaxrs-quickstart Maven archetype. See the Quickstart Guide for details. If you want to set up a project from scratch see the next chapter.

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 Chapter 5, Marshalling ).



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

A special case of this RemoteCallback is the ResponseCallback which can be used as an alternative. It provides access to the Response object representing the underlying HTTP response. This is useful when more details of the HTTP response are needed, such as headers and the status code. The ResponseCallback can also be used for JAX-RS interface methods that return a javax.ws.rs.core.Response type. In this case, the MarshallingWrapper class can be used to manually demarshall the response body to an entity of the desired type.



ResponseCallback callback = new ResponseCallback() {
  public void callback(Response response) {
    Window.alert("HTTP status code: " + response.getStatusCode());
    Window.alert("HTTP response body: " + 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;
  }
};

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:

To have a JAX-RS remote call intercepted, either an interface method or the remote interface type has to be annotated with @InterceptedCall . If the type is annotated, all interface methods will be intercepted.

Note that an ordered list of interceptors can be used for specifying an interceptor chain e.g.

Implementing an interceptor is easy:

The RestCallContext passed to the aroundInvoke method provides access to the context of the intercepted JAX-RS (REST) remote call. It allows to read and write the parameter values provided at the call site and provides read/write access to the RequestBuilder instance which has the URL, HTTP headers and parameters set.

Calling proceed executes the next interceptor in the chain or the actual remote call if all interceptors have already been executed. If access to the result of the (asynchronous) remote call is needed in the interceptor, one of the overloaded versions of proceed accepting a RemoteCallback has to be used instead.

The result of the remote call can be manipulated by calling RestCallContext.setResult() .

Not calling proceed in the interceptor bypasses the actual remote call, passing RestCallContext.getResult() to the RemoteCallBack provided at the call site.

Errai's JSON format will be used to serialize/deserialize your custom types. See Chapter 5, 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.