RESTful Web Service Implementation with RESTEasy

Exclusive offer: get 50% off this eBook here
RESTful Java Web Services

RESTful Java Web Services — Save 50%

Master core REST concepts and create RESTful web services in Java

$23.99    $12.00
by Jose Sandoval | November 2009 | BPEL SOA Web Services Java

In this article by Jose Sandoval, we implement the web service requirements we outlined in the previous article on RESTful Web Services Design, with the RESTEasy framework. RESTEasy is not only a RESTful framework, but is also JBoss's umbrella project that provides other frameworks to build RESTful web services. As part of the REST facilities, RESTEasy fully implements the JAX-RS specification. Subsequently, we only look at how we use RESTEasy to implement RESTful web services. At the time of this writing, the released version is 1.1GA.

Getting the tools

If you have already downloaded and installed Java's JDK and the Tomcat web server, you only need to download the JBoss's RESTEasy framework. Nevertheless, the complete list of the software needed for this article is as follows:

Software

Web Location

Java JDK

http://java.sun.com/

Apache Tomcat

http://tomcat.apache.org/download-60.cgi

Db4o

http://developer.db4o.com/files/default.aspx

RESTEasy Framework

http://www.jboss.org/resteasy/

Install the latest Java JDK along with the latest version of Tomcat, if you haven't done so. Download and install Db4o and RESTEasy. Remember the location of the installs, as we'll need the libraries to deploy with the web application.

RESTEasy — a JAX-RS implementation

  RESTEasy is a full open source implementation of the JAX-RS specification. This framework works within any Java Servlet container, but because it's developed by JBoss, it offers extra features that are not part of the JAX-RS requirements. For example, RESTEasy offers out-of-the-box Atom support and also offers seamless integration with the EJB container portion of JBoss (none of these features are explored here).

Web service architecture

By now, you should be familiar with the coding pattern. Because we want to reuse a large portion of code already written, we have separate layers of abstraction. In this article, therefore, we only talk about the web layer and study in detail how to implement a full RESTful web service using RESTEasy.

The full architecture of our web service looks as follows:

RESTful Web Service Implementation with RESTEasy

In this diagram, we depict clients making HTTP requests to our web service. Each request comes to the web container, which then delegates the request to our RESTful layer that is composed of RESTEasy resource classes. The actual serialization of user and message records is delegated to our business layer, which in turns talks directly to our database layer (a Db4o database).

Again, RESTEasy is a platform independent framework and works within any Servlet container. For this article we deploy our web service in Tomcat, as we've been working with it so far and are now familiar with deploying web applications to it, though we could as easily use the JBoss web container.

RESTful Java Web Services Master core REST concepts and create RESTful web services in Java
Published: November 2009
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

RESTful web service implementation with RESTEasy

We have six URIs that we now map to the following RESTEasy resource classes:

URI

Jersey Resource Class

http://localhost:8080/users

UsersResource.class

http://localhost:8080/users/{username}

UserResource.class

http://localhost:8080/messages

MessagesResource.class

http://localhost:8080/messages/{messageID}

MessageResource.class

http://localhost:8080/messages/users/{username}

UserMessagesResource.class

http://localhost:8080/messages/search/{search_item}

SearchMessagesResource.class

We implement the full API, and we list the full code for each resource.

To get the most out of this article, download the source code from Here. With the source code downloaded, you can deploy the full application in your local machine and follow along with the code explanations.

Application deployment

The full listing of source code is as follows:

RESTful Web Service Implementation with RESTEasy

Before running the application, we need to tell the web server which Servlet handles HTTP requests. We do this by modifying the web.xml application descriptor as follows:

<?xml version="1.0"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web
Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<display-name>RESTful Java Web Service</display-name>
<!-- this tells RESTEasy to load resource classes -->
<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>
<listener>
<listener-class>
org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
</listener-class>
</listener>
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet
.HttpServletDispatcher
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

