Create RESTful Web services with Java technology

JAX-RS: The easier, more pluggable alternative

JAX-RS (JSR-311) is a Java™ API that enables quick and easy development of Java RESTful services. The API provides an annotation-based model for describing distributed resources. Annotations are used to provide resource location, resource representation, and a pluggable data binding architecture. In this article, learn how you can use JAX-RS to realize the potential of a RESTful services architecture in a Java EE environment.

Dustin Amrhein, Software Engineer, IBM

Author photoDustin Amrhein is a software engineer working on the Web services support for WebSphere Application Server. He worked on the Web services runtime for both the Web Services Feature Pack for WebSphere Application Server 6.1 and WebSphere Application Server 7.0. He is a committer in the Apache Axis2 open source project. Dustin has been part of a team setting the direction for Java RESTful Web services support throughout IBM.


developerWorks Professional author
        level

Nick Gallardo, Software Engineer, IBM

Photo of Nick GallardoNick Gallardo is a software engineer in Austin, Texas. He has worked on various portions of the WebSphere Application Server dating back to version 5.0. Nick is a committer in the Apache Axis2 open source project and has been working on the REST support and JAX-RS for WebSphere.



23 February 2010

Also available in Chinese Russian Japanese

Introduction

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See Build RESTful web services with Java technology

JAX-RS (JSR-311) is a specification providing for RESTful services capability in a Java EE environment. It promises to give you a viable alternative to traditional, SOAP-based Web services.

In this article, learn about the major components of JAX-RS. An example illustrates how an enterprise exposes employee contact information in a RESTful manner using the facilities in JAX-RS.


Background

Developers have been creating RESTful services in their Java applications for years with a variety of tools. With the simplicity of a REST architecture, the main requirement—ability to receive an HTTP message and headers—can be served by a simple Java Web container.

Java servlets are commonly used to develop RESTful applications. There is no prescriptive pattern for using servlets. Usually, the servlet will accept the request and parse the HTTP request URI itself, looking to match the request to a known resource. For REST services development, the simple servlet model is extended in more formalized APIs. As APIs developed on top of the servlet model, though, none of them were developed as a formal standard.

With the growing adoption of REST as an architecture, the Java Community Process (JCP) sought to include formal support for REST in the upcoming Java Enterprise Edition 6 release. JSR-311 was created, and has produced the JAX-RS 1.0 specification, providing a new annotation-based approach to developing RESTful services. In contrast to the servlet model, JAX-RS annotations let you focus on your resources and data objects. And, you no longer have to develop the communication layer (via the servlet).


Java resources

JAX-RS establishes a vernacular to describe resources as represented by its programming model. There are five main items: root resources, subresources, resource methods, subresource methods, and subresource locators.

Root resources

Root resources are Java classes annotated with the @Path annotation. The @Path annotation provides a value attribute that indicates the path at which the resource is available. The value attribute may be literal characters, variables, or variables plus a customized regular expression. Listing 1 shows an example.

Listing 1. JAX-RS root resources
package com.ibm.jaxrs.sample.organization;

import javax.ws.rs.Path;

@Path(value="/contacts")
public class ContactsResource {
	...
}

Subresources

Subresources are Java classes returned as the result of a subresource locator invocation. They are similar to root resources, except they are not annotated with the @Path annotation since their path is described on the subresource locator. Subresources usually contain methods that are annotated with HTTP request method designators to serve the request. If they do not contain such annotated methods, they will further resolve the resource handling the request by delegating to the appropriate subresource locator.

Listing 2. JAX-RS subresources
package com.ibm.jaxrs.sample.organization;

import javax.ws.rs.GET;

public class Department {
	

	
	@GET
	public String getDepartmentName() {
		...
	}
	

	
}

Listing 2 above shows the subresource returned by the ContactsResource.getContactDepartment method. In this example, if an HTTP GET request were sent to the /contact/{contactName}/department path, the getDepartmentName resource method in the Department subresource would handle the request.

Resource methods

Resource methods are Java methods in a root resource or subresource that are bound to HTTP methods. The binding is done with an annotation such as the @GET annotation.

Listing 3. JAX-RS resource methods
package com.ibm.jaxrs.sample.organization;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path(value="/contacts")
public class ContactsResource {
	
	
	
	@GET
	public List<ContactInfo> getContacts() {
		...
	}
	

}

In the example in Listing 3, an HTTP GET request sent to the /contacts path would be handled by the getContacts() resource method.

Subresource methods

Subresource methods are very similar to resource methods; the only difference is that subresource methods are also annotated with an @Path annotation that further qualifies the selection of the method.

Listing 4. JAX-RS subresource methods
package com.ibm.jaxrs.sample.organization;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path(value="/contacts")
public class ContactsResource {
	
