Build RESTful Web Services using Spring


Spring, the well-known framework for building Java EE applications, now supports REST in its MVC layer. This article introduces the "Spring way" to build RESTful web services. Learn how to use Spring APIs and annotations to build RESTful web services, and see how Spring integrates this new feature seamlessly into its original framework. This article assumes that reader has basic understanding of RESTful web service concept, Eclipse and Tomcat.

Server Example using Spring REST Support

1. Enable Spring WebApplicationContext in WEB-INF/web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
 <display-name>Archetype Created Web Application</display-name>
 <servlet>
  <servlet-name>rest</servlet-name>
  <servlet-class>
   org.springframework.web.servlet.DispatcherServlet
  </servlet-class>
      <init-param>
      <param-name>config-api</param-name>
      <param-value>WEB-INF/rest-servlet.xml</param-value>
    </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>rest</servlet-name>
  <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>
</web-app>
 

2. Set up the Spring MVC-related configuration (Controller, View, View Resolver,Message Converters) in the WEB-INF/rest-servlet.xml file. Following shows the most important snippet.

<?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-3.0.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
  <context:annotation-config />
  
 <context:component-scan base-package="com.mycompany.mywebapp" />
 <bean
  class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="messageConverters">
   <list>
    <ref bean="marshallingHttpMessageConverter" />
   </list>
  </property>
 </bean>


 <bean id="marshallingHttpMessageConverter"
  class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
  <property name="marshaller" ref="jaxbMarshaller" />
  <property name="unmarshaller" ref="jaxbMarshaller" />
 </bean>
 <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
  <property name="classesToBeBound">
   <list>
    <value>com.mycompany.mywebapp.HelloWorldRequest
    </value>
    <value>com.mycompany.mywebapp.HelloWorldResponse
    </value>

   </list>
  </property>
 </bean>

 <bean id="helloWorldResponseView"
  class="org.springframework.web.servlet.view.xml.MarshallingView">
  <constructor-arg ref="jaxbMarshaller" />
 </bean>

 <bean
  class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
  <property name="mediaTypes">
   <map>
    <entry key="xml" value="application/xml" />
    <entry key="html" value="text/html" />
   </map>
  </property>
  <property name="viewResolvers">
   <list>
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />

   </list>
  </property>
 </bean>

</beans>
 

In the code above:

Component-scan
    Enables automatic scan for the class that has Spring annotations In practice, it's used to detect the @Controller annotation defined in controller classes.

AnnotationMethodHandlerAdapter
    Bean that will make the @ReqeustMapping annotation on the class or method to be processed by Spring.

Jaxb2Mashaller
    Defines the marshaller/unmarshaller that uses JAXB 2 to do the object XML mapping (OXM)

MashallingView
     Defines an XML representation view that utilizes the Jaxb2Mashaller

BeanNameViewResolver
    Defines a view resolver using the bean name that the user specifies.
    The example will use the MarshallingView name "helloWorldResponseView."

That completes the Spring-related configuration.
 

3. The next step is to write a controller that handles the user request, HelloWorldRequest and HelloWorldResponse. Following shows all classes.

######### HelloWorld Request Class ##########
        
package com.mycompany.mywebapp;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="helloWorldRequest")
public class HelloWorldRequest {
 private String helloString;

 public String getHelloString() {
  return helloString;
 }

 public void setHelloString(String helloString) {
  this.helloString = helloString;
 }
 
}

      ######### HelloWorld Response Class ##########


package com.mycompany.mywebapp;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="helloWorldResponse")
public class HelloWorldResponse {
 private String helloString;

 public String getHelloString() {
  return helloString;
 }

 public void setHelloString(String helloString) {
  this.helloString = helloString;
 }
}

   ######### HelloWorld Controller Class ##########
package com.mycompany.mywebapp;

import org.springframework.stereotype.Controller;
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;


@Controller
public class HelloWorldController {
 
 @RequestMapping(method=RequestMethod.POST,value="/postHelloWorld")
 public ModelAndView handlePostRequest(@RequestBody HelloWorldRequest helloWorldRequest){
  String request = helloWorldRequest.getHelloString();
  String response = "Hello " + request;
  HelloWorldResponse helloWorldResponse= new HelloWorldResponse();
  helloWorldResponse.setHelloString(response);
  return new ModelAndView("helloWorldResponseView", "helloWorldResponse", helloWorldResponse);
 }
 
 
 @RequestMapping(method=RequestMethod.GET,value="/getHelloWorld/{request}")
 public ModelAndView handlePostRequest(@PathVariable String request){
  String response = "Hello " + request;
  HelloWorldResponse helloWorldResponse= new HelloWorldResponse();
  helloWorldResponse.setHelloString(response);
  return new ModelAndView("helloWorldResponseView", "helloWorldResponse", helloWorldResponse);
 }
}
 

Clients that communicate with REST services

1. Create resources directory under src/main folder and make it a source folder. Configure client-context.xml under this resources directory as below

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
        <property name="messageConverters">
            <list>
                <bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
                    <property name="marshaller" ref="jaxbMarshaller" />
                    <property name="unmarshaller" ref="jaxbMarshaller" />
                </bean>
                
            </list>
        </property>
    </bean>

    <bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
              <value>com.mycompany.wsclient.HelloWorldRequest</value>
                <value>com.mycompany.wsclient.HelloWorldResponse</value>
             </list>
        </property>
    </bean>
</beans>
 

2. Create 'HelloWorldRequest' and 'HelloWorldResponse' objects under com.mycompany.wsclient package as created in Step#5 in server part

3. Create WSClient as shown below.

package com.mycompany.wsclient;

import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.client.RestTemplate;


/**
 * Hello world!
 *
 */
public class App 
{
    public static void main( String[] args )
    {
     System.out.println( "Hello World!" );
     ApplicationContext ctx = new ClassPathXmlApplicationContext("client-context.xml");
     RestTemplate restTemplate = (RestTemplate)ctx.getBean("restTemplate");
     
     /*  GET REQUEST */
     Map <String,String> parameters = new HashMap<String,String>();
     parameters.put("request", "RESTful WebService");
     
     HelloWorldResponse helloWorldResponse = restTemplate.getForObject("http://localhost:8080/mywebapp/rest/getHelloWorld/{request}", HelloWorldResponse.class,parameters);
     System.out.println(helloWorldResponse.getHelloString());
     
     /* POST REQUEST*/
     HelloWorldRequest helloWorldRequest = new HelloWorldRequest();
     helloWorldRequest.setHelloString("RESTful WebService");
     helloWorldResponse = restTemplate.postForObject("http://localhost:8080/mywebapp/rest/postHelloWorld", helloWorldRequest,HelloWorldResponse.class);
     System.out.println(helloWorldResponse.getHelloString());
    }
}
 

No comments:

Post a Comment