New Website

When I posted my article on creating a RESTful SOA it occurred to me that my own website was badly abusing every architectural direction that I was advocating. I decided to put my architecture to the test by creating a RESTful SOA for my own website. While I’ve recently applied the RESTful SOA to enterprise web applications I’ve never applied it to something so small.

So, I created a FrontController, ResourceLookup, and a full MVC utilizing a RESTful SOA written entirely in PHP and all for this one site! I even decided to keep the code backwards compatible with PHP4, so I didn’t get to use the cool reflection capability in PHP5, but I wanted to prove that I can still apply proper SOA fundamentals to PHP4.

I kept things simple and even managed to remove all dependencies to MySQL (which my previous site utilized). I only have three types of resources so it was relatively easy coding.

The end result: everything you’re seeing here can be represented as a web page, or as a service to be manipulated using HTTP methods, or as a news feed. I also added a text representation, which doesn’t serve much of a point except for demonstration.

The framework only took me a few hours to create, which was great, as it proves that a RESTful SOA is a flexible architecture that applies to web applications small and large. The problem was, I spent an entire weekend editing stylesheets, creating a new look and feel, and basically redesigning the entire site! That last part took longer than I wanted, and I’ve still got some bugs to work out.

Creating a RESTful SOA

I’m going to keep this discussion purposely language agnostic, however, I currently have two projects where I’m implementing a complete RESTful SOA (Service Oriented Architecture). One in J2EE, with a Model 2 architecture using Servlets, JSP, Oracle, and XSLT for the presentation-layer transforms. The other project is LAMP-based (Linux, Apache, MySQL, and PHP) using mod_rewrite and a custom front-controller.

It’s worth pointing out that a service-oriented design is different from object oriented design; and further, these two concepts are orthogonal to RESTful web applications. The PHP application I’m working on is not object-oriented (OO) while the J2EE project is rigorously OO. Both projects follow the same RESTful SOA pattern that I am presenting here.

Both projects have elements of aspect-oriented design (AOD), such as the authorization and logging aspects. I’m going to avoid this topic, and instead focus on the specifics of a RESTful SOA, but if you’re interested it’s worth understanding AOD as a way to compliment the traditional object-oriented design principles that don’t often lend themselves to things like REST.

On with the architecture!

Context of Use

The first step in building a RESTful SOA is to understand, and even better, document your context of use. An easy way to do this is to create a spreadsheet with three columns: Roles, Environment, and Goals. Create a list answering the following questions:

Roles: Who is going to use this site?
Environment: Where are they working?
Goals: What are they trying to do?

This is a simple exercise that is often overlooked. Ignoring this will just give you more work and a crappy product. The beauty of a RESTful SOA is that it provides resources that map to the different types of users and their goals. Don’t add anything beyond what your users need to do. You’ll find yourself making simple pages that provide a positive user experience.

Resource List

Walk through your context of use and create a list of content categories that meet your users goals. Even if you’re dealing with advanced applications, don’t complicate this process, tackle each of the users goals separately with different content sections.

Create a simple file hierarchy representation of your content, mapping closesly to your users and their goals. Here’s an example snippet:

/
/support
/admin
/it
/support/cases
/support/cases/num *
/support/request
/support/metrics

The REST is easy

You’ll find that in this process you’ve listed all of the resources that are needed to fulfil the needs of your users. Don’t invest your time into a CMS or a portal, the next step is to build your own application. You’ll find that a RESTful SOA will be quicker to build than configuring “Hello World” in a jsr-168 portlet!

Front Controller

This is critical, avoid JSF, and stop inserting random code into your html via JSP or PHP or whatever. You’ll want one small program that intercepts all traffic. Every language has a different way of doing this, whether you have to use mod_rewrite or servlet-mapping I don’t care; but funnel everything into one program and grab the path:

  class FrontController {
    path = getPathInfo();
    ...
  }

The Method Matters

The beauty of REST is that we leverage HTTP, URI, and our own web-server to do most of our work. Your front controller needs to process each RESTful HTTP method (GET, POST, PUT, DELETE) separately. Also make sure a request object gets passed in (query string, post variables, cookies, etc). You should have something like this:

  class FrontController {
    path = getPathInfo();
    ...

    function handleGet(path, request) {
      ...
    }

    function handlePost(path, request) {
      ...
    }

    function handlePut(path, request) {
      ...
    }

    function handleDelete(path, request) {
      ...
    }

  }

