You are previewing REST in Practice.

REST in Practice

Cover of REST in Practice by Ian Robinson... Published by O'Reilly Media, Inc.
  1. REST in Practice
    1. SPECIAL OFFER: Upgrade this ebook with O’Reilly
    2. Foreword
    3. Preface
      1. Should I Read This Book?
      2. Should I Skip This Book?
      3. Resources
      4. What Did You Think About the Book?
      5. Errata
      6. Conventions Used in This Book
      7. Using Code Examples
      8. How to Contact Us
      9. Safari® Books Online
      10. Acknowledgments
    4. 1. The Web As a Platform for Building Distributed Systems
      1. Architecture of the Web
      2. Thinking in Resources
      3. From the Web Architecture to the REST Architectural Style
      4. The Web As an Application Platform
      5. Web Friendliness and the Richardson Maturity Model
      6. GET on Board
    5. 2. Introducing Restbucks: How to GET a Coffee, Web Style
      1. Restbucks: A Little Coffee Shop with Global Ambitions
      2. Toolbox
      3. Here Comes the Web
    6. 3. Basic Web Integration
      1. Lose Weight, Feel Great!
      2. A Simple Coffee Ordering System
      3. URI Templates
      4. URI Tunneling
      5. POX: Plain Old XML over HTTP
      6. We Are Just Getting Started
    7. 4. CRUD Web Services
      1. Modeling Orders As Resources
      2. Building CRUD Services
      3. Aligning Resource State
      4. Consuming CRUD Services
      5. Consuming Services Automatically with WADL
      6. CRUD Is Good, but It’s Not Great
    8. 5. Hypermedia Services
      1. The Hypermedia Tenet
      2. Hypermedia Formats
      3. Contracts
      4. Hypermedia Protocols
      5. Implementing a Hypermedia Service
      6. Building the Ordering Service in Java
      7. Building the Ordering Service in .NET
      8. Ready, Set, Action
    9. 6. Scaling Out
      1. GET Back to Basics
      2. Caching
      3. Making Content Cacheable
      4. Implementing Caching in .NET
      5. Consistency
      6. Extending Freshness
      7. Stay Fresh
    10. 7. The Atom Syndication Format
      1. The Format
      2. Common Uses for Atom
      3. Using Atom for Event-Driven Systems
      4. Building an Atom Service in Java
      5. Building an Atom Service in .NET
      6. Atom Everywhere?
      7. After the Event
    11. 8. Atom Publishing Protocol
      1. Atom Publishing Protocol
      2. Implementing Order Fulfillment Using AtomPub
      3. Implementing AtomPub in .NET
      4. A Versatile Protocol
    12. 9. Web Security
      1. HTTP Security Essentials
      2. Identity and the OpenID Protocol
      3. The OAuth Protocol
      4. Service Hacks and Defenses
      5. Final Thoughts
    13. 10. Semantics
      1. Syntax Versus Semantics
      2. Structure and Representation of Information
      3. The Semantic Web
      4. Microformats
      5. Linked Data and the Web
      6. Guidance
    14. 11. The Web and WS-*
      1. Are Web Services Evil?
      2. SOAP: The Whole Truth
      3. WSDL: Just Another Object IDL
      4. Two Wrongs Don’t Make a Right
      5. Secure, Reliable, Transacted
      6. A Requiem for Web Services?
    15. 12. Building the Case for the Web
      1. No More Silver Bullets
      2. Building and Running Web-Based Services
      3. No Architecture Without Measurement
      4. Selling the Web
      5. Go Forth and Build
    16. Index
    17. About the Authors
    18. Colophon
    19. SPECIAL OFFER: Upgrade this ebook with O’Reilly
O'Reilly logo

Consuming CRUD Services

Services are one side of distributed systems, but to perform useful work they need consumers to drive them through their protocols. Fortunately, many frameworks and libraries support CRUD Web Services, and it’s worthwhile to understand a little about what they offer.

A Java-Based Consumer

