REST (REpresentational State Transfer) is an architecture style that describes how to use HTTP to access web services. JAX-RS (JSR 311) is a Java API to support implementation/access of REST web services using Java. This style was first documented by Ron Fielding. Note: Jan 10th 2012: Blog updated. Code moved into Maven project structure.
REST…
- requires that all services be treated as resources that can be accessed via a URI.
- requires the services be stateless.
- does NOT describe any common data exchange formats. The producer and consumer are free to choose whatever format they want.
- services in many cases are cacheable.
- uses existing HTTP methods to define actions to be done on the server.
Used over HTTP the following HTTP methods can be used:
- GET to retrieve data.
- DELETE to delete.
- POST to add new data
- PUT to update data.
Now compare all of this to SOAP based web services where you use a WSDL to advertise your interface. We have the SOAP envelope that wraps the payload. Then we have document-style vs. rpc style. SOAP Faults. Marshalling and un-marshalleing the soap headers, envelope and fault. SOAP Web Services also provide many services such as transaction, security, addressing, etc (basically the WS-* baggage). And last but not the least we have the payload – finally. All that’s great, but often we just need to access a simple service without the need for all of the SOAP complexity. That is where the RESTful architecture style comes in. On the Java side JAX-RS was introduced to provide a common API to implement/access REST based services in Java. Jersey is the open source reference implementation of REST. Lets get to an example and see how this works. I will implement my usual time service. Call a service to get time of the day in XML, plain text or JSON format. First the Maven pom.xml file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.aver</groupId> <artifactId>rest</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>jaxrs-jersey</name> <properties> <spring.version>3.1.0.RELEASE</spring.version> <jersey-version>1.11</jersey-version> </properties> <dependencies> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-server</artifactId> <version>${jersey-version}</version> </dependency> <dependency> <groupId>com.sun.jersey.contribs</groupId> <artifactId>jersey-spring</artifactId> <version>${jersey-version}</version> </dependency> <dependency> <groupId>com.sun.jersey</groupId> <artifactId>jersey-json</artifactId> <version>${jersey-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <finalName>jaxrs</finalName> <plugins> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.10</version> <configuration> <contextPath>/jaxrs</contextPath> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>9090</port> <maxIdleTime>60000</maxIdleTime> </connector> </connectors> </configuration> </plugin> </plugins> </build> </project> |
Here is the web.xml…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<web-app> <display-name>JAX-RS Jersey App</display-name> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> <servlet> <servlet-name>JAX-RS Jersey App</servlet-name> <servlet-class>com.sun.jersey.spi.spring.container.servlet.SpringServlet</servlet-class> <init-param> <param-name>com.sun.jersey.config.property.packages</param-name> <param-value>com.aver.restful</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>JAX-RS Jersey App</servlet-name> <url-pattern>/services/*</url-pattern> </servlet-mapping> </web-app> |
Here is the implementation of the TimeOfTheDayService. JAX-WS annotations have been used to configure various JAX-RS attributes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
package com.aver.restful; import java.text.SimpleDateFormat; import java.util.Calendar; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import org.springframework.stereotype.Component; @Component @Path("/timeoftheday") public class TimeOfTheDayService { private static String PATTERN = "MM.dd.yyyy HH:mm:ss"; @GET @Produces("text/plain") @Path("/asplaintext/{name}") public String getTimeOfTheDay(@PathParam("name") String name) { SimpleDateFormat df = new SimpleDateFormat(PATTERN); return name + "-" + df.format(Calendar.getInstance().getTime()); } @GET @Produces("application/xml") @Path("/asxml/{name}/") public Time getTimeOfTheDayInXML(@PathParam("name") String name) { SimpleDateFormat df = new SimpleDateFormat(PATTERN); Time t = new Time(); t.setName(name); t.setTime(df.format(Calendar.getInstance().getTime())); return t; } @GET @Produces("application/json") @Path("/asjson/{name}/") public Time getTimeOfTheDayInJSON(@PathParam("name") String name) { SimpleDateFormat df = new SimpleDateFormat(PATTERN); Time t = new Time(); t.setName(name); t.setTime(df.format(Calendar.getInstance().getTime())); return t; } } |
- @Component – This is NOT a JAX-RS annotation. This is a Spring annotation to declare a spring bean via annotations vs. XML configuration
- @Path(“/timeoftheday”) – Specifies the URI part for all the services in thisclass.
- @GET– Used to annotate the read method.
- @Produces(“text/plain”)– Marks the method as a producer of plain/text content.
- @Path(“/asjson/{name}/”) – Describes the specific method. The optional {name} describes in our case the parameter passed into this service method.
Run “mvn package jetty:run” to compile and deploy the web application to a local Jetty web server. The URL to access the services would be one of:
- http://localhost:9090/jaxrs/services/timeoftheday/asplaintext/mathew
- http://localhost:9090/jaxrs/services/timeoftheday/asxml/mathew
- http://localhost:9090/jaxrs/services/timeoftheday/asjson/mathew
The resource is identified via the URI and so is the parameter namein this example. Access one of the URLs mentioned above using your favorite browser and you will get the response in the appropriate format. You can also use the Jersey client API to access this service.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.WebResource; public class RestTest { public static void main(String[] args) { Client c = Client.create(); // plain text WebResource r = c .resource("http://localhost:9090/jaxrs/services/timeoftheday/asplaintext/mathew"); System.out.println("Plain Text=>> " + r.get(String.class)); // json r = c.resource("http://localhost:9090/jaxrs/services/timeoftheday/asjson/mathew"); System.out.println("JSON=>> " + r.get(String.class)); // xml r = c.resource("http://localhost:9090/jaxrs/services/timeoftheday/asxml/mathew"); System.out.println("XML=>> " + r.get(String.class)); } } |
Once you execute this client you should get a response such as:
1 2 3 |
Plain Text=>> mathew-01.10.2012 22:00:42 JSON=>> {"time":"01.10.2012 22:00:42","name":"mathew"} XML=>> <?xml version="1.0" encoding="UTF-8" standalone="yes"?><clock><time>01.10.2012 22:00:42</time><name>mathew</name></clock> |
Click here to download the full Maven project.