Skip to main content

Phobos Meets Atom, REST

Posted by robc on November 14, 2006 at 12:50 PM PST

In the Phobos CVS repository you'll now find an implementation of the Atom Publishing Protocol v9. The application name is atomserver. Since we started this work, the APP specification moved up to version 11, so we have some catching up to do, but I thought I'd discuss some interesting aspects of the implementation anyway.

First, it uses some new REST libraries we've been developing. Phobos is a URL-centric framework, so the way you go about designing your application is by defining the kind of URLs you are interested in and attaching logic to them. Typically, URLs map to complete web pages or to AJAX callbacks, but they can really be anything. Fitting REST into this model wasn't very hard.

At startup, the application registers certain URL patterns, e.g. /collection/@id, as belonging to resources. When a request for a resource arrives, the system instantiates a resource object via a factory, then lets it do its job. In the case of a collection, the factory function creates an instance of a CollectionResource class initialized with the id specified in the request URL. So if the request is for /collection/12, the application creates a CollectionResource with an id of 12. The collection id is then used as a key to look up feed information in the database.

The resource base class contains all the boilerplate code to deal with GET and HEAD requests, and all you need to do in a subclass is to return the appropriate representation of the underlying resource, an entity in Phobos/HTTP terms. (Of course, updates and especially POSTs, are going to be more involved.)

Here's a snippet showing the method that creates a collection entity (an Atom feed):

        prototype.getEntity = function() {
            log.trace("atom.CollectionResource.getEntity");
            var info = module.persistence.fetchCollectionInfo(this.id);
            if (info == undefined) {
                return undefined;
            }
            var doc = this.createFeedDocument(info);
            return new library.rest.ConcreteEntity({
                type: "application/atom+xml; charset=utf-8",
                text: doc.toXMLString(),
                lastModified: info.lastUpdated
            });
        }

It's worth emphasizing that there is no controller in the loop: requests are directly handled by resource objects. This is a departure from other frameworks, which route every sort of request via a single controller framework. In Phobos, we decided to model REST directly, by building some new libraries from the ground up to capture the peculiarities of the REST model, rather than retrofitting it in the existing controller framework. Besides simplifying things by shifting more of the work to the framework classes, we hope this will get developers who really want to do REST to think twice before embedding verbs in URLs, e.g. /photo/123456;rotate or /shopping_cart/1234;checkout (I'm referring to this article, by the way).

Another notable aspect of the APP server is the heavy use we make of E4X. I have to admit that, in the beginning, I was very skeptical about it. Somehow, XML and programming languages don't go together very well. I have a theory that the origin of this problem is the dual nature of XML itself, as reflected in its twin uses as document markup (e.g. Docbook) and to represent data structures . Now, after several months of use, I think that E4X is a very powerful tool for processing XML. I'm still not entirely convinced by the syntax, which can sometimes be confusing, e.g. for queries, but it's certainly a big step forward from the DOM API and all its surrogates (DOM4J, JDOM, etc.). You'll find plenty of examples in our Atom server code.

Related Topics >>