A Recipe for building RESTful Services

For a small project in my Master program I was in charge of building some RestFUL services for a fictional –an minimal- College Library. The clients we’re supposed to be a Mobile .NET Application and a Web Application built in PHP, being the only requirement that the data payload should be XML documents. Building that small piece of software teach me some things about building RESTful Services , and I like to share some of them in this post.

You need to select an environment

So I needed a hosting that has Java Support (because I’m a Java guy) and that also has no cost (because I’m poor), so I selected Google App Engine because it fulfills all this requirements. Then, the natural IDE Selection was Eclipse with the Google Plugin because it included some features that ease the deployment and development of software for that environment.

You need to select a Persistence Framework

Using Google App Engine, a relational database wouldn’t be available for free. so you so with that you can discard every  popular ORM Framework in the Java World (like Hibernate and friends). Google App Engine works with a Non-SQL repository called App Engine DataStore, and the SDK offers you the possibility to access it through JPA or JDO. Personally, I found that accessing the DataStore through JPA added artificial complexity to the code, complexity proper of a RDBMS solution that’s not necessary in a Schemaless product like the DataStore. So my choose was using Objectify, a simple-to-use framework based on the Low-Level API to access the DataStore. With the DAO implementation suggested by David Chandler, my data access layer was composed by only this class:

package pe.edu.pucp.dao;

import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import pe.edu.pucp.model.Book;
import pe.edu.pucp.model.BookReservation;
import pe.edu.pucp.model.Student;

import com.google.appengine.api.datastore.QueryResultIterable;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.ObjectifyService;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.util.DAOBase;

/**
 * @author cgavidia
 *
 */
public class LibraryServiceDAO extends DAOBase {

	public static final Logger LOG = Logger.getLogger(LibraryServiceDAO.class
			.getName());

	static {
		ObjectifyService.register(Book.class);
		ObjectifyService.register(Student.class);
		ObjectifyService.register(BookReservation.class);
	}

	protected Class clazz;

	public LibraryServiceDAO(Class clazz) {
		this.clazz = clazz;
	}

	public Key add(T book) {
		Key key = ofy().put(book);
		return key;
	}

	public void delete(Key key) {
		ofy().delete(key);
	}

	public T get(Long id) throws NotFoundException {
		return ofy().get(clazz, id);
	}

	public T get(Key key) {
		return ofy().get(key);
	}

	public List listByProperty(String propertyName, String propertyValue) {
		Query query = ofy().query(clazz);
		if (propertyName != null && propertyValue != null) {
			query.filter(propertyName, propertyValue);

		}
		return asList(query.fetch());
	}

	private List asList(QueryResultIterable fetch) {
		ArrayList list = new ArrayList();
		for (T t : fetch) {
			list.add(t);
		}
		return list;

	}
}

You need to select a RESTful framework

Handling HTTP requests using Servlets was never in my plans  because of deadlines and because I’m lazy. I have to make sure that the framework I choose has support Google App Engine because it is not an standards-compliant Servlet container and has several limitations and restrictions.  A Google search led me to  the Restlet Framework, and easy and simple REST framework fully compliant with the REST architectural style that also has support to Google App Engine. Using Restlet abstractions, all the resources of my application are exposed trough this class:

package pe.edu.pucp.library;

import org.restlet.Application;
import org.restlet.Restlet;
import org.restlet.routing.Router;

import pe.edu.pucp.resource.BookReservationResource;
import pe.edu.pucp.resource.BookReservationSerializer;
import pe.edu.pucp.resource.BookReservationsResource;
import pe.edu.pucp.resource.BookResource;
import pe.edu.pucp.resource.BookSerializer;
import pe.edu.pucp.resource.BooksResource;
import pe.edu.pucp.resource.StudentResource;
import pe.edu.pucp.resource.StudentSerializer;
import pe.edu.pucp.resource.StudentsResource;

/**
 * @author cgavidia
 *
 */
public class LibraryApplication extends Application {

	@Override
	public Restlet createInboundRoot() {
		Router router = new Router(getContext());
		router.attach("/books", BooksResource.class);
		router.attach("/books/{" + BookSerializer.CODE_ELEMENT + "}",
				BookResource.class);
		router.attach("/students", StudentsResource.class);
		router.attach("/students/{" + StudentSerializer.CODE_ELEMENT + "}",
				StudentResource.class);
		router.attach("/reservations", BookReservationsResource.class);
		router.attach("/reservations/{"
				+ BookReservationSerializer.CODE_ELEMENT + "}",
				BookReservationResource.class);
		return router;
	}

}

The RESTful Service code is now available in my Github account, so if you need some extra reference you can find it there.