|
First, let me apologize for my lack of posting. I've been really busy taking up to 4 night classes per week and I'm working on a super ultra-top-mega secret book project with a friend and colleague. The only hint I can drop is that the book is going to kick ass. Look for more details soon!
Now, on to REST. I don't need to go into too much detail here about what exactly REST is - I know that most of the readers of this blog are well versed in Web Services technologies and architectural patterns. The thing that I want to cover is that REST is an architectural decision, it is not a protocol or a wire format or even an industry standard. It is a set of recommendations for how you organize the information exposed by your Web Services. Before I go into detail here, I personally think that REST is the way to go. Unless you have a particular need to be strapped into the SOAP/WS-* roller coaster, your Web Service should be exposing resources via RESTful URLs. I can't imagine why people would chose not to do so.
Here's a quick summary of the main tenets of REST in case you're not familiar with the concept:
I could attempt to summarize why I like REST so much, but instead there's a quote from Fielding's paper (which I believe is also in Wikipedia) that does the job way better than I could:
REST’s client-server separation of concerns simplifies component implementation, reduces the complexity of connector semantics, improves the effectiveness of performance tuning, and increases the scalability of pure server components. Layered system constraints allow intermediaries—proxies, gateways, and firewalls—to be introduced at various points in the communication without changing the interfaces between components, thus allowing them to assist in communication translation or improve performance via large-scale, shared caching. REST enables intermediate processing by constraining messages to be self-descriptive: interaction is stateless between requests, standard methods and media types are used to indicate semantics and exchange information, and responses explicitly indicate cacheability.
Before getting into the example, I feel the need to again state that REST is not a wire format. You cannot compare REST to SOAP, or REST to POX, or REST to JSON. They are not the same type of animal nor do they solve the same kinds of problems. REST is an architecture for designing distributed applications that calls for universally and uniquely addressable resources.
Let's take a look at a sample of what RESTful URLs might look like. In this sample, let's "RESTify" a help desk service. This help desk service is responsible for managing support tickets. Each support ticket also has a list of work items that contain a log of the work done by support personnel on that ticket. The help desk service also needs to support searching, but in a RESTful manner. This is done by considering the collection of search results to be its own resource. Here are some sample RESTful URLs:
| URL | Method | Presumed Action |
| /helpdesk/tickets | GET | Returns a list of all help desk tickets |
| /helpdesk/tickets/100329312 | GET | Returns a payload representing just the ticket with a primary key of 100329312. |
| /helpdesk/tickets | POST | Creates a new ticket based on the payload in the HTTP POST body |
| /helpdesk/tickets/100329312 | PUT | Modifies the ticket with ID of 100329312. |
| /helpdesk/tickets/100329312/workitems | GET | Retrieves a log of all activity belonging to the given ticket. |
| /helpdesk/tickets/100329312/workitems/15 | GET | Retrieves work item #15 belonging to the given ticket |
| /helpdesk/tickets/100329312/workitems | POST | Creates a new work item for an existing ticket |
| /helpdesk/tickets/100329312/workitems/15 | PUT | Modifies work item #15 |
| /helpdesk/tickets/100329312 | DELETE | Deletes ticket 10032912. Assumed that all related/child data will also be deleted in this operation. |
| /helpdesk/tickets/searchresults/bob | GET | Runs a keyword query against the phrase ‘bob’ on all tickets in the system |
Another common use of REST is to use a slash (/) or semi-colon (;) to further subdivide a resource into views. For example, if you wanted to look at the list of helpdesk tickets but you wanted the "newunassigned" view (which is a really handy view to have!), then you might use the following URL:
/helpdesk/tickets/newunassigned
or
/helpdesk/tickets;newunassigned
A lot of Ruby folks seem to dislike the semi-colon syntax as they think it's "old school", but I like it as it visually distinguishes between a sub-view of a resource and an actual sub-resource. This gives different weight to the "newunassigned" sub-view than a sub-resource like "orderitems".
So how do you go about taking a problem domain and converting it into a service that adheres to RESTful architecture principals? Here's a few guidelines that I use when doing this myself:
So what does all this mean and why am I posting this? The Web Services scene has changed tremendously since I first started this blog a couple of years ago. A couple of years ago I didn't know much about REST, I wasn't doing anything with social networking, and most people in the industry were thinking, "Web Services? WTF. Just another stupid fad." They couldn't have been more wrong.
So now I'm taking my thoughts on Web Services applications from having spent the last 6 years of my life building them. I remember back in the good old days when they weren't called Web Services and what we were doing was "hacking HTTP to take XML payloads", probably because we were building distributed systems that couldn't communicate properly via DCOM or CORBA. We've come a long way since then and I want to do this series of blog posts covering my thoughts on Web Services as they stand now. This is all my own personal opinion, so feel free to ignore it or flame it, I'm doing this as much for my own edification as I am for yours ;)
Enjoy, and more posts will be forthcoming!