Resource vs. Service Oriented Data Design
December 7th, 2006While I’ve been touting the benefits of CXF’s RESTful HTTP binding a lot lately, I don’t know that its RESTful enough. One area we haven’t even touched yet is linkability. In my examples I’ve been using a CustomerService which gets/adds/updates/deletes customers. I’ll continue this trend here as well as I look at how I would design my data structures differently for services and resources.
Service Oriented Data Design
While there are many ways to design this, I’m going to chose one that highlights the differences best. Here is what I might design my Order and Customer objects to be:
<element name="Customer">
<complexType>
<sequence>
<element name="Id" type="xsd:int"/>
<element name="Name" type="xsd:string"/>
</sequence>
</complexType>
<element>
The important part to highlight here is the customer id. It allows me to reference/retreive/update/delete a customers in various operations. In RPC terms: getCustomer(“1″) or RemoveCustomer(“3″).
Resource Oriented Data Design
With HTTP we really don’t have any operations per se, but we do have URIs. And most likely we’re going to have a resource for reach customer and order. The question is – do we even need to share an ID any more? I’m not sure I really see any point. This leaves us with:
<element name="Customer">
<complexType>
<sequence>
<element name="Resource" type="xsd:anyURI"/>
<element name="Name" type="xsd:string"/>
</sequence>
</complexType>
<element>
Or a possibly better version would use an xlink:href type (someone should create an xlink schema type – I haven’t seen any around…). Additionally when I access the /customers resource, I don’t think I really want to return collection of all the s. I want to return links to them:
<Customers>
<Customer xlink:href="http://acme.com/customers/1" mce_href="http://acme.com/customers/1" />
<Customer xlink:href="http://acme.com/customers/2" mce_href="http://acme.com/customers/2" />
</Customers>
There are plenty of other differences too, but I think this will do for now.
Supporting Resource Oriented Data Design at a Client/Server Level
Minor difference? I don’t think so. Both SOA and ROA end up having the same functionality. But there are differences in maintainability, versioning and other aspects. At this point though I’m more interested in how implementing linkability would look from a CXF point of view. If you’re going to truly support resource data design it deeply effects the APIs as now we are concerned with both constructing and using URIs.
From the client side of things, I don’t know how many options we have. Abdera did a good job creating a client API that is similar to what I might do:
public interface Client {
ClientResponse get(String uri);
ClientResponse delete(String uri);
ClientResponse put(String uri, Base/InputStream/RequestEntity input);
ClientResponse post(String uri, Base/InputStream/RequestEntity input);
...
}
I personally might change that to include some nice generics, but that is beside the point. One can see how with this type of an API I can easily do CRUD type operations on my customers:
Customers[] customers = client.get("/customers");
Customer c = customer[0];
client.delete(c.getResource());
On the server side things get a little more tricky. Now I have to worry about URI creation.
Customer getCustomer(String id) {
String uri = URIContext.createURI("/customers/" + id)
Customer c = createCustomer(id);
c.setResource(uri);
return c;
}
Or we could have a slightly more RESTy version which instead parses the URI:
Customer get(String uri) {
String id = parseId(uri);
Customer c = createCustomer(id);
c.setResource(uri);
return c;
}
As you can see this would be quite different from how I might create a database model. Its not key based, its URI based. This means that from the outset of creating my service, I’m forced to create a mapping between the two concepts. One of the things I like about XFire is that I can quickly prototype a service and have a .NET client running with it in 5 minutes. This is partly because of WSDL but also because I tend to use ID based data models internally and that maps well to an operation/message oriented view of the world.
I’ve been thinking about how to automate linkability so a developer doesn’t have to think too much about it. But I’m not sure that the annotation or convention based route of mapping operations and schemas for services can achieve linkability. We can certainly do simple things with annotations/conventions like the mapping of an operation to a URI/verb combo. Going further probably requires a different way of building up resources though (I’m open to ideas if you have any).
Closing Thoughts
After writing this down, I can see why WSDL/SOAP are pretty popular. The concepts of operations, or distributed objects if you’re cynical, map directly to modes of development that most developers are very familiar with. If you’re going for a true resource oriented architecture, it is a bit of a mental shift (not a bad one, just a shift). And people are reluctant to shift. Hence my obsession with finding ways to do this right which are natural to developers.
December 14th, 2006 at 7:34 am
ROA
Daniel Diephouse has written a good piece beginning to explore some of the differences between thinking SOA and thinking ROA and what this means in practical terms. This is good stuff and we need lots more like this. http://netzooid.com/blog/2006/12/07...
April 26th, 2007 at 11:51 pm
[...] But there is something very nice about a uniform interface, URLs, etc. I will agree that proper resource oriented data types do make a big difference, but the issue to me is how do I even communicate that some datatype is [...]