KISS your CRUD Goodbye!

I should say CRUDL (Create, Read, Update, Delete, List), but that didn’t sound as cool. The next step is to parse your path, this varies from one application to another, but generally your path will contain what I like to call a “resource” followed by “input”. For example:

/support/cases/50

50 is not a resource! However, /support/cases most certainly is. Also, if the user goes to /support/cases, I should be showing them a list of cases rather than details about a specific case.

The simple way to solve this is that when you process your GET request and you haven’t been given any “input”, just a resource name, you’ll want to call the “List” method rather than “Read”. This keeps it simple and very, very RESTful.

Put the DAO to REST!

The astute reader may have noticed I glanced over how you’re suppose to derive a resource and an input from a sigle path. Well, REST assured, this is trivial. Create a simple data model with a Resource entity that maps to itself (one-to-many) to allow for multiple children resources. So, “/support/cases/50” would involve two entries:

+-------------------+
+ NAME    | PARENT  |
+-------------------+
+ support | NULL    |
+ cases   | support |
+-------------------+

Obviously, you’ll want to use unique numeric IDs so you don’t have name collisions, but you get the idea. This will allow you to lookup unique resources and an optional input parameter. The “resource” entity should also contain things like “Title”.

The children resources represent the sub-elements that you may want to appear on a menu navigation. So you’ll want to keep these handy also.

Finally, you now have a unique resource, with optional input and one of four HTTP methods. This all maps nicely into one pretty package, which should be something like:

  class RESTController {
    path = getPathInfo();
    resource = getResource( path );
    input = getPathInput( path );

    function handleGet(resource, input, request) {
      if ( empty(input) )
        resource.list( request );
      else
        resource.read( input, request );
    }

    function handlePost(resource, input, request) {
      resource.update(input, request);
    }

    function handlePut(resource, input, request) {
      resource.create(input, request);
    }

    function handleDelete(resource, input, request) {
      resource.delete(input, request);
    }

  }

Presentation and RESTful Content

Probably one of the biggest architectural mistakes you’ll find with web applications is an incorrect MVC abstraction. It’s easy to say “Model, View, and Controller”, but rarely is this done right. Typically the architecture looks pretty, but on close strutiny calls for tightly coupled templates with functions that belong in the model. Do yourself a favor, don’t let your view talk to your model.

You’re already using XML

Whether you like it or not, you’re on the web, you’re producing html for your content and hopefully keeping your presentation in css. The great thing about XML isn’t that it’s easy to parse or to read. I hate XML, it’s ugly, stupid, and slow to parse. What it is good at is transforming from one schema to another (via things like XSLT).

When you ask your model for a “read” or a “list” operation, you should be getting back pure conent. Content in the form of XML. This is content without a presentation, and it belongs in your model not in your view!

Putting the Representational into REST

If your model is dumping out content in the form of XML, the only thing left to do is for your fancy front controller to transform this XML into whatever representation that the user asked for! It’s a good idea to make the default representation html. The code should now be looking like this:

  class RESTController {
    path = getPathInfo();
    resource = getResource( path );
    input = getPathInput( path );
    view = new ViewDispatcher( request.getType() );

    function handleGet(resource, input, request) {
      if ( empty(input) )
        model = resource.list( request );
      else
        model = resource.read( input, request );

      output = view.transform( model );
      print output;
    }

    ...

That’s it, you can take your presentation-less content and transform it into anything you want (html+css, flash, pdf, plain text). You could even make it a SOAP envelope, autogenerate a WSDL and now you have REST and SOAP without doing any extra work!

So there you have it, this is the basis for a RESTful SOA, that if done right, will allow you to build really cool web applications. Since it’s RESTful, every resource is accessible in a browser, or as a service to an API, or whatever REpresentation you want!

Funny thing, it seems that the whole point of REST is to do MVC the right way, and de-couple everything. I’m not sure why all the big CMSs and portals claim to follow an MVC (or Model 2) architecture but fail to provide a decoupled view.