In the Java world, we might use the Apache Commons HTTP client[36] to implement the Create part of the protocol by POSTing an order to the ordering service, as shown in Example 4-31.

Example 4-31. Client-side order creation in Java

  public String placeOrder(Order order, String restbucksOrderingServiceUri)
                                throws BadRequestException, ServerFailureException,
                                       HttpException, IOException {

  PostMethod post = new PostMethod(restbucksOrderingServiceUri);
  // Use an existing XStream instance to generate XML for the order to transmit
  RequestEntity entity = new ByteArrayRequestEntity(

  HttpClient client = new HttpClient();

  try {
    int response = client.executeMethod(post);

    if(response == 201) {
      return post.getResponseHeader("Location").getValue();
    } else if(response == 400) {
      // If we get a 400 response, the caller's gone wrong
      throw new BadRequestException();
    } else if(response == 500 || response == 503) {
      // If we get a 5xx response, the caller may retry
      throw new ServerFailureException(post.getResponseHeader("Retry-After"));
    // Otherwise abandon the interaction
    throw new HttpException("Failed to create order. Status code: " + response);
  } finally {

The implementation in Example 4-31 shows the construction of a POST operation on the ordering service, using a PostMethod object. All we need to do is to populate the HTTP request with the necessary coffee order information by setting the request entity to contain the bytes of an XML representation of the order. To keep things simple for ourselves, we use the XStream library to encode the order resource representation in XML.

Having populated the HTTP request, we instantiate an HttpClient and execute the PostMethod, which POSTs the order to the Restbucks ordering service. Once the method returns, we examine the response code for a 201 Created status and return the contents of the Location header, which will contain the URI of the newly created order. We can use this URI in subsequent interactions with Restbucks. If we don’t get a 201 response, we fail by throwing an HTTPException, and assume that order creation has failed.

A .NET Consumer

On the .NET platform, we can opt for the framework’s built-in XML and HTTP libraries. The code in Example 4-32 represents how a client can send an order update to the Restbucks ordering service via HTTP PUT.

Example 4-32. .NET client code for order update via PUT

public void UpdateOrder(Order order, string orderUri)
  HttpWebRequest request = WebRequest.Create(orderUri) as HttpWebRequest;
  request.Method = "PUT";
  request.ContentType = "application/xml";

  XmlSerializer xmlSerializer = new XmlSerializer(typeof(Order));
  xmlSerializer.Serialize(request.GetRequestStream(), order);


  HttpWebResponse response = (HttpWebResponse)request.GetResponse();

  if (response.StatusCode != HttpStatusCode.OK)
    // Compensation logic omitted for brevity

In Example 4-32, we use an HTTPWebRequest instance to handle the HTTP aspects of the interaction. First we set the HTTP verb PUT via the Method property and subsequently set the Content-Type header to application/xml through the ContentType property. We then write an XML-serialized representation of the order object that was given as an argument to the UpdateOrder() method. The XmlSerializer transforms the local object instance into an XML document, and the Serialize() method writes the XML to the request’s stream. Once we’re done populating the request stream, we simply call Close(). Under the covers, the framework sets other headers such as Content-Length and Host for us, so we don’t have to worry about them.

To send the request we call the GetResponse() method on the request object, which has the effect of transmitting an HTTP PUT to the URI supplied as an argument to the updateOrder() method. The response from the ordering service is returned as an HttpWebResponse and its StatusCode property triggers any further processing.

One final job that we need to undertake is to mark up the Order type so that the XmlSerializer knows how to transform Order instances to and from XML representations. The code snippet in Example 4-33 shows the .NET attributes that we need to apply for our client-side plumbing to be complete.

Example 4-33. An XML-serializable order

 [XmlRoot(Namespace = "")]
 [XmlType(TypeName = "order")]
 public class Order

 [XmlElement(ElementName = "location")]
 public Location ConsumeLocation
   get; set;
 // Remainder of type omitted for brevity

The best content for your career. Discover unlimited learning on demand for around $1/day.