Brief introduction
Jax-rs (JSR-311) is a specification for RESTful service capabilities in a Java EE environment. It can provide a viable alternative to traditional SOAP-based Web services.
In this article, learn about the main components of Jax-rs. This article shows an example of how an enterprise can use features within JAX-RS to expose employee contact information in a Restful way.
Background
Over the years, developers have used various tools to create RESTful services within their Java applications. Because of the simplicity of the REST architecture, the primary requirement-the ability to receive HTTP messages and headers-can be implemented by a simple Java Web container.
Java Servlets is often used to develop RESTful applications. There is no fixed pattern for how to use Servlets. Typically, the servlet accepts the request and resolves the HTTP request URI itself to match the request to a known resource. For REST service development, this simple servlet model is extended with a more formal API. However, because these APIs were developed on top of the servlet model, none of these APIs was developed as a formal standard.
As rest is increasingly being adopted as an architecture, Java Community Process (JCP) plans to include formal support for rest in the future Java Enterprise Edition 6 release. JSR-311 has also been created and has the JAX-RS 1.0 specification, providing a new annotation-based approach to developing RESTful services. Jax-rs annotations allow you to focus on your resources and data objects compared to the servlet model. Also, you no longer have to develop the communication layer (via servlet).
Java Resources
Jax-rs has created a special language to describe resources, as represented by its programming model. There are five main entries: the root resource, the child resource, the resource method, the child resource method, and the child resource Locator.
Root Resource
The root resource is a @Path
Java class that is annotated by. The @Path
comment provides a value
property that indicates the path to which this resource resides. A value
property can be a literal character, a variable, or a variable plus a custom 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 {...} |
Child Resources
The child resource is the Java class returned as a result of the Subresource locator call. They are similar to root resources, except that they @Path
are not annotated because their paths are given by the child resource Locator. A child resource typically contains methods that are annotated by the HTTP request method designator (designator) to serve this request. If they do not contain such annotated methods, they will further resolve this resource processing request by assigning it to the appropriate child resource locator.
Listing 2. Jax-rs Child Resources
Package Com.ibm.jaxrs.sample.organization;import Javax.ws.rs.get;public class Department {@GETpublic String Getdepartmentname () {...}} |
Listing 2, shown above, shows the ContactsResource.getContactDepartment
child resources returned by the method. In this example, if an HTTP GET request is sent to the /contact/{contactName}/department
path, the Department
resource method within the child resource getDepartmentName
processes the request.
Resource methods
A resource method is a Java method that is bound to an HTTP method within a root resource or child resource. Bindings are done through @GET
annotations such as this.
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 {@GETpublic list<contactinfo> getcontacts () {...}} |
In the example in Listing 3, the /contacts
HTTP GET request sent to the path will be getContacts()
processed by the resource method.
Child resource Methods
The child resource method is very similar to a resource method; the only difference is that the child resource method is also @Path
annotated, and this comment further qualifies the method's selection.
Listing 4. Jax-rs Child Resource Method
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 {@GETpublic list<contactinfo> getcontacts () {...} @GET @path (value= "/ids") public list<string> Getcontactids () {...}} |
In Listing 4, the /contacts/ids
HTTP GET request sent to the path will be processed by the getContactIds()
child resource method.
Sub-Resource Locator
A child resource locator is some way to further parse the resources used to process a given request. They are very similar to child resource methods because they have a @Path
comment but do not have an HTTP request method indicator, such as a @GET
comment.
Listing 5. Jax-rs Sub-Resource Locator
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 {@GETpublic 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 above example, /contact/{contactName}/department
any HTTP request to the path will be processed by the getContactDepartment
child Resource Locator. {contactName}
section indicates that contact
the path section can then be any valid URL value.
Comments
This section will explore some important annotations and their use. For a complete list of annotations provided by the JAX-RS specification, you can refer to the JSR-311 link given in the Resources section of this article.
@Path
@Path
Annotations are used to describe the location of a root resource, a child resource method, or a child resource. value
values can contain text characters, variables, or variables that have custom regular expressions. The example in Listing 6 shows the @Path
main application of annotations.
Listing 6. Use 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:[email protected]+\\. [a-z]+}] public contactinfo getbyemailaddress (@PathParam (value= "EmailAddress") String EmailAddress) {...} @GET @path (value= "/{lastname}") Public ContactInfo Getbylastname (@PathParam (value= "LastName") String lastName) {...}} |
ContactsResource
The comment on the class indicates that /contacts
all requests to the path will be processed by the ContactsResource
root resource. getByEmailAddress
the @Path
comment on indicates that any request sent to /contacts/{emailAddress}
(which emailAddress
represents a regular expression [email protected]+\\.[a-z]+
) will be processed by the getByEmailAddress
.
getByLastName
The comment on the method @Path
specifies that all requests sent to the /contacts/{lastName}
path (which lastName
represent a getByEmailAddress
valid URL part that does not match the inside regular expression) will be processed by the getByLastName
method.
@GET, @POST, @PUT, @DELETE, @HEAD
@GET, @POST, @PUT, @DELETE, and @HEAD are all HTTP Request method indicator comments. You can use them to bind Java methods and HTTP request methods within a root resource or child resource. HTTP GET requests are mapped to methods that are annotated by @GET, HTTP POST requests are mapped to methods that are annotated by @POST, and so on. Users may also need to @HttpMethod
define their own custom HTTP request method indicators by using annotations.
Listing 7. Custom HTTP Request Method Indicator comments
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 a @CustomGET
comment. This comment will have the same semantic value as the @GET annotation and can be used in its place.
@Conumes and @Produces
@Consumes
The comment represents a MIME type that a resource can accept. @Produces
the comment represents a MIME type that a resource can return. These annotations can be found within a resource, resource method, child resource method, sub-resource locator, or sub-resource.
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:[email protected]+\\.[ 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 above getByEmailAddress
and the addContactInfo
methods, they can be processed text/xml
and application/json
. The received or returned resource representation will depend on the HTTP request header set by the client. @Consumes
the comment Content-Type
matches the request header to determine whether the method can accept the contents of a given request.
In Listing 9, application/json
the Content-Type
header plus the POST to the path /contacts
indicates that the ContactsResource
method within our class addContactInfo
will be called to process the request.
Listing 9. Use of Content-type Head
Post/contacts http/1.1content-type:application/jsoncontent-length:32 |
Instead, the @Produces
comment is matched against the Accept
request header to determine whether the client can handle the representation returned by the given method.
Listing 10. Use of the Accept head
Get/contacts/[email protected] Http/1.1accept:application/json |
In Listing 10, the request to/contacts/[email protected] indicates that the method will be GET
getByEmailAddress
called and the returned format will be application/json
, not text/xml.
Providers
JAX-RS providers are application components that allow customization of runtime behavior in three key areas: data binding, exception mapping, and context resolution (for example, providing a Jaxbcontext instance to the runtime). Each JAX-RS provider class must be @Provider
commented by. The following example discusses two data binding providers MessageBodyWriter
and MessageBodyReader
.
Messagebodywriter
Messagebodywriters is used by the JAX-RS runtime to serialize the representation of the returned resource. The JSR-311-compliant runtime provides native support for common types (java.lang.String, Java.io.InputStream, JAXB objects, and so on), but users can also provide the Jax-rs runtime with his or her own Messagebodywriter. For example, you can provide a customization MessageBodyWriter
to handle a 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 longgetsize (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);}} |
ContactInfoWriter
Called by the Jax-rs runtime before the returned resource representation is serialized. If it isWriteable
returns True and @Produces
is the closest match to the value of this resource method @Produces
, the writeTo
method is called. Here, you are ContactInfoWriter
responsible for serializing the contents of the instance to the underlying OutputStream
ContactInfo
.
Messagebodyreader
Messagebodyreaders is the opposite of messagebodywriters. For deserialization, the JAX-RS runtime supports the same type as serialization. The user can also provide his or her own messagebodyreader implementation. The primary function of the messagebodyreader is to read the request InputStream
and deserialize the incoming bytes into a Java object expected by this resource method. ContactInfo
the type MessageBodyReader
can be similar to listing 12.
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);}}
isWriteable
a method similar to ContactInfoReader
Messagebodywriter isReadable
will be called to determine whether Messagebodyreader can handle this input. If isReadable
true is returned and the @Consumes
value matches the value of this resource method @Consumes
, it is selected ContactInfoReader
. When the readFrom
method is called, the result is an InputStream
instance created based on the requested content ContactInfo
.
Configuration
At this point, we explored the Jax-rs resource class and some provider classes (Messagebodyreaders and messagebodywriters). So, how do you configure these classes within the Jax-rs runtime? This can be achieved by extending the Javax.ws.rs.core.Application class. This class provides a set of classes or a set of singleton (Singleton) object instances, including all root-level resources and providers (by @Provider
the annotated Class) within a JAX-RS application. If you extend this application class for this example contact information application, it should look like 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}} |
getClasses
The Jax-rs method provides a set of classes available to the runtime for metadata. Notice that the getSingletons
method does not return anything. In general, it is no problem to treat a jax-rs provider as a singleton, but it is prudent to treat a jax-rs resource as a singleton. Note-based injection, which is often used by the Jax-rs resource class, may not be supported in the case of a singleton instance. Therefore, you should avoid using singleton instances of JAX-RS resources unless you plan carefully.
Assuming that you are deploying a JAX-RS application within a servlet container, there are two ways to register your javax.ws.rs.core.Application subclass with the Jax-rs runtime. This is handled by the Web. XML of the WAR file, as shown below.
Listing 14. A servlet container that cannot perceive jax-rs
<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> |
Within a servlet container that is considered Jax-rs-aware, the application subclass name should be provided as init-param within the servlet definition. The name of the Init-param must be javax.ws.rs.Application. The Servlet class is most likely the Jax-rs runtime system servlet. You can list each of the possible URL patterns, or use /*
wildcards to register as shown below.
Listing 15. A servlet container that can perceive jax-rs
<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> |
Within a servlet container that is considered to be capable of perceiving jax-rs, the application subclass name must be provided as the value of the servlet class element within the servlet definition. You can still choose whether to list each possible URL pattern or use a /*
wildcard character to register.
Using Apache Wink as the runtime Jax-rs
The next step is to find a runtime that supports the available features within the JAX-RS. The Apache Wink Project provides a runtime that satisfies this requirement, with all of the features described above (see Resources). Initially, Wink was a collaborative project initiated by multiple vendors and members of the open source community. The goal of the project is to provide the most flexible and lightweight runtime.
In addition to the standard Jax-rs features, Wink also provides enhanced support for JSON, Atom, and RSS serialization formats. The JAX-RS itself does not provide the client API, but Wink includes its own model of the client API and is completely resource-centric.
To simplify the development of Wink-based services, you can download Wink 1.0 libraries and include them as the default Jax-rs libraries into the Rational application Developer (RAD) 7.5.5 development environment (see Resources). In this updated version, RAD adds a jax-rs facet that you can configure to support validators and annotation help. This new facet also simplifies the configuration of the servlet by automatically generating the required servlet entries and mappings.
Conclusion
Compared to the traditional servlet model, JAX-RS provides a viable, simpler, and more portable way to implement RESTful services within Java. Using annotations allows you to easily provide path locations for Java resources and bind Java methods to HTTP request methods. A portable data-binding architecture provides some native Java type support and allows for full customization of serialization/deserialization processing. The extension of the Javax.ws.rs.core. Application subclass and the corresponding inventory within Web. XML indicate that a minimal deployment descriptor configuration makes it easy to deploy.
This article only covers part of the functionality that JAX-RS can provide. The other two Jax-rs provider types ContextResolvers
and ExceptionMappingProviders
also provide further control over the application components, in terms of providing an application context (such as a Jaxbcontext instance) and mapping runtime exceptions to HTTP requests. Annotations are defined to control the injection of method parameters and class members, and they provide valuable contextual information to the application throughout the run-time process. Overall, Jax-rs is bound to be a simple, portable, and comprehensive API for the development of RESTful Java-based services.
Create RESTful Web Services with Java technology/@[email protected]@PathParam