Category Archives: Rest

Code4Lib 2009

In 2009 I attended the Code4Lib Coneference hosted at Brown University.

I presented on RESTafarian-ism at the NLA. Click on the link see the slides and video.

“Two years ago the National Library of Australia decided to go the route of SOA, particularly REST web services. Since then we have developed a stack of them for varying projects. This talk will expose a few of those services (that provide MARCXML, MODS, METS, Identity information and Copyright Status), highlight some of the technology choices and give some idea of the success of this approach.”

It was really fun to hang out with fellow developers from the Library domain. The Code4Lib community is rather interesting too.

REST in Spring without using Spring Webservices

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 Evil

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 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