I work on ERP applications for a living, so I tend to see lots of ways business intent is manifested in an API. For the past few years, I’ve been trying out different architectural ideas to merge the success of the Web to enterprise application API development. The two aspects that have garnered the most payback have been (a) casting the data domain as a hypermedia set and (b) rationalizing constraints around GET, PUT, and POST to convey business intent and manage work. This blog entry is about (a). Making the data domain flexibly addressable is critical to workflow and EAI, which in turn makes it critical to SOA -- no matter how REST or WS-* might be utilized.
Most reasonably normalized databases already have clear semantics for referential data and child data. Reference columns link tables together by record ID. Child tables inherit the ID of their parent plus their own additional anonymous key value. The referential aspects form hypermedia-like links and the parent-child aspects provide document scope (not to mention the nice fit with XML).
Putting these together means that we can map a record as a URL using the same key values that identify records in a database. We can also extend the URL format across referential values. Here are some examples from an implementation we put out several years ago:
url://MySite/orders/101.xml returns the XML representation of order “101” in all its glory (details and all)
url://MySite/orders/101/1.xml returns just the first line item of order “101”.
url://MySite/orders/101/CustomerID.xml returns the ID of the customer
url://MySite/orders/101/CustomerID/Customer.xml returns the entire customer record for the customer identified in the “CustomerID” link
The last item is the most significant, because you can traverse the entire data domain – if the linkages exist – and access data many degrees of separation away from your starting point. We’ve been doing this for several years now in Business Process Management (BPM) architectures because the data one needs to make a business policy decision is rarely in the message. In other words, workflow-driven architectures need expression formats that bind the data in question with data already in the system.
For example, an administrator might set a policy to disallow orders for items belonging to a product class that itself is under approval hold by, say, the U.S. FDA.
Or, you don’t want to allow orders for customers on credit hold: url://message/orders/CustomerID/holdnotices/credit.xml
Note the “message” bit rather than “MySite” in the previous examples. The idea is to not only traverse entities in a database – it’s also to traverse from the message payload to the database in one expression. Non-programmers can actually read this and figure out what it’s doing. That capability is important in BPM because line managers control the policies in force. Line managers understand hierarchies like directory structures. The key is to keep the URN constructs uncluttered and simple.
That seems straightforward, but you have to work out how to pipeline referential constructs through the entity chain for multiple situations: inner-join, outer-join, existential, etc. You also have to work out how to constrain certain kinds of URLs that bring back too much data. Our initial work let you do something like this: url://MySite. It spit out every record in the database.
BTW, you can swap “.xml” for “.xsd” and get a schema for the results. You can also use “.htm” to get an HTML rendering. In fact, you can go to town with MIME types and style sheets to provide lots of viewable interpretations of whatever data is being sought. That’s pretty powerful.