What is REST?
REST is a term coined by Roy Fielding in his Ph.D. dissertation [1] to describe an architecture style of networked systems. REST is an acronym standing for Representational State Transfer.
I'm going to explain in detail in this article how to build a Spring based REST service.
1. Create a "Dynamic web project" in Eclipse, Name "restService" for example.
2. You need the following Jar files
commons-logging-1.1.1.jar
jstl-1.2.jar
org.springframework.aop-3.1.1.RELEASE.jar
org.springframework.asm-3.1.1.RELEASE.jar
org.springframework.aspects-3.1.1.RELEASE.jar
org.springframework.beans-3.1.1.RELEASE.jar
org.springframework.context-3.1.1.RELEASE.jar
org.springframework.context.support-3.1.1.RELEASE.jar
org.springframework.core-3.1.1.RELEASE.jar
org.springframework.expression-3.1.1.RELEASE.jar
org.springframework.instrument-3.1.1.RELEASE.jar
org.springframework.instrument.tomcat-3.1.1.RELEASE.jar
org.springframework.jdbc-3.1.1.RELEASE.jar
org.springframework.jms-3.1.1.RELEASE.jar
org.springframework.orm-3.1.1.RELEASE.jar
org.springframework.oxm-3.1.1.RELEASE.jar
org.springframework.spring-library-3.1.1.RELEASE.libd
org.springframework.test-3.1.1.RELEASE.jar
org.springframework.transaction-3.1.1.RELEASE.jar
org.springframework.web-3.1.1.RELEASE.jar
org.springframework.web.portlet-3.1.1.RELEASE.jar
org.springframework.web.servlet-3.1.1.RELEASE.jar
org.springframework.web.struts-3.1.1.RELEASE.jar
3. Edit the web.xml file under WEB-INF, add the following lines
<servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping>
4. As per the instructions given in the link create Jaxb java classes for the following XSD file
Generating Jaxb java classes<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.lax.com/customer" xmlns="http://www.lax.com/customer" > <xs:element name="customerDetails" type="CustomerDetails"/> <xs:complexType name="CustomerDetails"> <xs:sequence> <xs:element name="customerName" type="xs:string" minOccurs="1" maxOccurs="1"/> <xs:element name="customerStreet" type="xs:string" minOccurs="1" maxOccurs="1"/> <xs:element name="customerCity" type="xs:string" minOccurs="1" maxOccurs="1"/> <xs:element name="customerState" type="xs:string" minOccurs="1" maxOccurs="1"/> <xs:element name="customerZip" type="xs:string" minOccurs="1" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:schema>
5. In the same way create Jaxb java classes for the following XSD as well.
<?xml version="1.0" encoding="UTF-8"?> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.lax.com/statusRes" xmlns="http://www.lax.com/statusRes" > <xs:element name="statusRes" type="StatusRes"/> <xs:complexType name="StatusRes"> <xs:sequence> <xs:element name="resMsg" type="xs:string" minOccurs="1" maxOccurs="1"/> </xs:sequence> </xs:complexType> </xs:schema>
6. Under WEB-INF folder create a file called springmvc-servlet.xml (The file name has a significance, it should be <servlet-name>-servlet.xml). Add the following lines in this file.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Enable annotation scanning --> <context:component-scan base-package="com.lax"/> <bean name="viewResolver2" class="org.springframework.web.servlet.view.BeanNameViewResolver"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="stringHttpMessageConverter"/> <ref bean="marshallingHttpMessageConverter"/> </list> </property> </bean> <bean id="marshallingView" class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg ref="jaxbMarshaller"/> </bean> <bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter"/> <bean id="marshallingHttpMessageConverter" class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"> <constructor-arg ref="jaxbMarshaller"/> <property name="supportedMediaTypes" value="application/xml" /> </bean> <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.lax.oxm.customer.CustomerDetails</value> <value>com.lax.oxm.res.StatusRes</value> </list> </property> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/> <property name="prefix" value="/WEB-INF/jsp/"/> <property name="suffix" value=".jsp"/> </bean> </beans>
The classes mentioned under the tags
<bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"> <property name="classesToBeBound"> <list> <value>com.lax.oxm.customer.CustomerDetails</value> <value>com.lax.oxm.res.StatusRes</value> </list> </property> </bean>
are the classes you generate in steps 4 & 5
7. Create the following Controller Java class
package com.lax.controller; import org.springframework.stereotype.Controller; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.lax.oxm.customer.CustomerDetails; import com.lax.oxm.res.StatusRes; @Controller @RequestMapping("/sampleAnnotationCnt") public class SampleAnnotationController{ private static final String XML_VIEW_NAME = "marshallingView"; @RequestMapping(value="/processCustomerDetails.htm", method=RequestMethod.POST) public ModelAndView processCustomerDetails(@RequestBody CustomerDetails customerDetails) throws Exception { System.out.println(customerDetails.getCustomerName()); StatusRes statusRes = null; statusRes = new StatusRes(); statusRes.setResMsg("successful"); return new ModelAndView(XML_VIEW_NAME, BindingResult.MODEL_KEY_PREFIX, statusRes); } }
8. Creating a client for the service
Jars required
commons-httpclient-3.1-jbossorg-1.jar
commons-logging-1.1.1.jar
commons-codec-2.0-20110918.143203-58.jar
9. Create the following java class and execute it to invoke the REST Webservice
package com.lax.restclient; import java.io.IOException; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpException; import org.apache.commons.httpclient.methods.PostMethod; public class RestClient { public static void main(String[] args) { String response = null; String body = "<?xml version="1.0" encoding="UTF-8" standalone="yes"?><ns2:customerDetails xmlns:ns2="http://www.lax.com/customer"><customerName>Balamurugan</customerName><customerStreet>5000 Vinoy blvd</customerStreet><customerCity>Charlotte</customerCity><customerState>NC</customerState><customerZip>28262</customerZip></ns2:customerDetails>"; String url = "http://localhost:8080/restService/sampleAnnotationCnt/processCustomerDetails.htm"; PostMethod postMethod = new PostMethod(url); postMethod.setRequestBody(body); postMethod.setRequestHeader("Content-type", "application/xml"); HttpClient httpClient = new HttpClient(); try { int status = httpClient.executeMethod(postMethod); response = postMethod.getResponseBodyAsString(); System.out.println("Status : "+status); System.out.println("Response : "+response); } catch (HttpException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }