Thursday, August 26, 2010

Java API for RESTful Web Services (JAX-RS)

Java API for RESTful Web Services (JAX-RS), JSR 311 enables you to rapidly build lightweight web services that conform to the Representational State Transfer (REST) style of software architecture. An important concept in REST is the existence of resources, each of which can be referred to with a global identifier, that is, a URI. In particular, data and functionality are considered resources that can be identified and accessed through URIs. To manipulate these resources, components of the network, clients and servers, communicate through a standardized interface such as HTTP and a small, fixed set of verbs — GET, PUT, POST, and DELETE — and exchange representations of these resources.

RESTful web services are web services built according to the REST architectural style. Building web services with the RESTful approach has emerged as a popular alternative to using SOAP-based technologies thanks to REST's lightweight nature and the ability to transmit data directly over HTTP.

JAX-RS furnishes a standardized API for building RESTful web services in Java. The API contributes a set of annotations and associated classes and interfaces. Applying the annotations to POJOs enables you to expose web resources. This approach makes it simple to create RESTful web services in Java.

JAX-RS makes it simple to create RESTful web services in Java.

The specification for the initial release of the technology, JAX-RS 1.0, was finalized in October 2008 and a reference implementation named Jersey is also available. Java EE 6 includes the latest release of the technology, JAX-RS 1.1, which is a maintenance release that aligns JAX-RS with new features in Java EE 6.

Let's take a look at a RESTful web service that uses JAX-RS.

import javax.ws.rs.Path;

import javax.ws.rs.Produces;

import javax.ws.rs.Get;

import javax.ws.rs.Post;

import javax.ws.rs.Consumes;

import javax.ws.rs.core.Response;

import javax.ws.rs.core.MediaType;

import javax.ws.rs.core UriInfo;

import javax.ws.rs.core.UriBuilder;

import java.net.URI;

@Path ("items")

@Produces (MediaType.APPLICATION_XML)

Public class ItemsResource {

@Context UriInfo uriInfo;

@GET

Items listItems() {

Return Allitems();

}

@POST

@Consumes (MediaType.APPLICATION_XML)

Public Response create(Item item) throws ItemCreationException {

Item newItem = createItem(item);

URI newItemURI = uriInfo.getRequestUriBuilder().path(newItem.getId()).build();

return Response.created(newItemURI).build();

}

...

}



In this example, the ItemsResource class is a web service that manages a set of items. The imports in the class are for JAX-RS 1.1 annotations, classes, and interfaces.

The @Path annotation specifies a relative path for the resource, in this case "items". The URI for the class resource is based on the application context. So if the application context for this example ishttp://example.com, the URI for the class resource ishttp://example.com/items. This means that if a client directs a request to the URIhttp://example.com/items, the ItemsResource class will serve it.

The @GET annotation specifies that the annotated method, here the listItems() method, handles HTTP GET requests. When a client directs an HTTP GET request to the URI for the ItemsResource resource, the JAX-RS runtime invokes the listItems() method to handle the GET request.

Notice the @Produces annotation. It specifies the MIME media types that the methods in the resource can produce and return to the client. In the ItemsResource example, the @Produces annotation specifies MediaType.APPLICATION_XML. The MediaType class is an abstraction of a MIME media type. Constants supplied to the class identify the particular media type to be abstracted. TheMediaType.APPLICATION_XML specification is an abstraction of the MIME media type for XML content, "application/xml".

Annotations such as @Produces suggest some of the content type translation that JAX-RS handles automatically. For example, thelistItems() method returns a Java object of type Items. JAX-RS automatically translates that Java type to the "application/xml" MIME type to be used in the HTTP response to the client. Note that the translation is automatic only if the returned type is supported by default. For instance, if Items is a JAXB-annotated bean, then the translation would be automatic. However, if Items is a POJO, you would need to implement a MessageBodyReader to handle the serialization.

You can also specify a @Produces annotation on a method. In that case, the MIME type you specify on the method overrides the MIME types in any @Produces annotation that you specify on the class. For example, you could specify a @Produces annotation for the listItems() method as follows:

@GET

@Produces (MediaType.TEXT_PLAIN)

Items listItems() {

Return Allitems();

}



JAX-RS would then translate the Items Java type to the "text/plain" MIME type, which represents plain text, and return content of that type in the HTTP response to the client.

The @POST annotation specifies that the annotated method, in this case, the create() method, responds to HTTP POST requests. In this example, the method creates a new item, perhaps in a database, and then returns a response indicating that it created the new item. When a client directs an HTTP POST request to the URI for the ItemsResource resource, the JAX-RS runtime invokes thecreate() method to handle the POST request.

Notice that the @Consumes annotation is specified on the create() method. The annotation specifies the MIME media types that the methods in the resource can accept from the client. As is the case for the @Produces annotation, if you specify @Consumes on a class, it applies to all the methods in the class. If you specify @Consumes on a method, it overrides the MIME type in any @Consumesannotation that you specify for the class. In the example, the @Consumes annotation specifies that thecreate() method can accept XML content, that is, the MIME type "application/xml". Here the type translation is from MIME type to Java type. When a client submits XML content in a POST request to the URI for the ItemsResource class, JAX-RS invokes the create() method and automatically translates the incoming XML to the Item Java type required for the method's argument.

JAX-RS also includes a number of utility classes and interfaces that further simplify actions related to building and using RESTful web services in Java. You've already seen one of them: MediaType, a class for abstracting MIME media types. Some others are:

· UriInfo, an interface for accessing URI information. In this example, the @Context annotation injects the UriInfo interface into the uriInfo field of the ItemsResource class.

· UriBuilder, a class for building URIs from their components

· Response, a class represents an HTTP response

· Response.ResponseBuilder, a class that builds Response objects, in accordance with the well-known Builder Pattern

These classes and interfaces are used in the following statements in the example:

URI newItemURI = uriInfo.getRequestUriBuilder().path(newItem.getId()).build();

return Response.created(newItemURI).build();



The first statement builds a URI for the new item. The getRequestUriBuilder() method is aUriInfo method that creates a UriBuilder object. The path() and build() methods areUriBuilder methods that together construct the URI for the new item.

The second statement creates a Response object for the new item to be returned to the client. Thecreated method is a Response method that creates a Response.ResponseBuilder object. Thebuild() method is a Response.ResponseBuilder method that creates the Response object for the new item. This object delivers metadata to the JAX-RS runtime to construct the HTTP response.

These utility classes and interfaces hide a lot of the complexity of HTTP programming — another reason why using JAX-RS is a simple way to build RESTful web services. However, this simplicity also extends beyond web services. JAX-RS can simplify the development of many types of HTTP-aware web applications. For example, if you need to build a web application that examines HTTP headers, you can probably code it in a much simpler way by using JAX-RS rather than other approaches.

JAX-RS has other convenient features. For example, JAX-RS includes a number of parameter-based annotations to extract information from a request. One of these is @QueryParam, with which you can extract query parameters from the Query component of a request URL. Some other parameter-based annotations are @MatrixParam, which extracts information from URL path segments,@HeaderParam, which extracts information from HTTP headers, and @CookieParam which extracts information from the cookies declared in cookie-related HTTP headers.


No comments:

Post a Comment