	@GET
	public List<ContactInfo> getContacts() {
		...
	}
	
	
	
	@GET
	@Path(value="/ids")
	public List<String> getContactIds() {
		...
	}
	

}

In Listing 4, an HTTP GET request sent to the /contacts/ids path would be handled by the getContactIds() subresource method.

Subresource locators

Subresource locators are methods that further resolve the resource that should handle a given request. They are like subresource methods in that they have an @Path annotation, but they do not have an HTTP request method designator, such as the @GET annotation.

Listing 5. JAX-RS subresource locators
package com.ibm.jaxrs.sample.organization;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path(value="/contacts")
public class ContactsResource {
	
	@GET
	public List<ContactInfo> getContactss() {
		...
	}
	
		@GET
	@Path(value="/ids")
	public List<String> getContactIds() {
		...
	}
	
	
	
	@Path(value="/contact/{contactName}/department")
	public Department getContactDepartment(@PathParam(value="contactName") 
		String contactName) {
		...
	}
	

}

In the example above, any HTTP request to the /contact/{contactName}/department path would be handled by the getContactDepartment subresource locator. The {contactName} part means that any legal URL value could follow the contact path part.


Annotations

This section takes a look at some of the prominent annotations and their uses. For a complete list of the annotations provided by the JAX-RS specification, see the JSR-311 link in the Resources section.

@Path

The @Path annotation is used to describe the location of a root resource, subresource method, or subresource. The value attribute can contain literal characters, variables, and variables with custom regular expressions. The example in Listing 6 shows the primary uses of the @Path annotation.

Listing 6. Uses of @Path
package com.ibm.jaxrs.sample.organization;

import java.util.List;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path(value="/contacts")
public class ContactsResource {

		
	@GET
	@Path(value="/{emailAddress:.+@.+\\.[a-z]+}")
	public ContactInfo getByEmailAddress(@PathParam(value="emailAddress") 
		String emailAddress) {
		...
	}
	
	@GET
	@Path(value="/{lastName}")
	public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) {
		...
	}
}

The annotation on the ContactsResource class indicates that all requests to the /contacts path will be handled by the ContactsResource root resource. The @Path annotation on the getByEmailAddress means that any request sent to /contacts/{emailAddress}, where emailAddress represents the regular expression .+@.+\\.[a-z]+, will be handled by the getByEmailAddress.

The @Path annotation on the getByLastName method specifies that all requests sent to the /contacts/{lastName} path, where lastName represents a valid URL part that does not match the regular expression in getByEmailAddress, will be handled by the getByLastName method.

@GET, @POST, @PUT, @DELETE, @HEAD

@GET, @POST, @PUT, @DELETE, and @HEAD are the HTTP request method designator annotations. You can use them to bind Java methods in a root resource or subresource to HTTP request methods. HTTP GET requests are mapped to methods annotated with @GET; HTTP POST requests are mapped to methods annotated with @POST; and so on. Users may also define their own custom HTTP request method designator annotations by using the @HttpMethod annotation.

Listing 7. Custom HTTP request method designator annotations
package com.ibm.jaxrs.sample.organization;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import javax.ws.rs.HttpMethod;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@HttpMethod("GET")
public @interface CustomGET {

}

The declaration above defines the @CustomGET annotation. This annotation will have the same semantic value as the @GET annotation and can be used in its place.

@Consumes and @Produces

The @Consumes annotation represents the MIME types that a resource accepts. The @Produces annotation represents the MIME types a resource returns. These annotations can be found on a resource, resource method, subresource method, subresource locator, or subresource.

Listing 8. @Consumes/@Produces
package com.ibm.jaxrs.sample.organization;

import java.util.List;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

@Path(value="/contacts")
public class ContactsResource {

		
	@GET
	@Path(value="/{emailAddress:.+@.+\\.[a-z]+}")
	@Produces(value={"text/xml", "application/json"})
	public ContactInfo getByEmailAddress(@PathParam(value="emailAddress") 
		String emailAddress) {
		...
	}
	
	@GET
	@Path(value="/{lastName}")
	@Produces(value="text/xml")
	public ContactInfo getByLastName(@PathParam(value="lastName") String lastName) {
		...
	}
	
	@POST
	@Consumes(value={"text/xml", "application/json"})
	public void addContactInfo(ContactInfo contactInfo) {
		...
	}
}

For the getByEmailAddress and the addContactInfo methods above, they both can handle text/xml and application/json. The resource representation that is accepted or returned will depend on HTTP request headers set by the client. The @Consumes annotation is matched against the Content-Type request header to determine if a method can accept the content of a given request.

In Listing 9, the Content-Type header of application/json, along with the POST to path /contacts, means the addContactInfo method in our ContactsResource class will be called to handle the request.

Listing 9. Usage of Content-Type header
POST /contacts HTTP/1.1
Content-Type: application/json
Content-Length: 32

