Hypermedia and HATEOAS: Client/Server Relations

JANUARY 29, 2014

My Goal is to Make Changes Easier

So, I started writing a fully HATEOAS web service API. It's funny, I am not designing this new API for any external developer community. I am designing it for myself. My hope is that it will make my life easier, but also that other developers may be encouraged to use our service in the future. I am facing changing business rules, an ever evolving state machine, and some very interactive services. I am designing an online College/University recruiting and application service. My goal is to make my life easier by creating a consistent set of semantic elements that I can add remove, and move around to generate UI for our University and Student users.

I Already Have an Application Model

The basic application models are: students, admissions officers, schools, applications, form cards, and info cards. There are authentication rules for some services, and several domain specific semantic regularities: like paged search results, 320 pixel wide display cards, navigation links, html form cards, administrative links, nofollow links, and a few more semantics specific to my application domain. My goal is to encapsulate all of those semantics into a domain specific media type, a hypermedia API, a HATEOAS server, a client side schema crawler, and a client side GUI client.

I Wasn't Starting Over From Scratch, But...

I started over from scratch. I wanted to simplify the process of understanding HATEOAS constraints and application modeling. Originally, I tried to refactor my existing website into an API, by RESTifying the existing models, but I ran into permission and state machine issues. I began considering building a permission model into each of the models. The more I tried to refactor, the more complex the API spec became, and the fewer problems it solved. So, I started by creating a new repository, and building each low level piece of my puzzle from scratch. I did not choose a framework to seed from, because I wanted to fully understand the reality of the challenges. I needed to be able to optimize for performance and also to add customizations easily without constraints often introduced by frameworks that are not fully baked. In the HATEOAS world, I found very few frameworks that felt more than half baked. So, I started over from scratch.

Top Down, In Through the Front Door

After all this work is being presented to an end user, our customers and clients. I wanted to approach it as though through their eyes, iterating on my designs, and seeing functionality grow organically from a root URL, but I also wanted a lean way to keep that growth restricted to functional growth, and not concern myself with adding "features," as a University of Texas engineering professor once warned us of. Features kill an application, they obfuscate functionality by decorating it with compromises and quick fixes to business problems. They are a stop gap to business needs, and not a solution. I endeavor to generate an lean and functionally complete Client and Server application that uses the advantages of Hypermedia. The first thing to do was to be able to navigate my API like an end user. I started with a very basic UI, with all the links manifested as buttons along the left edge of the screen, and all the data rendered as plain JSON.

An example screenshot of my early Hypermedia client app

That was the beginning of something great. I could not prototype out the user experience very quickly. I could add and remove navigation links and see the data at each endpoint, as well as evaluate how easy and friendly it was to get there. That was just a start. Links are very powerful in an API, because they provide a way to control the state model of the application. You can see FIelding on this topic for more detailed and thorough analysis. Links will become the foundation for my API, because I want to build an interactive experience, not just an amalgamation of data. I want to guide my users to what is right, like Steve Jobs once said:

"people don't know what they want until you show it to them." - Steve Jobs
In Creating Something So Basic, Such Profit

AT this stage I didn't have anything worth really showing to a client or customer. nonetheless I insisted to my business partner that what we had we should be able to show to customers or clients, in all it's basic simplicity. After all our customers and really every user is essentially after functionality, and until I can offer that, beauty is just decoration on a bad service.

Oh, to take a few step back: at this point I had an API that return json/application media data on GET requests, and json-hyper-schema media (http://json-schema.org/latest/json-schema-hypermedia.html) on OPTIONS requests. At this point I had a schema.js crawler that could parse links in the root of the schema and put them into an array structure. I had a client.js application that could render those links using AngularJS templates and some ng-repeat directives. I was just showing the raw JSON on the page (in grey above). This got me started.

I started to work on the mechanisms for parsing out links at deeper levels of the schema, and then interpolating the data at the GET request into the schema to generate dynamic link titles, hrefs and rels. Those two issues were the most important in the beginning: find all the links and interpolate data into those links. (See Angular Interpolation and JSON-Hyper-Schema Links for more on interpolation and links). This was the core of the work.

With this basic functionality I could begin to distill my application into simple components. It's amazing how restraints can define and refine your work. I needed a few things, some of which are: navigation, forms, data display, and authentication. Everything else is decoration of a very basic service. So, I started by making that basic functionality work the way I expected it to, and the way I thought our customers would expect.

Fast Forwarding Two Months Later, Amazing Progress

My entire application uses a single 305 line HTML template, one 430 line javascript schema parser, and one 166 line javascript Angular client application to do the majority of the client side work. Almost everything else is either an API endpoint, a JSON Hyper Schema, an Media Type: HTML, JSON, CSV, or other representation of data: which is generated and sent from the API server in response to client requests, dynamically generated by a combinations of schema crawling and user interaction.

Check it out at http://api.psprt.com and on GitHub at https://github.com/bpanahij/passportedu_schema

The latest version of the Hypermedia Client