About a year ago I started using Spring for a whole heap of REST webservices I was writing. In the process I found it surprisingly easy. Various other colleagues experimented with RESTLET (http://www.restlet.org/) and Jersey (https://jersey.dev.java.net/). But as I wanted to use Hibernate easily and I was using Spring MVC to build the client component of the project I was working on, so I used Spring MVC to build the services. Pretty simple. (Even though I refer to Spring 2.5 in the pom file, I am not using the features of 2.5.)
Here's an example:
I have created a simple webapp using maven. The webapp is called rest-webapp. I have created a stupid service that retrieves the name of an evil programmer.
This means that the request would look like:
http://localhost:8080/rest-webapp/evil/programmers/1
and this would return:
I wrote a simple class that does this and also returns a 404 error if the request for tne evil programmer does not exist.
This means that the request would look like:
http://localhost:8080/rest-webapp/evil/programmers/6
would return a 404 error with the message: HTTP Status 404 - This evil programmer does not exist!!
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>2.5</version>
</dependency>
web.xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<!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>rest-webapp</display-name>
<description>Test Rest Service</description>
<servlet>
<servlet-name>mytest</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mytest</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>1</session-timeout>
</session-config>
</web-app>
mytest-servlet.xml (Spring Application Context)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/evil/programmers/*">myController</prop>
</props>
</property>
</bean>
<bean id="myController" class="au.bandaid.programming.controller.MyTestController">
</bean>
</beans>
MyTestController.java
package au.bandaid.programming.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;
import au.bandaid.programming.exception.HttpStatusException;
public class MyTestController implements Controller {
private Hashtable
public MyTestController() {
list = new Hashtable
// Set an arbitary list
list.put("1", "Dr Evil");
list.put("2", "Big Bad Billy");
list.put("3", "Big Bad Billy");
list.put("4", "Stevie Exception");
list.put("4", "Frank Void");
}
public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception {
// Determine the type of method
try {
if (request.getMethod().toUpperCase().equals("GET")) {
writeResponse(response, "text/xml", HttpServletResponse.SC_OK, get(request));
}
//else if (method.toUpperCase().equals("POST"))
//else if (method.toUpperCase().equals("DELETE"))
//else if (method.toUpperCase().equals("PUT"))
else {
throw new HttpStatusException(HttpServletResponse.SC_NOT_IMPLEMENTED, "Operation: " + request.getMethod() + " not supported.");
}
}
catch (HttpStatusException e) {
response.sendError(e.getStatusCode(), e.getMessage());
}
catch (Exception e) {
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
}
return null;
}
private String get(HttpServletRequest request) throws HttpStatusException {
// Grab some parameters
// I am not using any now
String type = request.getParameter("type");
// Look at the request
// am expecting rest-webapp/programmers/1
Pattern p = Pattern.compile("[1-9]+");
Matcher m = p.matcher(request.getPathInfo());
String index = "";
if (m.find()) {
index = m.group();
}
if (!list.containsKey(index)) {
throw new HttpStatusException(HttpServletResponse.SC_NOT_FOUND, "This evil programmer does not exist!!");
}
return "
}
private void writeResponse(HttpServletResponse response, String contentType, int statusCode, String ouput) throws IOException {
response.setContentType(contentType);
response.setStatus(statusCode);
PrintWriter out = new PrintWriter(response.getOutputStream());
out.println(ouput);
out.close();
}
}
Some extra reading:
http://jira.springframework.org/browse/SPR-4419 - Comprehensive REST Support
http://springframework.org/docs/MVC-step-by-step/Spring-MVC-step-by-step.html