Conversely, the @Produces annotation is matched against the Accept request header to determine if a client can handle the representation returned by a given method.

Listing 10. Usage of Accept header
GET /contacts/johndoe@us.ibm.com HTTP/1.1
Accept: application/json

In Listing 10, the GET request to /contacts/johndoe@us.ibm.com means the getByEmailAddress method will be called and the return format will be application/json, not text/xml.


Providers

JAX-RS providers are application components that allow for customization of runtime behavior in three key areas: data binding, exception mapping, and context resolution (for example, providing JAXBContext instances to the runtime). Each JAX-RS provider class must be annotated with the @Provider annotation. The example below discusses the data binding providers MessageBodyWriter and MessageBodyReader.

MessageBodyWriter

MessageBodyWriters are used by a JAX-RS runtime to serialize the representation of a returned resource. JSR-311 compliant runtimes provide native support for common types (java.lang.String, java.io.InputStream, JAXB objects, and so on), but a user can provide his or her own MessageBodyWriter to the JAX-RS runtime. For example, you can supply a custom MessageBodyWriter to handle the custom ContactInfo Java type, as shown below.

Listing 11. Custom MessageBodyWriter
package com.ibm.jaxrs.sample.organization;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;

@Provider
@Produces("text/xml")
public class ContactInfoWriter implements MessageBodyWriter<ContactInfo> {

	public long	getSize(T t, java.lang.Class<ContactInfo> type, 
		java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] 
		annotations, MediaType mediaType)  {
		...
	}
	
	public boolean isWriteable(java.lang.Class<ContactInfo> type, 
		java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] 
		annotations, MediaType mediaType) {
		return true;
	}
	
	public void writeTo(ContactInfo contactInfo, java.lang.Class<ContactInfo> type, 
		java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] 
		annotations, MediaType mediaType, MultivaluedMap<
		java.lang.String, java.lang.Object> httpHeaders, java.io.OutputStream 
		entityStream) {
		contactInfo.serialize(entityStream);
	}
}

The ContactInfoWriter will be called by the JAX-RS runtime prior to serialization of a returned resource representation. If the isWriteable returns true, and the @Produces is the closest match for the @Produces value of the resource method, the writeTo method will be called. At this point, the ContactInfoWriter is responsible for serializing the contents of the ContactInfo instance to the underlying OutputStream.

MessageBodyReader

MessageBodyReaders are the opposite of MessageBodyWriters. JAX-RS runtimes natively support the same types for deserialization as they do for serialization. A user can also supply his or her own MessageBodyReader implementation. The primary function of a MessageBodyReader is to read from a request InputStream and deserialize the incoming bytes into a Java object expected by the resource method. A MessageBodyReader for the ContactInfo type might look like Listing 12.

Listing 12. Custom MessageBodyReader
package com.ibm.jaxrs.sample.organization;

import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;

@Provider
@Consumes("text/xml")
public class ContactInfoReader implements MessageBodyReader<ContactInfo> {

	public boolean isReadable(java.lang.Class<ContactInfo> type, 
		java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] 
		annotations, MediaType mediaType) {
		return true;
	}
	
	public ContactInfo readFrom(java.lang.Class<ContactInfo> type, 
		java.lang.reflect.Type genericType, java.lang.annotation.Annotation[] 
		annotations, MediaType mediaType, MultivaluedMap<
		java.lang.String,java.lang.String> httpHeaders, java.io.InputStream 
		entityStream) {
		return ContactInfo.parse(entityStream);
	}
	
}

Similar to the MessageBodyWriter isWriteable, the isReadable method of the ContactInfoReader will be called to determine if the MessageBodyReader can handle the input. If the isReadable returns true, and the @Consumes value is the most compatible with the @Consumes value of the resource method, the ContactInfoReader will be chosen. When the readFrom method is called, the result will be the creation of a ContactInfo instance based on the request InputStream content.


Configuration

Thus far we've explored JAX-RS resource classes and a subset of the provider classes (MessageBodyReaders and MessageBodyWriters). Now, how are these classes configured within a JAX-RS runtime? It's achieved through the extension of the javax.ws.rs.core.Application class. This class provides a set of classes, or a set of singleton object instances, that include all of the root-level resources and providers (classes annotated with @Provider) in a JAX-RS application. If you were to extend the Application class for the example contact information application, it would look similar to Listing 13.

Listing 13. ContactInfoApplication
package com.ibm.jaxrs.sample.organization;

import java.util.HashSet;
import java.util.Set;
import javax.ws.rs.core.Application;

public class ContactInfoApplicaiton extends Application {

	public Set<Class<?>> getClasses() {
		Set<Class<?>> classes = new HashSetSet<Class<?>>();
		classes.add(ContactsResource.class);
		classes.add(ContactInfoWriter.class);
		classes.add(ContactInfoReader.class);
	}
	
	public SetSet<Object<?>> getSingletons() {
		// nothing to do, no singletons
	}
	
}

The getClasses method provides the JAX-RS runtime with a list of classes it should consider for metadata. Note that the getSingletons method returns nothing. Generally, it's okay to treat JAX-RS providers as singletons, but treating a JAX-RS resource as a singleton will require greater care. Annotation-based injection often used by JAX-RS resource classes may not be supported in the case of a singleton instance. Therefore, use of a singleton instance for JAX-RS resources should be avoided unless carefully planned.

Provided you're deploying your JAX-RS application within a servlet container, there are two main ways to register your javax.ws.rs.core.Application subclass with the JAX-RS runtime. This is handled with the web.xml of the WAR file, as shown below.

Listing 14. Non-JAX-RS aware servlet container
<web-app id="WebApp_ID" version="2.5"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi=
	"http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<servlet>
		<servlet-name>ContactInfoServlet</servlet-name>
		<servlet-class>com.sample.RESTSystemServlet</servlet-class>
		<init-param>
			<param-name>javax.ws.rs.Application</param-name>
			<param-value>
				com.ibm.jaxrs.sample.organization.ContactInfoApplication
			</param-value>
		</init-param>
	</servlet>
	<servlet-mapping>
		<servlet-name>ContactInfoServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

In a servlet container that's considered non-JAX-RS aware, the Application subclass name should be supplied as an init-param within the servlet definition. The name of the init-param must be javax.ws.rs.Application. The servlet-class will likely be the JAX-RS runtime system servlet. You can either list each possible URL pattern, or use the /* wild card registration as shown below.

Listing 15. JAX-RS aware servlet container
<web-app id="WebApp_ID" version="2.5"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi=
	"http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
	<servlet>
		<servlet-name>ContactInfoServlet</servlet-name>
		<servlet-class>
			com.ibm.jaxrs.sample.organization.ContactInfoApplication
		</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>ContactInfoServlet</servlet-name>
		<url-pattern>/*</url-pattern>
	</servlet-mapping>
</web-app>

In a servlet container that's considered JAX-RS aware, the Application subclass name can be supplied as the value of the servlet-class element within the servlet definition. You still have the option to list the URL patterns individually or use the /* wild card registration.


JAX-RS in action with Apache Wink

The next step is to find a runtime that supports the capabilities available in JAX-RS. The Apache Wink project provides a JAX-RS compliant runtime with all of the features described above (see Resources). Wink was started as a collaborative effort between various vendors and members of the open source community. The goal of the project is to provide the most flexible and lightweight runtime possible.

In addition to standard JAX-RS features, Wink also provides enhanced support for JSON, Atom, and RSS serialization formats. JAX-RS itself does not provide a client API, but Wink includes its own model for a client API that is completely resource-centric.

Join the Apache Wink group on My developerWorks

Discuss topics and share resources with other developers about developing with Apache Wink in the My developerWorks Apache Wink group.

Not a member of My developerWorks? Join now!

To simplify development of your Wink-based services, download the Wink 1.0 libraries and include them as the default JAX-RS library in your Rational Application Developer (RAD) 7.5.5 development environment (see Resources). In this update, RAD added a JAX-RS facet that you can configure to support validators and annotation assistance. This new facet also simplifies configuration of the servlet by automatically generating the necessary servlet entries and mappings.

Summary

Compared to the traditional servlet model, JAX-RS provides a viable, easier, more pluggable alternative to implementing RESTful services in Java. Using annotations lets you easily provide path locations for Java resources and bind Java methods to HTTP request methods. A pluggable data-binding architecture provides some native Java type support and allows full customization of the serialization/deserialization process. The extension of the javax.ws.rs.core. Application subclass, and the corresponding listing in the web.xml, mean easy deployment with minimal deployment descriptor configuration.

This article only touched upon some of the capabilities offered by JAX-RS. Two other JAX-RS provider types, ContextResolvers and ExceptionMappingProviders, give further control to application components in terms of providing application context (for example, JAXBContext instances) and mapping runtime exceptions to HTTP responses. Annotations are defined that govern injection of method parameters and class members, which provide valuable contextual information to applications during runtime. All in all, JAX-RS promises to be an easy, pluggable, and comprehensive API for developing Java-based RESTful services.

Resources

Learn

Get products and technologies

  • Apache Wink framework: Download the framework for building RESTful Web services.
  • IBM product evaluation versions: Download these versions today and get your hands on application development tools and middleware products from DB2®, Lotus®, Rational®, Tivoli®, and WebSphere®.

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Web development on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Web development, SOA and web services
ArticleID=469100
ArticleTitle=Create RESTful Web services with Java technology
publish-date=02232010