This  configuration file looks similar to the ones we have already seen. For RESTEasy, however, we need to specifically tell the framework to scan for resource classes within the web application context, because the default setting is to ignore resource classes. We do this with the following XML code:

<context-param>
<param-name>resteasy.scan</param-name>
<param-value>true</param-value>
</context-param>

Without this directive set to true, our application won't identify resource classes to handle HTTP requests.

Aside from this distinct web application configuration, a RESTEasy web service is deployable as a typical Java web application. Furthermore, for the framework to be available at runtime, we have to make sure all the libraries are available to the web application. The implementation libraries of the JAX-RS specification are available in the /resteasy-jaxrs-1.1.GA/resteasy-jaxrs.war/WEB-INF/lib directory (this is the location where you extracted the RESTEasy package). Remember to add all the JAR files in this directory to your web application's WEB-INF/lib directory as shown in the screenshot.

URI and resources

Because RESTEasy is a full implementation of the JAX-RS specification, we already have all the code for our web service. This also means that all the Java annotations that we have are already studied, apply to RESTEasy.  Nevertheless, we list all the code for the sake of completeness, as the RESTEasy implementation of the web service is a completely separate web application.

/users

With this URI we list all users and create users. The full listing of the UsersResource class looks as follows:

package web;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import business.UserBO;
@Path("/users")
public class UsersResource {
@GET
@Produces("application/xml")
public String getXML() {
return UserBO.getAllXML();
}
@GET
@Produces("application/json")
public String getJSON() {
return UserBO.getAllJSON();
}
@POST
@Consumes("application/xml")
@Produces("application/xml")
public String createUser(String representation) {
try {
return UserBO.create(representation);
} catch (InvalidXMLException e) {
throw new WebApplicationException(400);
} catch (ItemAlreadyExistsException e) {
throw new WebApplicationException(403);
}
}
}

/users/{username}

With this URI we retrieve, update, and delete user records. The full listing for the UserResource class looks as follows:

package web; 
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import business.UserBO;
import exception.InvalidXMLException;
import exception.ItemAlreadyExistsException;
import exception.ItemNotFoundException;
@Path("/users/{username}")
public class UserResource {
@GET
@Produces("application/xml")
public String getXML(@PathParam("username") String username) {
String xml = UserBO.getXML(username);
if (xml != null) {
return xml;
} else {
throw new WebApplicationException(404);
}
}
@GET
@Produces("application/json")
public String getJSON(@PathParam("username") String username) {
String json = UserBO.getJSON(username);
if (json != null) {
return json;
} else {
throw new WebApplicationException(404);
}
}
@PUT
@Consumes("application/xml")
@Produces("application/xml")
public String updateUser(@PathParam("username") username, String
representation) {
try {
return UserBO.update(representation);
} catch (InvalidXMLException e) {
throw new WebApplicationException(400);
} catch (ItemNotFoundException e) {
throw new WebApplicationException(404);
}
}
@DELETE
public void deleteUser(@PathParam("username") String username) {
try {
UserBO.delete(username);
} catch (ItemNotFoundException e) {
throw new WebApplicationException(404);
}
}
}

/messages

  With this URI we create messages and retrieve representations of messages. The MessagesResource class looks as follows:

package web;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import business.MessageBO;
@Path("/messages")
public class MessagesResource {
@GET
@Produces("application/xml")
public String getXML() {
return MessageBO.getAllXML();
}
@GET
@Produces("application/json")
public String getJSON() {
return MessageBO.getAllJSON();
}
@POST
@Consumes("application/xml")
@Produces("application/xml")
public String createMessage(String representation) {
try {
return MessageBO.create(representation);
} catch (InvalidXMLException e) {
throw new WebApplicationException(400);
} catch (UserNotFoundException e) {
throw new WebApplicationException(403);
}
}
}

/messages/{messageID}

With this URI we retrieve and delete messages. The full listing for the MessageResource class looks as follows:

