RESTful Webservices with Jersey
I have discussed my earlier article about architectural consideration<<link>> to become a RESTful system on distributed environment that are usable my system/machines. This article we are going to discuss how to build web services based on REST architecture consideration. 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 and accepted 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 having following major parts:
- Core Server: To build RESTful web services based on annotation 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 and Jersey libraries here<link>
RESTful web service implementation using Jersey
We will build a small application for user management to operate CRUD operations on user. Then, we will create small User table with column username and password and do the CRUD operation using POJO class expose 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
UsersResource.java @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 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 it help to communicate with server and test the services. The 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 link<>
Resources:
Hi
I need to create a REST webservice in java which calls various other webservices(REST and SOAP ) both. How can I do that?
Hi,
Thanks for this tutorial, the download link is invisible.
Thanks
Would it be possible to do a
public List testGetUsers()
method? I know it would be possible to manually parse the XML, but is there any kind of data binding already built in?
Hi Nitin Kumar, thanks for providing a valid article on REST Webservice.
This code doesnt work while deploying on Jboss 7.1
I am facing this error ,
IUsersResource cannot be resolved to a type
is there another file containing this interface ?
I made a user library and added all jar files mentioned above, and added that userlibrary in build path as well
Hello,
I tried to test the full code with ECLIPSE but i got the following error :
exception
javax.servlet.ServletException: “Servlet.init()” pour la servlet Jersey REST Service a généré une exception
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1041)
org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:603)
org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310)
java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
java.lang.Thread.run(Unknown Source)
Any idea what’s the reason ? thank’s in advance