Enterprise Java
RESTEasy Tutorial Part-2: Spring Integration
RESTEasy provides support for Spring integration which enables us to expose Spring beans as RESTful WebServices.
Step#1: Configure RESTEasy+Spring dependencies using Maven.
Step#1: Configure RESTEasy+Spring dependencies using Maven.
<project xmlns='http:maven.apache.orgPOM4.0.0' xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xsi:schemaLocation='http:maven.apache.orgPOM4.0.0 http:maven.apache.orgmaven-v4_0_0.xsd'> <modelVersion>4.0.0<modelVersion> <groupId>com.sivalabs<groupId> <artifactId>resteasy-demo<artifactId> <version>0.1<version> <packaging>war<packaging> <properties> <project.build.sourceEncoding>UTF-8<project.build.sourceEncoding> <org.springframework.version>3.1.0.RELEASE<org.springframework.version> <slf4j.version>1.6.1<slf4j.version> <java.version>1.6<java.version> <junit.version>4.8.2<junit.version> <resteasy.version>2.3.2.Final<resteasy.version> <properties> <build> <finalName>resteasy-demo<finalName> <build> <dependencies> <dependency> <groupId>junit<groupId> <artifactId>junit<artifactId> <scope>test<scope> <dependency> <dependency> <groupId>org.slf4j<groupId> <artifactId>slf4j-api<artifactId> <version>${slf4j.version}<version> <dependency> <dependency> <groupId>org.slf4j<groupId> <artifactId>jcl-over-slf4j<artifactId> <version>${slf4j.version}<version> <scope>runtime<scope> <dependency> <dependency> <groupId>org.slf4j<groupId> <artifactId>slf4j-log4j12<artifactId> <version>${slf4j.version}<version> <scope>runtime<scope> <dependency> <dependency> <groupId>log4j<groupId> <artifactId>log4j<artifactId> <version>1.2.16<version> <scope>runtime<scope> <dependency> <dependency> <groupId>org.springframework<groupId> <artifactId>spring-context-support<artifactId> <version>${org.springframework.version}<version> <exclusions> <exclusion> <artifactId>commons-logging<artifactId> <groupId>commons-logging<groupId> <exclusion> <exclusions> <dependency> <dependency> <groupId>org.springframework<groupId> <artifactId>spring-web<artifactId> <version>${org.springframework.version}<version> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>resteasy-jaxrs<artifactId> <version>${resteasy.version}<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>resteasy-jaxb-provider<artifactId> <version>${resteasy.version}<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>jaxrs-api<artifactId> <version>2.3.0.GA<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.jboss.resteasy<groupId> <artifactId>resteasy-spring<artifactId> <version>2.3.0.GA<version> <exclusions> <exclusion> <artifactId>commons-logging<artifactId> <groupId>commons-logging<groupId> <exclusion> <exclusion> <artifactId>org.jboss.resteasy<artifactId> <groupId>resteasy-jaxb-provider<groupId> <exclusion> <exclusion> <artifactId>jaxb-impl<artifactId> <groupId>com.sun.xml.bind<groupId> <exclusion> <exclusion> <artifactId>sjsxp<artifactId> <groupId>com.sun.xml.stream<groupId> <exclusion> <exclusion> <artifactId>jsr250-api<artifactId> <groupId>javax.annotation<groupId> <exclusion> <exclusion> <artifactId>resteasy-jaxb-provider<artifactId> <groupId>org.jboss.resteasy<groupId> <exclusion> <exclusion> <artifactId>activation<artifactId> <groupId>javax.activation<groupId> <exclusion> <exclusions> <dependency> <dependency> <groupId>javax.servlet<groupId> <artifactId>servlet-api<artifactId> <version>2.5<version> <scope>provided<scope> <dependency> <dependency> <groupId>org.apache.httpcomponents<groupId> <artifactId>httpclient<artifactId> <version>4.1.2<version> <dependency> <dependencies> <project>
Step#2: Configure RESTEasy+Spring in web.xml
<web-app xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xmlns='http:java.sun.comxmlnsjavaee' xmlns:web='http:java.sun.comxmlnsjavaeeweb-app_2_5.xsd' xsi:schemaLocation='http:java.sun.comxmlnsjavaee http:java.sun.comxmlnsjavaeeweb-app_3_0.xsd' id='WebApp_ID' version='3.0'> <listener> <listener-class>org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap<listener-class> <listener> <listener> <listener-class>org.jboss.resteasy.plugins.spring.SpringContextLoaderListener<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>rest*<url-pattern> <servlet-mapping> <context-param> <param-name>contextConfigLocation<param-name> <param-value>classpath:applicationContext.xml<param-value> <context-param> <context-param> <param-name>resteasy.servlet.mapping.prefix<param-name> <param-value>rest<param-value> <context-param> <context-param> <param-name>resteasy.scan<param-name> <param-value>true<param-value> <context-param> <web-app>
Step#3: Create a Spring Service class UserService and update UserResource to use UserService bean.
package com.sivalabs.resteasydemo; import java.util.List; import org.springframework.stereotype.Service; import com.sivalabs.resteasydemo.MockUserTable; @Service public class UserService { public void save(User user){ MockUserTable.save(user); } public User getById(Integer id){ return MockUserTable.getById(id); } public List<User> getAll(){ return MockUserTable.getAll(); } public void delete(Integer id){ MockUserTable.delete(id); } } package com.sivalabs.resteasydemo; import java.util.List; 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.core.GenericEntity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @Path('users') @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public class UserResource { @Autowired private UserService userService; @Path('') @GET public Response getUsersXML() { List<User> users = userService.getAll(); GenericEntity<List<User>> ge = new GenericEntity<List<User>>(users){}; return Response.ok(ge).build(); } @Path('{id}') @GET public Response getUserXMLById(@PathParam('id') Integer id) { User user = userService.getById(id); return Response.ok(user).build(); } @Path('') @POST public Response saveUser(User user) { userService.save(user); return Response.ok('<status>success<status>').build(); } @Path('{id}') @DELETE public Response deleteUser(@PathParam('id') Integer id) { userService.delete(id); return Response.ok('<status>success<status>').build(); } } package com.sivalabs.resteasydemo; import java.util.List; import org.springframework.stereotype.Service; import com.sivalabs.resteasydemo.MockUserTable; @Service public class UserService { public void save(User user){ MockUserTable.save(user); } public User getById(Integer id){ return MockUserTable.getById(id); } public List<User> getAll(){ return MockUserTable.getAll(); } public void delete(Integer id){ MockUserTable.delete(id); } } package com.sivalabs.resteasydemo; import java.util.List; 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.core.GenericEntity; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component @Path('users') @Produces(MediaType.APPLICATION_XML) @Consumes(MediaType.APPLICATION_XML) public class UserResource { @Autowired private UserService userService; @Path('') @GET public Response getUsersXML() { List<User> users = userService.getAll(); GenericEntity<List<User>> ge = new GenericEntity<List<User>>(users){}; return Response.ok(ge).build(); } @Path('{id}') @GET public Response getUserXMLById(@PathParam('id') Integer id) { User user = userService.getById(id); return Response.ok(user).build(); } @Path('') @POST public Response saveUser(User user) { userService.save(user); return Response.ok('<status>success<status>').build(); } @Path('{id}') @DELETE public Response deleteUser(@PathParam('id') Integer id) { userService.delete(id); return Response.ok('<status>success<status>').build(); } } applicationContext.xml <?xml version='1.0' encoding='UTF-8'?> <beans xmlns='http:www.springframework.orgschemabeans' xmlns:xsi='http:www.w3.org2001XMLSchema-instance' xmlns:p='http:www.springframework.orgschemap' xmlns:context='http:www.springframework.orgschemacontext' xsi:schemaLocation='http:www.springframework.orgschemabeans http:www.springframework.orgschemabeansspring-beans.xsd http:www.springframework.orgschemacontext http:www.springframework.orgschemacontextspring-context.xsd'> <context:annotation-config> <context:component-scan base-package='com.sivalabs.resteasydemo'> <beans>
Step#4: Same JUnit TestCase to test the REST Webservice described in Part-1.
package com.sivalabs.resteasydemo; import java.util.List; import org.jboss.resteasy.client.ClientRequest; import org.jboss.resteasy.client.ClientResponse; import org.jboss.resteasy.util.GenericType; import org.junit.Assert; import org.junit.Test; import com.sivalabs.resteasydemo.User; public class UserResourceTest { static final String ROOT_URL = 'http:localhost:8080resteasy-demorest'; @Test public void testGetUsers() throws Exception { ClientRequest request = new ClientRequest(ROOT_URL+'users'); ClientResponse<List<User>> response = request.get(new GenericType<List<User>>(){}); List<User> users = response.getEntity(); Assert.assertNotNull(users); } @Test public void testGetUserById() throws Exception { ClientRequest request = new ClientRequest(ROOT_URL+'users1'); ClientResponse<User> response = request.get(User.class); User user = response.getEntity(); Assert.assertNotNull(user); } @Test public void testSaveUser() throws Exception { User user = new User(); user.setId(3); user.setName('User3'); user.setEmail('user3@gmail.com'); ClientRequest request = new ClientRequest(ROOT_URL+'users'); request.body('applicationxml', user); ClientResponse<String> response = request.post(String.class); String statusXML = response.getEntity(); Assert.assertNotNull(statusXML); } @Test public void testDeleteUser() throws Exception { ClientRequest request = new ClientRequest(ROOT_URL+'users2'); ClientResponse<String> response = request.delete(String.class); String statusXML = response.getEntity(); Assert.assertNotNull(statusXML); } }
Important Things to Keep in mind:
1. org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap Listener should be registered before any other listener.
2. You should configure resteasy.servlet.mapping.prefix @lt;context-param> if the HttpServletDispatcher servlet url-pattern is anything other than /*
3. You should register REST Resource as Spring bean by annotating with @Component or @Service.
Reference: RESTEasy Tutorial Part-2: Spring Integration from our JCG partner Siva Reddy at the My Experiments on Technology blog.
u pasted UserResource class twice :)
I am getting the exception like below, when I deploy the project on Jboss
Caused by: java.lang.NoSuchMethodError: org.jboss.resteasy.spi.InjectorFactory.createPropertyInjector(Ljava/lang/Class;)Lorg/jboss/resteasy/spi/PropertyInjector;
Caused by: java.lang.NoSuchMethodError: org.jboss.resteasy.spi.InjectorFactory.createPropertyInjector(Ljava/lang/Class;)Lorg/jboss/resteasy/spi/PropertyInjector;