Saturday, March 28, 2015

Spring 3 MVC and REST

For anyone working with Spring 3 MVC and REST, I spent a lot of time getting this sorted, so I thought I would post some results.

Spring 3 is a few years old now, but I'm using it at my day job, so that's what I'm using here. You can get a Spring 3 MVC project running by following any number of tutorials. I won't go into those details here.

The biggest gotcha I ran into wasn't well documented anywhere, in fact, I found two singular pieces of information which enabled me to get this code working after some considerable effort. First is using Jackson version 1.9, instead of 2.x, for Spring MVC versions prior to 3.1. Here's the POM entries.

<properties>
 <jackson.version>1.9.13</jackson.version>
</properties>

<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-core-asl</artifactId>
 <version>${jackson.version}</version>
</dependency>

<dependency>
 <groupId>org.codehaus.jackson</groupId>
 <artifactId>jackson-mapper-asl</artifactId>
 <version>${jackson.version}</version>
</dependency>

Secondly, with Spring MVC 3.0, you need this in your bean configuration;

 <!-- JSON support -->
 <bean id="jacksonMessageConverter"
  class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
 <bean
  class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  <property name="messageConverters">
   <list>
    <ref bean="jacksonMessageConverter" />
   </list>
  </property>
 </bean>

So, let's take a request from the beginning. I used Advanced Rest Client chrome extension, but this works as a simple URL request. Your web.xml file needs handle the request,

<!-- Initialise the Spring MVC DispatcherServlet -->
<servlet>
 <servlet-name>spring-myapp</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
</servlet>

<!-- Map the Spring MVC DispatcherServlet to intercept *.sp requests -->
<servlet-mapping>
 <servlet-name>spring-myapp</servlet-name>
 <url-pattern>*.sp</url-pattern>
</servlet-mapping> 

<servlet-mapping>
 <servlet-name>spring-myapp</servlet-name>
 <url-pattern>json/*</url-pattern>
</servlet-mapping> 


Spring maps the URL to a controller,

<context:component-scan base-package="com.nml.myapp.web.controller" />
<context:annotation-config />
<mvc:annotation-driven />

and with Jackson in the classpath, the controller code returns the JSON response,


@Controller
public class JsonController {

 private static final Logger logger = Logger.getLogger(JsonController.class);

 @RequestMapping(value = "/getCategories", method = RequestMethod.GET)
 public @ResponseBody List<String> query() {

  logger.info("rest request: getCategories");
  
  List<String> list = new ArrayList<String>();
  list.add("object is list");
  list.add("second object"); 
//  model.addAttribute("list", list);
  
  return list;
 }
}

Here's the result. My first good night's sleep in a week.


No comments: