When JAX-RS 1.0 was first unveiled back in 2008 by JSR-311 spec leads Marc Hadley and Paul Sandoz, it became one of the first POJO/Annotation based frameworks for creating robust web-based applications.
Now five years later Java EE 7 has been released and it includes the latest JAX-RS version 2.0, the realization of JSR-339 led by Marek Potociar and Santiago Pericas-Geertsen. We will look at some of the features that make JAX-RS 2.0 worth the upgrade, but first let's take a quick refresher view of JAX-RS 1.0.
1 @Path(portfolios) 2 public class PortfolioResource { 3 4 @GET 5 public Collection<Portfolio> allPortfolios() { 6 . . . 7 } 8 9 @GET 10 public Portfolio getPortfolio( @PathParam("portfolioId") String id) { 11 . . . 12 } 13 }
In the above listing, line 1 says to map this resource to the relative path /portfolios. Line 4 says that a GET request should return all portfolios. Lines 9 & 10 indicate that a GET request with, for example, URI /portfolios/123 should extract the parameter (e.g. 123) following the resource URI (e.g. portfolios), and assign it to the variable "id", then return the associated portfolio.
That syntax remains in JAX-RS 2.0.
Consistent with the central theme of Java EE 7, JAX-RS 2.0 adds some long awaited features mostly focused around what Oracle calls its "simplified API".
These features can be categorized as:
- Client API
- Async
- HATEOAS (Hypermedia)
- Annotations
- Validation
- Filters and Handlers
- Content negotiation
We will take a quick look at each of these categories:
Client API
JAX-RS 1.0 was strictly a server side API. Some implementations provided varying degrees of client support but generally the developer was left to install something ad-hoc like the Apache Software Foundation's Jakarta Commons HttpClient or WizTools REST Client.
JAX-RS 2.0 adds "builder" tools for calling a web service from the client. Here is a sample:
Client client=ClientFactory.newClient(); String shares=client.target("http://.../portfolio/123") .pathParam("identifier", "IBM") .queryParameter("identifierType", "ticker") .request("text/plain).get(String.class");
You can see that this method first obtains a client, and then uses the builder pattern to construct all of the parameters of the URL, allowing the application developer to formulate the URL without dealing with the vagaries of the URL construction.
This approach is especially useful for calls with an HTTP body, such as HTTP POST and HTTP PUT. The following example allows the application to sell 100 shares of IBM:
Stock stock=client.target("http://.../portfolio/123/sell") .pathParam("identifier", "IBM") .queryParameter("identifier", "ticker") .request("application/json") .post(text("100", Shares.class));
Async
In JAX-RS 1.0, a calling client had to wait for the response from the server. 2.0 introduces asynchronous support. This allows a client to make a RESTful call, and optionally get a Future or an InvocationCallback to be notified when the response is complete.
HATEOAS (Hypermedia)
According to strict RESTafarian Orthodoxy if you are not using HATEOAS you are not doing REST! HATEOAS (Hypermedia as the Engine of Application State) requires the RESTful producers and consumers to agree on a set of links to be returned in each call, for navigating to the next step. If you think of REST as an application version of a web page, then HATEOAS can be thought of as the links within a web page.
JAX-RS 2.0 provides Link and Target classes for introducing hyperlinks into a response on the server side and reacting to them on the client.
Annotations
New annotations have been introduced, for example to support new injections.
Bean Validation
An annotation-based facility for specifying parameter meta-data. For example "@NotNull shares" indicates that the "shares" parameter may not be null. You can also supply custom annotation for example to ensure certain data formats such as a zip code or phone number.
Filters and Handlers
The Filters API provides the ability to chain servlet filters in a chain of responsibility pattern. This is useful for introducing orthogonal concerns such as logging. Any filter can decide to continue or terminate the chain by calling FilterAction.NEXT or FilterAction.STOP respectively.
Handlers are similar to Filters except they wrap a method invocation at a specified extension point. This is useful for intercepting calls at that extension point, for example to massage or enrich the payload data.
Content negotiation
Richer annotations for @Accepts and @Produces parameters allow you to prioritize request/response formats.
JAX-RS is still missing a good security model, which makes it difficult to use in an external facing enterprise application. We hope the next release will provide support for point to point authentication.
It may be some time before the main JEE containers provide support for JAX-RS 2.0. Meanwhile you can take advantage immediately by deploying the latest version of Jersey with your application. Oracle has published steps for doing so in WebLogic 12c.
For more information, please see the OTN article Java EE 7 and JAX-RS 2.0 by JSR 339 expert group member Adam Bien