package web;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import business.MessageBO;
import exception.InvalidXMLException;
import exception.ItemNotFoundException;
import exception.UserNotFoundException;
@Path("/messages/{messageID}")
public class MessageResource {
@GET
@Produces("application/xml")
public String getXML(@PathParam("messageID") String messageID) {
String xml = MessageBO.getXML(messageID);
if (xml != null) {
return xml;
} else {
throw new WebApplicationException(404);
}
}
@GET
@Produces("application/json")
public String getJSON(@PathParam("messageID") String messageID) {
String json = MessageBO.getJSON(messageID);
if (json != null) {
return json;
} else {
throw new WebApplicationException(404);
}
}
@DELETE
public void deleteMessage(@PathParam("messageID")
String messageID) {
try {
MessageBO.delete(messageID);
} catch (ItemNotFoundException e) {
throw new WebApplicationException(404);
}
}
}

/messages/users/{username}

With this URI we retrieve messages that have been added by a user with identifier username. The full listing for the UserMessagesResource class looks as follows:

package web;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import business.MessageBO;
@Path("/messages/users/{username}")
public class UserMessagesResource {
@GET
@Produces("application/xml")
public String getXML(@PathParam("username") String username) {
return MessageBO.getAllXMLForUser(username);
}
@GET
@Produces("application/json")
public String getJSON(@PathParam("username") String username) {
return MessageBO.getAllJSONForUser(username);
}
}

/messages/search/{search_item}

With this URI we search messages that contain the term search_item. The full listing for the SearchMessagesResource class looks as follows: 

package web;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import business.MessageBO;
@Path("/messages/search/{search_item}")
public class SearchMessagesResource {
@GET
@Produces("application/xml")
public String searchXML(@PathParam("search_item") String
search_item) {
return MessageBO.searchAllXML(search_item);
}
@GET
@Produces("application/json")
public String searchJSON(@PathParam("search_item") String
search_item) {
return MessageBO.searchAllJSON(search_item);
}
}

Summary

In this article we have used RESTEasy's JAX-RS implementation to code our sample web service. Because it's a certified implementation of JAX-RS, we reused all the code, including all the Java annotations specified in the JAX-311 specification. However, JBoss's RESTEasy open source umbrella project adds more functionality to fully integrate with JBoss technology stack, which is beyond the scope of this article. For more information on the RESTEasy project visit http://www.jboss.org/resteasy/.

If you have read this article you may be interested to view :

RESTful Java Web Services Master core REST concepts and create RESTful web services in Java
Published: November 2009
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

About the Author :


Jose Sandoval

Jose Sandoval is a software developer based in Canada. He's played and worked with web technologies since the Mosaic web browser was released into the wild, and for the last eight years he's consulted for various financial institutions and software companies in Canada and the US, concentrating in large-scale Java web applications. He holds a Bachelor of Mathematics degree from the University of Waterloo and an MBA from Wilfrid Laurier University.

Aside from coding and writing, he enjoys watching a good soccer match and coaching his son's soccer team. You can learn more about his interests at his personal web site http://www.josesandoval.com or his consulting firm's web site http://www.sandoval.ca.

Books From Packt


Service Oriented Architecture with Java
Service Oriented Architecture with Java

SOA Patterns with BizTalk Server 2009
SOA Patterns with BizTalk Server 2009

Spring Persistence with Hibernate
Spring Persistence with Hibernate

JBoss RichFaces 3.3
JBoss RichFaces 3.3

Seam 2.x Web Development
Seam 2.x Web Development

JasperReports 3.5 for Java Developers
JasperReports 3.5 for Java Developers

Oracle SOA Suite Developer's Guide
Oracle SOA Suite Developer's Guide

Microsoft Dynamics AX 2009 Programming: Getting Started
Microsoft Dynamics AX 2009 Programming: Getting Started


Your rating: None Average: 4 (2 votes)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
A
S
6
8
F
S
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software