I quite like using Spring. Especially when using the Spring/Hibernate combo.
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:
Dr EvilI 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.javapackage 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 list; 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 "" + list.get(index) + ""; } 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