|
|
A blog of my thoughts on the current beat of the Java drum.
-
This is the third part in a series on Representational State Transfer (REST). The first part makes an attempt at a proper introduction to the principles of REST. The second part discusses about how these principles are applied on the Internet for human consumption (the Human Web) and how they can likewise be applied to computer systems (the Programmable Web). In this instalment, which I’ve broken up into two sub-parts, I want to share a fictional need for a service and then proceed to analyze the requirements and implement it in such a way that caters to both the Human and Programmable Webs. In the last sub-part we went over the requirements for the service and then made an attempt at a design. In this second sub-part, we’ll implement the design and take notes along the way.
While it is not required, I strongly suggest reading the other instalments first (at least the first sub-part that relates to this post) so that a lot of the design decisions I made make sense. It is my hope that you enjoy the ride as much I’m going to enjoy sharing it. Also, you can find the entire source produced in this article here: Season's Greetings Application Code Part One ReviewIn the first part of this instalment, we had a mission statement and then set out to analyse and design the service in a RESTful way. This was our mission text: "It is the holiday season, and we must spread cheer and merriment to one and all, human and machine. Make a service that allows people to request a customizable greeting that they can share with the world, by consequence spreading the love and spirit of the season. Make it simple and easy to deploy and maintain. Make it accessible to simple folk as well as natively in different computer languages to power users out there. Our collective holiday cheer is at stake. Good luck!"We parsed out of the mission text some key things (e.g., human AND machine friendly) and also settled on a technology toolset (e.g., Java, XML). We then designed the service from both the perspective of the business component (the service itself) as well as from the perspective of the web application component that would host our service. We drew up some UML class diagrams for good measure, which we will revisit as we implement the service in this post. To get a full catch-up, read the first part fully. Then you’ll be ready to roll. Our main use case was as follows: 
Let’s make this a reality! Service ImplementationLet’s start with the business service we will implement, so that we can have something to “serve” when it comes time to implement the web application bit. Here’s our design for the service:  We have five classes/interfaces to implement. We could start with the service, but that depends on the greeting model class, which in turn depends on the XML encoder/decoder. That has no visible dependencies, so let’s start there, XMLSerialiser: 1 package com.silvanolte.util; 2 3 import com.thoughtworks.xstream.XStream; 4 5 public class XMLSerialiser { 6 7 private static final XStream XS = new XStream(); 8 9 public static String toXML(Object o) { 10 return XS.toXML(o); 11 } 12 13 public static Object fromXML(String xml) { 14 return XS.fromXML(xml); 15 } 16 17 }
Implementing the to and from XML stuff is really a key bit to our service, and while I could break out Java’s XML APIs to do this parsing on my own in a generic way, I’ll delegate to a third-party library. In this case, I use XStream to handle this messy work. As you can see, this particular library is very easy, and out-of-the-box gives us everything we need. With generic XML encoder/decoder done, let’s do the model object next, Greeting: 1 package com.silvanolte.model; 2 3 import com.silvanolte.util.XMLSerialiser; 4 5 public class Greeting { 6 7 public static Greeting fromXML(String xml) { 8 return (Greeting) XMLSerialiser.fromXML(xml); 9 } 10 11 private String message; 12 13 public Greeting(String message) { 14 setMessage(message); 15 } 16 17 public String getMessage() { 18 return message; 19 } 20 21 public void setMessage(String message) { 22 this.message = message; 23 } 24 25 @Override 26 public String toString() { 27 return message; 28 } 29 30 public String toXML() { 31 return XMLSerialiser.toXML(this); 32 } 33 34 }
I implement this as a simple JavaBean-like model class. The interesting bit to note is how we delegate the XML-related functions to our XML encoder/decoder (lines 7-9, 30-32). We’ve decoupled how we do the XML from the model itself while retaining a clean API to this functionality from right within the object. I also make the fromXML(String) : Greeting factory method static, so that it is bound to the class as opposed to a particular instance. Let’s move on to the service interface now, GreetingService: 1 import com.silvanolte.model.Greeting; 2 3 public interface GreetingService { 4 5 public Greeting getGreeting(); 6 7 public Greeting getGreeting(String name); 8 9 }
Simple service interface that exposes the functions we’re looking for. Three classes down and two implementations to go. Let’s do the core business one first, MyGreetingService: 1 package com.silvanolte.services.impl; 2 3 import com.silvanolte.model.Greeting; 4 import com.silvanolte.services.GreetingService; 5 6 public class MyGreetingService implements GreetingService { 7 8 public Greeting getGreeting() { 9 return getGreeting(null); 10 } 11 12 public Greeting getGreeting(String name) { 13 if (name == null) { 14 return new Greeting("Seasons' Greetings"); 15 } else { 16 return new Greeting("Seasons' Greetings, " + name); 17 } 18 } 19 20 }
This implementation is the one that does our actual greeting. We return a very cheery “Seasons’ Greetings” that becomes “Seasons’ Greetings, ” if a name is provided. Right. Now on to our last class, the remote service client, GreetingServiceClient: 1 package com.silvanolte.services.clients; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 import java.net.URL; 7 import java.net.URLConnection; 8 import com.silvanolte.model.Greeting; 9 import com.silvanolte.services.GreetingService; 10 11 public class GreetingServiceClient implements GreetingService { 12 13 private String serviceURI; 14 15 public GreetingServiceClient() { 16 serviceURI = "http://localhost:8080/greeter-service/" + 17 "greeting.xml"; 18 } 19 20 public GreetingServiceClient(String URI) { 21 serviceURI = URI; 22 } 23 24 public Greeting getGreeting() { 25 return getGreeting(null); 26 } 27 28 public Greeting getGreeting(String name) { 29 String resourceXML; 30 try { 31 resourceXML = getResourceXML(name); 32 } catch (IOException e) { 33 throw new IllegalStateException(e); 34 } 35 return (Greeting) Greeting.fromXML(resourceXML); 36 } 37 38 private String getResourceXML(String name) 39 throws IOException { 40 String localURI = serviceURI; 41 if (name != null) { 42 localURI = localURI + "?name=" + name; 43 } 44 45 URL url = new URL(localURI); 46 URLConnection conn = url.openConnection(); 47 BufferedReader responseReader = new BufferedReader( 48 new InputStreamReader(conn.getInputStream())); 49 StringBuffer response = new StringBuffer(); 50 String line; 51 while ((line = responseReader.readLine()) != null) { 52 response.append(line); 53 } 54 responseReader.close(); 55 56 return response.toString(); 57 } 58 59 }
At 59 lines, this is our biggest class yet! Probably will prove to be the biggest class we have to do. Not surprising, from the standpoint of our discussion, this implementation has the most interesting things to note: - Lines 15-18, 20-22: I provide two constructors and a default URI. This gives the consumers of this implementation the freedom to supply their own URI, which may be useful.
- Lines 28-36: The heart of my implementation simply gets the XML representation of the greeting using a private function, and uses the factory method on the Greeting object to satisfy the return value.
- Lines 38-57: Arguably the most interesting, if not complex, bit. This is where I reach out over the web to get the XML that matters most to the implementation: the Greeting XML representation.
- I noticed that I had not designed for how the name would be passed over the web, and made the decision at this time to pass it as HTTP Parameter (line 31). This is sufficient for now.
- I utilised Java’s
URL and URLConnection classes to make the reach over the web. This completes the service side. As a reminder, you can find the entire source produced in this article here: Season's Greetings Application Code Web Application ImplementationNow we’re ready to build the web application bit. Before we start, let’s review our web application design:  According to this design we have three HTTP Servlets to implement. We also have to map the relevant URIs to the proper HTTP Servlets. Let’s start with the top-level Servlet, GreeterServlet: 1 package com.silvanolte.servlets; 2 3 import java.io.IOException; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import com.silvanolte.model.Greeting; 9 import com.silvanolte.services.GreetingService; 10 import com.silvanolte.services.impl.MyGreetingService; 11 12 public abstract class GreeterServlet extends HttpServlet { 13 private static final long serialVersionUID = 1L; 14 15 private GreetingService greetingService; 16 protected Greeting greeting; 17 18 public GreeterServlet() { 19 greetingService = new MyGreetingService(); 20 } 21 22 protected void doGet(HttpServletRequest request, 23 HttpServletResponse response) throws ServletException, 24 IOException { 25 greeting = greetingService.getGreeting( 26 request.getParameter("name")); 27 } 28 29 }
First of all, you may notice I made this class abstract (Line 12). I did this because I only wanted to consolidate the business of getting the greeting (the model) with the express intent of letting subclasses handle how it routes the model to its respective views (in our case, HTML and XML). Secondly, I account for any name that might have been provided to customise the greeting by checking for an HTTP parameter named “name” (Line 26). Finally, I use the MyGreetingService implementation to get me the greeting I need. This works perfectly. But it is worth noting that I could have just as easily used GreetingServiceClient instead because it is a valid implementation of the GreetingService interface, allowing me to chain-link multiple HTTP calls, in theory. This is pretty powerful stuff. Let’s move on to the HTML Servlet implementation, GreeterHTMLServlet: 1 package com.silvanolte.servlets; 2 3 import java.io.IOException; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 9 public class GreeterHTMLServlet extends GreeterServlet { 10 private static final long serialVersionUID = 1L; 11 12 public GreeterHTMLServlet() { 13 super(); 14 } 15 16 protected void doGet(HttpServletRequest request, 17 HttpServletResponse response) throws ServletException, 18 IOException { 19 super.doGet(request, response); 20 request.setAttribute("greeting", greeting); 21 getServletConfig().getServletContext().getRequestDispatcher( 22 "/greeting.jsp").forward(request, response); 23 } 24 25 }
The most interesting things to note here are between lines 19 and 22. First, I make a call to the super class’ doGet() function, which is GreeterServlet’s doGet() function. And we know that this function puts together our model and places it in scope (through the protected local variable greeting). I then set the model on request scope (line 20) and finally forward the request to a JSP for generating the HTML view (lines 21-22). Let’s take a look now at that JSP, Greeting.jsp: 1 <%@ page language="java" 2 contentType="text/html; charset=ISO-8859-1" 3 pageEncoding="ISO-8859-1"%> 4 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> 5 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 6 "http://www.w3.org/TR/html4/loose.dtd"> 7 <html> 8 <head> 9 <meta http-equiv="Content-Type" 10 content="text/html; charset=ISO-8859-1"> 11 <title>Greeting Service</title> 12 </head> 13 <body> 14 15 <h1><c:out value="${greeting.message}"/></h1> 16 17 </body> 18 </html>
The interesting here to note is the use of JSP Expression Language (EL) on line 15 to pull the message out of the Greeting object. This is made possible because I put the Greeting object in request scope, and through the use of the core Java Server Tag Library (JSTL), which we define on line 4. This will generate the HTML part! Pretty exciting. Let’s now XML Servlet implementation, GreeterXMLServlet: 1 package com.silvanolte.servlets; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 public class GreeterXMLServlet extends GreeterServlet { 11 private static final long serialVersionUID = 1L; 12 13 public GreeterXMLServlet() { 14 super(); 15 } 16 17 protected void doGet(HttpServletRequest request, 18 HttpServletResponse response) throws ServletException, 19 IOException { 20 super.doGet(request, response); 21 response.getOutputStream().print(greeting.toXML()); 22 } 23 24 }
This is very similar to our HTML implementation with the key difference being on line 21. Instead of putting the model object on request scope and forwarding the request to a Java Server Page (something I could have done just the same), I decided to instead pass the XML representation straight to the response output stream. One good reason for doing it this way is that in relying on the service to define the XML, I’m freed of that implementation detail on the web application side. I can focus on the matter of receiving and processing a request, and delegate to the service the matter of creating an XML representation of the model object I get back from it. The final bit is the mapping of URIs to HTTP Servlets. In a J2EE web application, this is done in a file called a web application description. It is named web.xml and while not in our design model, it is an implicit part of the application in that we’re implementing this in Java. Below is the web.xml file for this web application: 1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app id="WebApp_ID" version="2.4" 3 xmlns="http://java.sun.com/xml/ns/j2ee" 4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 5 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee 6 http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> 7 <display-name>greeter-service</display-name> 8 <servlet> 9 <description> 10 A servlet that returns an XML representation 11 of a greeting. 12 </description> 13 <display-name>GreeterXMLServlet</display-name> 14 <servlet-name>GreeterXMLServlet</servlet-name> 15 <servlet-class> 16 com.silvanolte.servlets.GreeterXMLServlet 17 </servlet-class> 18 </servlet> 19 <servlet> 20 <description> 21 A servlet that returns an HTML representation 22 of a greeting. 23 </description> 24 <display-name>GreeterHTMLServlet</display-name> 25 <servlet-name>GreeterHTMLServlet</servlet-name> 26 <servlet-class> 27 com.silvanolte.servlets.GreeterHTMLServlet 28 </servlet-class> 29 </servlet> 30 <servlet-mapping> 31 <servlet-name>GreeterXMLServlet</servlet-name> 32 <url-pattern>/greeting.xml</url-pattern> 33 </servlet-mapping> 34 <servlet-mapping> 35 <servlet-name>GreeterHTMLServlet</servlet-name> 36 <url-pattern>/greeting.html</url-pattern> 37 </servlet-mapping> 38 <welcome-file-list> 39 <welcome-file>greeting.html</welcome-file> 40 </welcome-file-list> 41 </web-app>
The above may be a tad confusing to the non-Java crowd. The key lines to look at are lines 14-17, 25-28 and 30-37, which is where we name our HTTP Servlet classes and then map those Servlets (through their configured names) to URI patterns. Deploying our application with this web application descriptor will give us the results we desire. This completes the web application side. As a reminder you can download all the relevant code here: Season's Greetings Application Code Putting it to the testIf you can and have the know-how, I strongly encourage you to download the source and deploy the Web Application Archive (WAR) file in the /greeter-web-application/build directory (greeter-service.war). This is already built for you, so you can follow along with these examples. You can also build the source, but will require some tinkering with the Ant build script (just don’t edit below the line I asked not to). And if you have no idea what I’m talking about, don’t worry, it’s not required. Just read on. :) I’ve built my code and deployed it to my web application server. To review, let’s remind ourselves of the use case we used to illustrate our high-level view of our service:  Let’s start with the web browser. I fire up Firefox and immediately type in the full URI to the HTML resource for a greeting: http://localhost:8080/greeter-service/greeting.html
The result I get looks like this:  Fantastic! We got our greeting, just as we expected. If we look at the source of the HTML, this is what it looks like: 1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" 2 "http://www.w3.org/TR/html4/loose.dtd"> 3 <html> 4 <head> 5 <meta http-equiv="Content-Type" 6 content="text/html; charset=ISO-8859-1"> 7 <title>Greeting Web Application</title> 8 </head> 9 <body> 10 11 <h1>Seasons' Greetings</h1> 12 13 </body> 14 15 </html>
Great stuff. This was generated by our Java Server Page, Greeting.jsp. We can compare line 11 of this generated HTML with line 15 of the Java Server Page code to see the relationship. The apostrophe at the end of the word ‘Seasons’ was automatically HTML-encoded for us, as well. Let’s try and add a name to the mix, see the personalized result:  It works! The Human Web now has a greeting service, albeit temporarily, that anybody with a browser, access to my network, and the right URI can access. If this were released on the World Wide Web, I could share the URI with anybody with Internet access and they would be able to get their own greeting. Continuing to use Firefox, let’s request the XML representation of our resource, this time using the following URI: http://localhost:8080/greeter-service/greeting.xml
The result I get looks like this:  This is a much different representation of essentially the same data (resource). Firefox has a built-in XML parser, and as such shows you the XML output our application returned, with a warning that there is no style information associated with it. This is fine, as we have no Extensible Stylesheet Language (XSL) file to provide the browser some guidance. After all, this is not meant for human consumption[1]. Let’s add a name to the URI to see the result, and make sure it works:  This is truly brilliant. I wrote my service code only once, and I’m sharing my data in two meaningful ways. To drive this point home, let’s quickly implement and test that command-line Java application that I wanted to write to make use of the service client, GreeterServiceClient. Rather than show the code, I’ll just jump straight into its utilisation. Definitely look at the source to see what I did on this Java application.  This is a screen shot of my console window. I change directories, set a classpath for my Java application and then run it, first without names then customised with names. I output the implementation I’m using to get the greeting. There are two quick things I want to bring to light here: - The output is the same, whether we use the local or remote implementation. There are some serious differences in how we get the data, but it’s still the same "stuff."
- The remote implementation returns a "local"
Greeting object, populated with data found on a "remote" server. I think this is the key to the beauty of REST. It focuses on resource state (data) and delegates the remainder to the client. In this case, the client gets the data, and creates an instance of the object on the client-side, giving a transparency that is seldom lost in the complex layers of frameworks and specifications found in the WS-I stack. ConclusionWell, in my third instalment I’ve done the longest one yet, splitting it into two parts. The upcoming ones won’t be as long, I assure you. But if you’ve hung in there with me, you’ve now been exposed to REST in both a theoretical and practical way. The way we think about data and how we share it is challenged when we consider a resource-oriented approach. Two representations can be completely different (in their format) and yet completely identical (in the resource state it represents) at the same time and in the same relationship. Seems illogical on the surface, but the power of this reality couples with the strengths of the Internet creates a foundation for truly accessible and scalable computing. In my next post I will extend this example by supporting the HTTP POST method and introduce how we might expose a way to change the default greeting service behaviour, RESTfully. I will also add a Ruby-based client to our library of service implementations, to open our service to all those Ruby power users out there. And as I look to close out the series, we will look at implementing the rest of the HTTP methods and investigate some of the frameworks available today to help make your applications RESTfully beautiful. Until next time!
|
-
This is the third part in a series on Representational State Transfer (REST). The first part makes an attempt at a proper introduction to the principles of REST. The second part discusses about how these principles are applied on the Internet for human consumption (the Human Web) and how they can likewise be applied to computer systems (the Programmable Web). In this instalment, which Ive broken up into two sub-parts, I want to share a fictional need for a service and then proceed to analyze the requirements and implement it in such a way that caters to both the Human and Programmable Webs. In this sub-part, well go over the requirements for the service and then make an attempt at a design. In the second upcoming sub-part, well implement the thing. Sounds groovy, eh? While it is not required, I strongly suggest reading the other instalments first, so that a lot of the design decisions I make here make sense. It is my hope that you enjoy the ride as much Im going to enjoy sharing it. RequirementsThis is our mission, if we choose to accept it: "It is the holiday season, and we must spread cheer and merriment to one and all, human and machine. Make a service that allows people to request a customizable greeting that they can share with the world, by consequence spreading the love and spirit of the season. Make it simple and easy to deploy and maintain. Make it accessible to simple folk as well as natively in different computer languages to power users out there. Our collective holiday cheer is at stake. Good luck!"Armed with the power of Java, XML and REST, we should be ready. Lets get to task. We accept! Analysis and AssumptionsThese requirements are a bit vague, but we can extrapolate some key ones: - Greeting service
- Customisable greetings
- Human friendly
- Machine friendly, different languages
We're also going to build our solution using the following tool set, which is easy and familiar to me: - Java
- Java Enterprise Edition (J2EE)
- Hypertext Mark-up Language (HTML)
- Extensible Mark-up Language (XML)
Although we won't be thinking too heavily into technology at this point, it's good to set these assumptions in place, as it will influence how we tackle some of these issues. Service DesignFor the Greeting Service, well define an Interface with a function that will return an appropriate greeting for the holidays. To provide customizable greetings, well add another function that takes a name as input and returns the same appropriate greeting for the holidays but personally addressed as well. Well also define one model object, the greeting itself, with one property that will contain the greeting message. I'll provide two implementations for my service. The first will be a simple implementation, returning a simple holiday greeting according to some set business rule we can define as were writing the code. The second will be my RESTful machine-friendly implementation. It will have a private method to somehow get an XML version of a greeting from a URI over HTTP and use a generic XML encoder/decoder class that we can provide to handle the greeting serialisation to and from XML. Now that I think about these concerns with XML, Ill also add some methods to the greeting model object so that I can easily get an XML representation from a greeting object, as well as add a factory method that would create a greeting object given an XML representation of one. Of course, just like my RESTful greeting service implementation, Ill use the same generic XML encoder/decoder class to provide seamless integration. Those pieces will finish the service side of our task. Heres a UML diagram to help us keep track: 
Web Application DesignWith our service design completed, we know have to think about how were going to expose our service to our human and machine audiences. The MyGreetingService implementation works well if you use Java, but our human audience for the most part does not do so directly. Furthermore, the GreetingServiceClient implementation will only work if theres a URI to use in the first place that would return the XML representation of a Greeting. The answer, given our toolbox, is to create a J2EE Web Application to expose our service as both human readable and machine readable. We can leverage the popular Model-View Controller (MVC) design pattern with J2EE to create a nice system that can handle requests for both the HTML and XML versions of our greeting. Lets start by specifying the following two URIs for our representations[1]: /greeter-service/greeting.html (human readable)
/greeter-service/greeting.xml (machine readable)
We can then map these URI patterns to an HTTP Servlet[2] that will act as the Controller in our design. We could make an abstract HTTP Servlet that handles the business of getting the greeting, and we can create two other Servlets that extend the first one, each returning a different representation, one thats HTML and one thats XML. That way we can map each URI variant to its own HTTP Servlet while reusing the code that does the business of getting the greeting. The HTML Servlet can pass the Model (Greeting) to the Java Server Page (JSP) to generate an HTML View. The XML Servlet can use the functions we defined on the Greeting object to generate an XML representation of it as an XML View. And because the requirements only call for receiving a greeting, well implement the doGet(HttpServletRequest, HttpServletResponse) function on the requisite Servlets to support HTTP GET. (In a future post, Ill go full-bore on supporting all HTTP methods for a purely RESTful service that supports reads and writes.) Those bits help us wrap up the web application side of the story. Lets draw up some more UML to not lose track of these design decisions[3]. 
Before I finish the design, I’ll add scope for one more item. It would be really cool if we had a simple application that used our GreetingServiceClient (RESTful) implementation, which does our HTTP calls to our XML version of our resource. We’ll call it GreetingServiceApplication and implement its main function to utilize our service client. This would be analogous to the web browser for the HTML representation, but programmatic. To be consistent, let’s throw one more UML diagram up illustrating these bits as well: 
Service Use CaseWith the service and web application designs in place, let’s quickly illustrate at a high-level how our service works. Ideally, we want our consumers to make a request of the URI that’s appropriate for who they are (humans through web browsers would request greeting.html while machines would use the client we provide, or otherwise make a request directly to greeting.xml). All requests are made over HTTP using the appropriate URI for the resource they want. 
This should work very well. I’m pleased with this design. We’re satisfying the requirements in a simple and RESTful way. Now we’re ready to dive into the code and make this happen. ConclusionThinking RESTfully, we have designed a service and how we can expose it to different client types. For our human consumers, we can whip out some lovely HTML that they can see through their web browsers. For our machine-based consumers, we will provide an XML representation instead, and will include a client library to make things slightly simpler for our Java-based machine consumers. In the second part of this instalment, we’ll proceed to implement this stuff. We’ll write plenty of code, and go through it bit by bit to explain why we do things the way we do. We’ll even test it out, so everything will really shift from the theoretical to the practical. Hopefully along the way you’ll pick up a thing or two on how to best implement your own RESTful services. It will be fun to do it, so I hope you come back. See you then!
|
-
The Internet is quite something isn’t it? It brings many different pieces of data together through an interface that all of us are familiar with (at least those that read my blog): a web browser. If we need to find the nearest Tube station or but stop in London, we can go to the Transport for London web site. If we wanted the latest news, we can go our favourite’s news provider’s web site, which has all sorts of neat pictures and articles to satiate our hunger. If we wanted to cook something new and interesting for dinner tonight, we can fire up our favourite cooking web site, or, more interestingly, use Google to find what we’re looking for (the latter can apply for most anything you’re looking for on this wild and wacky world-wide web of computers, networks and you).
What I have just described is of course, the Internet. You’re familiar with it. Perhaps you even landed on this post through a search engine hoping to read about Representational State Transfer (REST). It’s (mostly) a fantastic and accessible interface to a library of information from all over the world, all walks of life. Blissfully built upon a RESTful architecture using the Internet Protocol Suite (TCP/IP), Hypertext Transfer Protocol (HTTP), and Uniform Resource Identifiers (URIs) you have what has been referred to as the Human Web[1].
The Human Web
Simply put, the Human Web is the collective set of resources available on the Internet that was designed for human consumption.
Beyond the Internet’s underlying architecture, what makes this possible is the Hypertext Mark-up Language (HTML). HTML is a set of tags that can be used on information to describe its structure. For example, <H1> is an HTML tag to refer to a level one heading. The title of this post is REST: Tale of Two Webs, so I could reasonably do something like <H1>REST: Tale of Two Webs</H1> to convey that the content between the H1 tags is some sort of heading. But how does an Internet consumer see all there is to see on the web and never see these tags? The answer to that lies on the tools we use.
The other side of the HTML coin is the Web Browser. Web browsers, like Microsoft Internet Explorer, Mozilla Firefox, and Apple Safari, are computer programs that take in HTML input and output that data in a way that a human can easily understand, according to the specification published by the World Wide Web Consortium[2]. The Web Browser reads in the <H1> HTML tag, and understands that it should make that content of that tag big, bold, and whatever other styling the browser deems appropriate to represent a Level 1 Heading. (It is worth noting that HTML producers can optionally provide a style guide to the browser as to how to represent any HTML tag on-screen, and the browser user can, in most cases, tell the browser to use provided styling or their own custom styling set up in browser preferences, ignoring the author’s styling suggestion.)
With HTML as the language and the Web Browser as the tool, we can get what we need from the Internet in a way that makes sense to us. Let’s walk through the steps typically used to find something on the Internet:
1. Open a web browser on your computer. 2. Type: http://google.com (this is the URI). 3. Submit the request by clicking GO or pressing the ENTER key. 4. The request makes its way to the server associated with the Google.com host name and a response is returned based on the requester (computer web browser) and URI requested (the root default resource belonging to Google.com): an HTML representation of the Google Home Page. 5. The response makes its way back to the web browser in the form of an HTML document. 6. The browser renders the HTML document to you in a way that you can easily interact with. 7. Repeat from step 2 for another specific URI, click on one of the links presented or submit any forms required and continue from step 4, or proceed to step 8 if you have nothing more to do. 8. Close the web browser.
That’s how a human’s journey on the web typically goes. The Human Web alive and ticking.
It’s hard to argue with the success of the Human Web. The Internet’s resources meant for human consumption is growing and evolving. It started as simple static pages. Nowadays we have personalised content, interactive media, and rich user interfaces within the safe harbours of the web browser sandbox[3]. And there seems to be no limit to what can be done in the Human Web, as full-blown operating systems and office software suites are on the horizon as well.
Yes, humans have it good, don’t we? A strong open architecture underpins a set system where we can go out and get what we need when we need it, all things considered. So at this point, I ask myself:
Is there potential here outside of the scope of human use?
Is there a way that computer systems can leverage this architecture to interact and collaborate?
The Programmable Web
You could point out the work being done by the W3C and the WS-I on the Web Services Stack Specification[4] but frankly, I think this approach is riddled with serious issues. To pick one example, the Simple Object Access Protocol (SOAP) is by all intents a repeat of the HTTP protocol (making SOAP over HTTP redundant), causing the spec to be needlessly complicated (and by consequence difficult to deploy and maintain). Moreover, the WS-I stack is pretty anti-RESTful. It uses the URI more as a point of entry to a set of operations instead of a unique identifier for a resource. And the response you get is typically something more or less what you requested, with enough ambiguity to cause subsequent requests because of lack of information or receiving what you did and didn’t need.
No, this doesn’t look like the Human Web at all. So let’s take a step back from the path that’s been trodden and ask the questions again:
Is there potential here outside of the scope of human use?
Is there a way that computer systems can leverage this architecture to interact and collaborate?
It is from a clean slate and an analysis of the web as it is utilized by you and me through our web browsers that I consider something referred to as the Programmable Web[5]. Similar to the Human Web, it is the collective set of resources available on the Internet, but this time as designed for computing consumption. Imagine being able to programmatically get the data you need, from an internal or external service, just as easily as you do using Google or the like yourself. This is what the Programmable Web looks like. But is it possible? Is it feasible? I think so, and without all the needless complexities as well. To apply the same model as the Human Web to the Programmable Web, we need a similar approach to how we expose our data, along with tools like HTML and web browsers, for our computing platforms. What follows is my take on what we could use to solve both these problems and provide a clean guideline for web services.
Much like a human-intended HTML resource, exposing an API as well-defined URI resources that meaningfully support the HTTP methods is the first step. If I have a User Service, I’m going to want a URI that corresponds to a user. For example, I would have something like http://localhost/my-user-service/user/100 where the /user/100 portion refers to the User with User ID 100. A GET request would return some sort of representation of a specific user, whereas a POST request of the same slightly modified representation will update a specific user. Clean resource exposure through well-defined URIs is the first place to start.
Next, we need a meaningful and effective way in which to encode our representations. HTML works well for the Human Web because it’s a published specification for document parts that allows web browsers to easily implement and render. For the Programmable Web, I submit XML as a good choice for how to encode machine-friendly representations of our resources. XML lets us structure data in a meaningful way both to a human observer and a computer program (via an XML parser). XML over HTTP is easily handled. And XML is also language-agnostic, opening our service up to be cross-platform.
To continue the User Service example, I would encode my User representation in XML, so that an HTTP GET request for the http://localhost/my-user-service/user/100 URI would return:
<user> <id>100</id> <name>Daniel Silva</name> <favourite-arch>SOAP</favourite-arch> </user>
But, there’s a mistake! SOAP is not my favourite. We have to take care of that immediately by posting the following to the http://localhost/my-user-service/user/100 URI via HTTP POST:
<user> <id>100</id> <name>Daniel Silva</name> <favourite-arch>REST</favourite-arch> </user>
And my service should understand that by doing an HTTP POST request to the URI http://localhost/my-user-service/user/100 what I want to do is update the user. Note the lack of some specific form URI or form handler that you might find in traditional web applications that operate at this level.
It is worth noting that while XML works as the means for representing your data in a machine-friendly way it is not the only way. Alternatives such as JSON, YAML, and GroovyMarkup work potentially as well. (There are many more that just these, and you can even write your own custom flat-file format if you’d like.) However I could say a couple things in favour of XML. You can use XML Schemas (XSDs) to ensure data integrity, and XML parsers are highly-available, making your service data friendlier to consumption. But you are certainly not limited to XML. The point is to make your data machine-friendly somehow.
The final piece of the puzzle is the client. Web browsers make it very easy for humans to browse the Human Web. Is there, or could there be, a similar tool for the Programmable Web? Unless the XML that is returned from every URI is standardized in some way, creating some new language in the process (Object-XML perhaps), there is no way to really do this. (SIDEBAR: I will tackle this issue more head-on in a future post and explore what Object-XML might look like.) Therefore, we could go one of two routes. We could publish a schema and let our consumers deal with the parsing bit, or provide our own custom client instead. While you could do both, I think it’s best to do the latter only.
Custom clients are the [short-term] answer to the web browser problem in the Programmable Web. The designer of the service is best capable of doing this work. The designer can also implement a client for his service in many different languages, giving his service true cross-platform operability. But the biggest positive of this approach is that it encapsulates the web’s architecture and data, much the same way a web browser does for the Human Web. As a consumer of the Human Web, you’re expected to have a web browser and know a URI. That’s it. Custom clients provide the same notion to the Programmable Web: consumers would be expected to have the client and, optionally, know the URI. (However, the URI could be hidden in the implementation because the client is specific to a particular URI set as I describe.) Using the custom client, consumers make what looks like a local function call that in its implementation reaches out over the web to get whatever it is you requested. It’s beautiful, really. Isn’t it?
Thus, in summary, to make your application a part of the Programmable Web just as the Human Web:
1. Adjust your API exposure to be more resource-oriented. 2. XML is analogous to HTML: Expose clean URIs that return XML representations of your data. 3. Custom clients are analogous to the Web Browser: Create custom clients that read your XML and translate it transparently to the object model of choice, in the appropriate computer language.
The benefits of this approach are tremendous. While I could write a whole new post about it, I’ll just quickly highlight three benefits. Coding to the Programmable Web provides quick cross-platform interoperability. You can, for example, utilize the Java platform for the back-end heavy lifting while you delegate the front-end capabilities of a web site to the Ruby platform, for which it is well-suited. You can also leverage the architecture of none other than the World Wide Web to design distributed applications, where key bits are done in different, focused computing environments, vastly improving the scalability of your system. Lastly, I’ll again reiterate the simplicity of it all. By providing a machine-friendly response and a client that can read it in, you have scalable cross platform web services, without the need for sticky, gooey fluff.
It’s a wonder to me this approach hasn’t been more popular to-date!
Conclusion
A “Tale of Two Webs” is a bit of a farce, really. There aren’t two webs, but rather at least two generic response types: human-readable (e.g., HTML) and machine-friendly (e.g., XML). The point I wanted to make in drawing attention to a notion of the Programmable Web is as follows: the machine-friendly stuff is surprisingly lacking. Yes, some companies on the Web are producing XHTML, a stricter form of HTML that can be machine friendly while being human-readable (through a web browser). However XHTML’s base (HTML) is still a tag library for marking up parts of a document (e.g., headings, subtitles, and paragraphs) and not the contents of the document itself (the data, e.g., planes, trains, and automobiles). While it is fashionable to “scrape” content (create complex parsers that read in HTML data and spit out machine-friendly versions of it) I submit to you there shouldn’t be the need at all for this, and making it easier will only enhance the quality of the Web and our applications at-large.
In my next instalment, I will go over a RESTful Seasons’ Greetings service. It will be a simple service that will return an optionally-customized greeting appropriate for the holidays. We’ll break down the parts, explain why they are meaningful as they are, and bring together this notion of the Human and Programmable Webs together through one web application. I’m a Java developer so I will be doing this in Java, but the concepts really are cross-platform. And I will be providing tarballs of the entire source, so that you can build it and deploy it on your own machine.
I’m personally very excited, and I hope you are, too. See you next time!
[1] RESTful Web Services, http://oreilly.com/catalog/9780596529260/
[2] While this is mostly true, it’s not 100% true because each browser implements portions of the specification, which may or may not behave the same way. Browsers also provide functionality outside of the specification as a way to drive users to their platform (as opposed to a competitor).
[3] By design it’s supposed to be safe, but an improper web browser implementation can open your computer to published and lesser-known dangers. Always practice safe browsing.
[4] W3C Web Services Activity, http://www.w3.org/2002/ws/
[5] RESTful Web Services, http://oreilly.com/catalog/9780596529260/
|
-
|
In my evolution as an applications developer I’ve stumbled upon certain technologies that excited me. These were the more obvious things at first, like discovering the power of design patterns or unit testing. But the last one that has really been tickling me is Representational State Transfer, or REST for short. And I find myself more excited about the promise of REST than anything else I’ve encountered so far in my journey.
Representational State Transfer (REST) is a set of architectural guidelines defined by Roy E. Fielding, in his dissertation on the design of the World Wide Web[1]. In short, it describes how resources that live on the “web” are requested and modified by agents outside of the web. This includes the medium (TCP/IP), the protocol (HTTP), and the representation (HTML). Sounds like the W3C specification, right? Well that’s because Roy also co-authored those.
There are many[2] resources[3] on what REST is, so rather than go over the specifics I’ll just highlight the guideline and the things I find interesting about it. There’s a huge emphasis on resource-orientation in REST. That is, the angle taken when thinking about objects isn’t so much in terms of what they do but more about what they are. To further the contrast: object-orientation pre-occupies itself with the blueprint of objects to understand how they may interact, where as resource-orientation is more concerned with what the object looks like, and leaves the interactivity out. This in isolation makes little sense, but if you think about the web, there are basically two messages that are sent most of the time: GET and POST. Resource-orientation assumes that at some point resources should handle GET, POST, and other HTTP-specification messages, and thus leaves out the behaviour of resources. Instead, it focuses on what the resource looks like, or in other words, its state.
Imagine a world where every object had a basic uniform interface – the HTTP-specification-based methods – and rather than manipulation of objects (in terms of messages you can send and receive) you focus on manipulation of state instead, and you start warming up to the core of REST.
The other thing noteworthy about REST is its emphasis on the importance of Uniform Resource Identifiers (URIs). A URI is the way a resource is published, and thus it is critical that it have a unique namespace, as well as a descriptive name. The URI is the handle through which agents can grab a hold of a resource and do something with it or to it. Without the presence or uniqueness of this identifier, the world of resource-orientation grinds to a halt.
To review, in light of these clarifications: REST is an architectural guideline whereby resources are uniquely identified and their states are managed by a uniform interface, such as the HTTP methods.
REST might still be a bit blurry, so I’ll contrast it with another process guideline that plays its antagonist: Remote-Procedure Call (RPC). In RPC, you send a message from one end of a wire to the other end of the wire, where a recipient waits for messages and optionally responds in kind, over the wire, back to the originator with some kind of response. This is object-oriented for the same reason it’s not resource-oriented (RESTful): the concern in this process model is the objects and the messages, not the resources and their state. A REST approach wouldn’t expose a list of possible messages an object could receive (think: verbs/actions) over a wire, but rather expose a representation of the resource’s state (think: nouns/representations) over the wire. All the while managed by sending one of a core set of messages you’d use with any other resource, the response differing only in how that resource would handle the message. The core set that’s been implemented are the HTTP methods and resources named via URIs, which are generally (and for good reason) associated with REST.
“Manage resource-state instead of the resource itself? That’s crazy talk!” But it’s really no crazier than thinking when you instantiate an object, you really have that object. In the end, objects and messages are facade for resources and resource-state. Representations of objects in memory, each with easy-to-grab handles to manipulate them. REST actually brings us closer to the machine (in terms of abstraction).
I’ll give a simple example to help bring the point home. Imagine we have to model a light bulb. Putting on our OO thinking caps, we start thinking that it has certain properties (colour, size, power) and at least one function: toggle on/off. Putting on our RO (resource-oriented) caps on, we think it has to live somewhere (e.g., silvanolte.com), it has to have a unique name in that place (e.g., light-bulb.html), and its state is managed by the HTTP method used to interact with it (e.g., GET retrieves a light bulb, POST changes the state of a light bulb, such as whether it’s on or off, and DELETE would delete a light bulb – one URI, three different HTTP methods). In OO, we now create other object to interact with our shiny new light bulb, whereas in RO we now simply interact with it through an already available client (e.g., web browser) or write a custom client to interact with it. (This last point is rather powerful, but that may not be immediately apparent. As I continue the series, I will revisit this and show you exactly why.)
And these are just some of the reasons why I am smitten by REST. It challenges my foundation for how I approach computing problems (object-orientation) , specifically dealing with web application design and, to a greater extent, web services implementation. It nudges me in different ways when I look at how I build my model, and how I expose parts of it in a web application. Focusing on resource- and state-management gives me a different look and, combined with an object-oriented perspective, provides a wider picture from which I can draw design cues.
Resource-orientation fits the web model better. Process models like RPC act more as an adapter process than an embracing of the underlying infrastructure. While some levels of indirection provide great benefit for the introduced complexity, going beyond resources and their states is hard to justify. It’s what the web was designed for, and adding facades to make the web fit our paradigms for application development, while the web’s infrastructure is sufficient, introduces needless complexity. That brings me to my next point...
I love simplicity, and REST is, at its core, very simple. Simpler designs has less room for error and are easier to manage. Resources, whether static or logical, exist given their URI (their “handle”) and are accessible to you. Simply apply an HTTP Method to a URI to get some representation of it, changing its state along the way (in the very least, it changes for no other reason than your interaction with it). No messy end points. No complicated RPC calls. Simple design that is extensively powerful in its application.
And besides, it’s hard to argue with results. The World Wide Web is as successful a platform as there’s ever been in the computer science space. From humble beginnings to supporting full-blown services such as Word Processing and Data Mining, the Internet has revolutionized the way we work and live. And if you look carefully, you’ll notice this is not in spite of REST, but in large part because of it.
Finally, I like REST because I see a lot of potential. I consider all the questions that come to mind when I think about the Web, its design, and how Web Applications work, and I see a lot of room for innovation and growth based on a RESTful foundation. There’s a lot of upside to this approach, and when I superimpose it over everything I’ve learned to date about web applications, web services and all the concerns that come with them (session management, transaction management, scalability, performance, security) there seems to glowing paths to new levels of enlightenment. And there’s only one way to know: I must make the journey and see what’s there.
In a nutshell, that’s REST, and that’s why I like it. In the next few weeks I’m going to delve deeper into RESTful application design and share bits of code I’m writing to illustrate some of the powerful things you can do with this simple paradigm. We’ll write a service, and write different kinds of consumers (desktop application, web application, and finally web service), and see where REST shines brightest.
We'll also look at what libraries and frameworks that exist today to help anybody put together a RESTful architecture. Some are great, and some are complex again (defeating the purpose!) but they all have something interesting to offer. We'll explore what niches are left to fill, and perhaps even start an open souce project to address some of these concerns.
All in all, It is my hope that in sharing with you parts of my journey into REST you too will get something meaningful out of it, and blaze your own RESTful evolution in your projects. Just remember to give back, so we can all grow together.
[1] Fielding, Roy T.; Taylor, Richard N. (2002-05), "Principled Design of the Modern Web Architecture" (PDF), ACM Transactions on Internet Technology (TOIT) (New York: Association for Computing Machinery) 2 (2): 115–150, doi:10.1145/514183.514185, ISSN 1533-5399
[2] Representational State Transfer – Wikipedia: http://en.wikipedia.org/wiki/Representational_State_Transfer
[3] Building Web Services the REST Way: http://www.xfront.com/REST-Web-Services.html
|
|
|
|