I have discussed my earlier article about architectural consideration on RESTful system for distributed environment. This article we are going to discuss how to build RESTful web services with Jersey and Apache Tomcat.
This tutorial explains how to develop RESTful web services in Java with the Tomcat 6, Eclipse and Jersey a JAX-RS (JSR 311) reference implementation.
In a nutshell a RESTful web service is a communication between machines using HTTP on REST principles which have following key points:
- Each resource represents unique URI to communicate over HTTP protocols
- Each resource operation supported by HTTP methods (POST, GET, PUT and DELETE)
- Request and Response supported by JSON, XML and various MIME type such as image, byte stream etc.
JAX-RS
JAX-RS is an annotation-based API for implementing RESTful web services, based on HTTP, in Java. Essentially, classes and methods are annotated with information that enables a runtime to expose them as resources. A runtime that implements JAX-RS mediates between the HTTP protocol and the Java classes, taking into account URIs, requested , content types, and HTTP methods.
Jersey framework implemented JSR-RS(JSR-311) reference APIs. In addition to Jersey various other implementation are available such as Retlet, JBOSS RESTeasy, Apache CXF etc.
Jersey:
Jersey contains following major parts:
- Core Server: To build RESTful web services based on annotation which include key libraries such as : jersey-core.jar, jersey-server.jar, jsr311-api.jar, asm.jar
- Core Client: The Jersey client API helps you to easily communicate with REST services include libabry ersey-client.jar
- JAXB support: (Used in the advanced example) jaxb-impl.jar, jaxb-api.jar, activation.jar, stax-api.jar, wstx-asl.jar
- JSON support: (Used in the advanced example) jersey-json.jar
- Integration: Jersey also provides libraries that can easily integrate with Spring, Guice, Apache Abdera, and so on.
Getting the tools
Software | Download |
Java JDK-6 | http://www.oracle.com/ |
Eclipse – Indico | http://www.eclipse.org/ |
Tomcat Apache -6 | http://tomcat.apache.org/ |
H2-Database | http://www.h2database.com/ |
Note: You could download full demo application including H2 database and Jersey libraries here Download Link
RESTful web service implementation using Jersey
We will build a small application for user management to operate CRUD operations on users.
We will create small User table with column username and password and do the CRUD operation using POJO class exposing operation on web services using Jersey annotation.
Following are the design consideration before starting the RESTful web service development.
- Resources: User with attributes username and password
- Resource Class: UsersResource.java
- URI: http://localhost:8080/UserManagement/users
- Representation: XML
Application Development folder structure
The directory structure of our application looks as follows:
Following are list of application libraries required:
Application Configuration:
Before starting the development we need to add the Jersey servlet into web.xml to direct the entire request to jersey for resource identification and operation processes (POST, GET, PUT, and DELETE).
After including jersey servlet ,Web.xml will look like as below
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>UserManagement</display-name> <servlet> <servlet-name>Jersey REST Service</servlet-name> <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>resource.com.users.java</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Jersey REST Service</servlet-name> <url-pattern>/*</url-pattern> </servlet-mapping> </web-app>
Resources
Resources are anything that are addressable and manipulated over the web . Jersey resources are plain java object (POJO) with annotation @Path and will be manipulated by HTTP methods POST, GET,PUT and DELETE. A resource also has sub resources. In the sample application UsersResource for Users java bean is Resources. Users is simple POJO with attributes ‘name’ and ‘password’
<span style="font-family: 'Courier 10 Pitch', Courier, monospace; font-size: 13px;">UsersResource.java</span> @Path("/users") public class UsersResource implements IUsersResource{ @Context UriInfo uriInfo; @GET @Produces ("application/xml") public List<User> getUsersAll() { List<User> als=null; try { als= UserService.getInstance().getUserAll(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return als; } @POST @Consumes ("application/xml") @Produces ("application/xml") public User createUser(User user){ URI uri = uriInfo.getAbsolutePathBuilder().path(user.getUserName()).build(); Response res=Response.created(uri).build(); try { UserService.getInstance().CreateUser(user); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } return user; } @Path("/user/{username}") @GET @Produces ("application/xml") public List<User> getUser(@PathParam("username") String username) { List<User> asl=null; try { asl= UserService.getInstance().getUser(username); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } return asl; }
Below are the explanations of JAX-RS annotation in brief
- @Path: Path combined with root path provide URI to identify resource. E.g. in the given example URI will be http://localhost:8080/UserManagement/users
- @Path(“/user/{username}”): we could also sub path on method to expose sub resources this example URI will be http://localhost:8080/UserManagement/users/user/john
- @Context: Context use to inject the contextual objects such as Request, Response, UriInfo, ServletContext etc.
- @PathParam : This annotation is used together with @Path and in conjunction with GET, POST, PUT and DELETE. Other available annotations are @FormParam, @QueryParam etc.
- @Produces (“application/xml”): Multiple MIME types are supported for responses. In this case, application/xml will be the default MIME type.
- @Consumes (“application/xml”): Input Request payload will be send in xml format.
- @GET: resources manipulated by one of the GET,POST, PUT and DELET method pass by HTTP header
JAXB – Java POJO XML Binding
Jersey support JAXB which interns to handle POJO to XML conversion and vice versa. To qualify POJO to support XML we have to declare @XmlRootElement annotation as follows:
Don’t forget to add empty constructor as it required during conversion.
@XmlRootElement public class User { private String userName; private String userPasswd; public User(String userName, String userPasswd) { this.userName = userName; this.userPasswd = userPasswd; } public User() { super(); } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getUserPasswd() { return userPasswd; } public void setUserPasswd(String userPasswd) { this.userPasswd = userPasswd; } }
We will create service classes which perform CRUD operation in User table in H2 database.
UserService.java public class UserService{ public static UserService userService = new UserService(); public static final String GET_USER="SELECT * FROM USER"; public static final String INSERT_USER="Insert into user "; public List<User> getUserAll() throws ClassNotFoundException, SQLException { List<User> ls = new ArrayList(); ls=DataServiceHelper.getInstance().executeQuery(GET_USER); return ls; } public List<User> getUser(String name) throws ClassNotFoundException, SQLException{ String SQL_WHERE_CAS=" where name='"+name+"'"; List<User> als=DataServiceHelper.getInstance().executeQuery(GET_USER+SQL_WHERE_CAS); return als; } public void CreateUser(User user) throws SQLException, ClassNotFoundException { String SQL_WHERE_CASE=" VALUES('" + user.getUserName() + "','" + user.getUserPasswd() + "')"; DataServiceHelper.getInstance().executeUpdateQuery(INSERT_USER+SQL_WHERE_CASE); } public static UserService getInstance() { return userService; } }
Helper classes
We have to create couple of more classes to interact with DB(H2 in our case) and perform CRUD operation.
DaraServiceHelper.java public class DataServiceHelper { public static DataServiceHelper dataServiceHelper = null; private Connection con = null; DataSource dataSource = null; InitialContext initialContext = null; public static final String DB_URL = "jdbc:h2:tcp://localhost/~/test"; public static final String DRIVER_NAME = "org.h2.Driver"; /** * This method is used to create an object for the given DAO class name. */ public Connection getConnection() throws ClassNotFoundException, SQLException { Class.forName(DRIVER_NAME); con = DriverManager.getConnection(DB_URL, "sa", ""); return con; } public void closeConnection() throws SQLException { if (isConnectionOpen()) { con.close(); con = null; } } public boolean isConnectionOpen() { return (con != null); } public static DataServiceHelper getInstance() { if (dataServiceHelper == null) { dataServiceHelper = new DataServiceHelper(); } return dataServiceHelper; } public void executeUpdateQuery(String query) throws SQLException, ClassNotFoundException { Connection con = getConnection(); Statement stmt = con.createStatement(); stmt.execute(query); closeConnection(); } public List<User> executeQuery(String query) throws ClassNotFoundException, SQLException { Connection con = getConnection(); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(query); List<User> als = convertPojoList(rs); closeConnection(); return als; } private List<User> convertPojoList(ResultSet rs) throws SQLException { List<User> asl = new ArrayList<User>(); while (rs.next()) { User user = new User(rs.getString("name"), rs.getString("password")); asl.add(user); } return asl; } public static void main(String[] args) throws ClassNotFoundException, SQLException { String query = "Select * from user where name='nitin'"; List<User> als = DataServiceHelper.getInstance().executeQuery(query); System.out.println("List==>" + als); } }
Note: For simplicity I have included all code in one class
Jersey Client Testing
Jersey provide client to test the RESTful web services whic help to communicate with server and test the services. The client library is a generic implementation that can cooperate with any HTTP/HTTPS-based Web service.
public class UserResourceSample { public static final String USER_URI="http://localhost:8080/UserManagement/users"; public String testGetUsersAll() { ClientConfig config = new DefaultClientConfig(); Client client = Client.create(config); WebResource resource = client.resource(ForumConstant.USER_URI); ClientResponse response = resource.type(MediaType.APPLICATION_XML).get( ClientResponse.class); String en = response.getEntity(String.class); return en; } public String testGetUsers() { ClientConfig config = new DefaultClientConfig(); Client client = Client.create(config); WebResource resource = client.resource(ForumConstant.USER_URI); ClientResponse response = resource.type(MediaType.APPLICATION_XML).get( ClientResponse.class); String en = response.getEntity(String.class); return en; } public User testCreateUser() { User user = new User("John", "john@"); Client client = Client.create(); WebResource r = client.resource(ForumConstant.USER_URI); ClientResponse response = r.accept(MediaType.APPLICATION_XML).post( ClientResponse.class, user); return user; } }
Run using browser
Run you web application in Eclipse and test the availability of your REST service under: “http://localhost:8080/UserManagement/users”. You should see the XML representation of your users items
For sub resource
Note: Before running the application don’t forget to run H2 database and insert the record into User table
Conclusion:
This example talks about basic uses of Jersey with Apache tomcat. We will discuss some later on advance JAX-RS uses. You can also download the full code into below this Download link
References:
http://en.wikipedia.org/wiki/Representational_state_transfer
https://jersey.java.net/
Excellent items from you, man. I’ve take into account
your stuff prior to and you are just too excellent.
I really like what you have bought right here,
certainly like what you’re stating and the way
by which you are saying it. You’re making it enjoyable and you still care for to stay it sensible.
I cant wait to read much more from you. That is really a
tremendous web site.
Hi to every one, the contents present at this web page are genuinely remarkable
for people experience, well, keep up the good work fellows.
Hi just wanted to give you a quick heads up and let you know a few of the pictures aren’t
loading properly. I’m not sure why but I think its a linking issue.
I’ve tried it in two different web browsers and both show
the same outcome.
This article is in fact a good one it assists new web people, who are wishing in favor of blogging.
Thanks for finally writing about >RESTful Webservices
with Jersey | TechMyTalk <Loved it!
Thank you for any other informative website.
Where else may I get that kind of info written in such an ideal means?
I have a project that I am simply now operating on, and I have been on the look out for
such info.
I see the example of the client which tests the service in most such tutorials. I on the other hand am trying to write a Java swing application that will interact with the rest service. So I got the service part running (meaning i can hit the URL and i am able to get the xml response) but now how do I use jersey to make a call to that url and interpret the xml and parse it into objects to show it to the end-user? I am not able to find a way to do that. Can you please share some thoughts on this?
Thanks