Developing a REST based Web Service

Exclusive offer: get 50% off this eBook here
RESTful Java Web Services

RESTful Java Web Services — Save 50%

Master core REST concepts and create RESTful web services in Java

$23.99    $12.00
by Nicholas Floyd | November 2009 | BPEL SOA Web Services

REST (REpresentational State Transfer) is an architecture for distributed hypermedia systems. The World Wide Web is possibly the best known implementation of this architecture style. The term "REST" was coined and described by a dissertation written by Roy Fielding in 2000. This article by Nicholas Floyd covers the architecture which contains four basic constructs that address common concerns such as: scalability, generalized interfaces and resources, and patternized approaches for manipulation of resources.

Some of the problems and concerns that this architecture attempts to solve are:

  1. Security
  2. Follow common community standards / practices
  3. General interfaces
  4. Ease of consumption
  5. Fault tolerance
  6. Supports common resource representations
  7. Needs to scale and understand complex relationships

The four basic principles of REST

A REST based service should implement four basic constraints: identification of resources, manipulation or resources through, representations, self-descriptive messages, and HATEOAS (hypermedia as the engine of application state).

Identification of resources

Basically, any information that can be named can be a resource. A resource could be a representation of a code Class, a file on the file system, a simple block of text, a byte array of an image, or the image itself. Think of a resource as a conceptual representation of entity - a conceptual representation of a person, building, order, so on.

Given the non-virtual resource representing person, a conceptual representation of that resource might be:

<?xml version="1.0" encoding="utf-8"?>
<person id="" uri="">
<firstName/>
<middleName/>
<lastName/>
</person>

Given the non-virtual resource "John Adams", a representation of that resource might be:

<?xml version="1.0" encoding="utf-8"?>
<person id="123" uri="http://domain/people/123">
<firstName>John</firstName>
<middleName></middleName>
<lastame>Adams</lastame>
</person>

There are a few things that should be noted regarding resources:

  1. Resources can be highly static or highly dynamic
    • Semantics of a resources mapping determines how "static" it is
    • Static: http://domain/People/123, Dynamic: http://domain/People/Search?status=new
  2. This abstract definition of a resource enables key features of the Web architecture to "work"
    • Grouping of data without definition
    • Late binding of the reference to a representation
    • Allows reference to the resource concept without having to reference a specific resource

Manipulation of resources through representations

Some of the most basic constructs of HTTP 1.1 are some of the Web's most powerful tools. Users of the Web have been shielded from the specifics of protocols such as HTTP 1.1 (as described in RFC2616) via various user-agents such as Firefox and Google Chrome. It was no mistake that REST was being conceptualized at the same time HTTP 1.1 was being formulated. Both became instrumental to the success of Web based applications on the internet. To illustrate, consider the 7 basic URI routes for a Ruby on Rails application using the person representation from above:

HTTP Method

URI

Action

GET

people

Index

GET

people/123

Show

POST

people

Create

PUT

people/123

Update

DELETE

people/123

Delete

GET

people/123/new

New

GET

people/123/edit

Edit

A patternized approach to URI schemes makes implementation and consumption of a REST service drastically more simplistic. The URI schemes above are examples of what the manipulation of resources through the use of HTTP verbs might look like. The point is that a RESTful service should provide the client with enough information to manipulate the resource.

Given the following: GET people/123

HTTP/1.1 200 OK
Cache-Control: private
Content-Type: application/xml; charset=utf-8
Content-Location: http://domain/people/123
Date: Fri, 01 May 2009 05:36:38 GMT
Content-Length: 102

<?xml version="1.0" encoding="utf-8"?>
<person id="123" uri="http://domain/people/123">
<firstName>John</firstName>
<middleName></middleName>
<lastame>Adams</lastame>
</person>

The consumer of the REST service now has all they need to know to update the "middleName" node with the value of "Quincy":

PUT people/123

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Date: Fri, 01 May 2009 05:36:38 GMT
Content-Length: 102

<?xml version="1.0" encoding="utf-8"?>
<person id="123" uri="http://domain/people/123">
<firstName>John</firstName>
<middleName>Quincy</middleName>
<lastame>Adams</lastame>
</person>

Server responds:

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Content-Location: http://domain/people/123
Date: Fri, 01 May 2009 05:36:40 GMT
Content-Length: 102

<?xml version="1.0" encoding="utf-8"?>
<person id="123" uri="http://domain/people/123">
<firstName>John</firstName>
<middleName>Quincy</middleName>
<lastame>Adams</lastame>
</person>

There are a few things to note regarding manipulation of resources via representations:

  • A representation is a sequence of bytes plus representation metadata (in the form of name value pairs) to describe those bytes
  • Data format = media type
  • Composite media types can be used to encapsulate multiple representations in one message

Self-descriptive messages

This rule of REST implies that the server must provide enough information in each message, to the consumer, so that they can properly process the message. The message must somehow be self-descriptive so that the consumer can use it without having to look into the body of the message. Headers are probably the best example of how to inform the user without inspection. Using HOST headers, content-type, content-location, and even resource extensions the server implementation quickly enables successful consumption. Caching, chunking are also some of the other enabling mechanisms of HTTP 1.1.

There are a few things to note regarding self-descriptive messages:

  1. Messages may include both the representation metadata (ex. xsd), and the resource metadata (ex. nodes)
  2. Control data: action (get, put post, delete), or definition of the response
    • Also use to override default behavior (supporting low and high rest clients)
RESTful Java Web Services Master core REST concepts and create RESTful web services in Java
Published: November 2009
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

HATEOAS (Hypermedia As The Engine Of Application State)

This constraint proposes that the server provides the client with enough information about the resource and all related resources via URIs and actions so that use and implementation are decoupled. Basically, the server will always hand the client proper URIs for all resources that are able to be referenced (at minimum). This is simply making media into hyper-media. HATEOAS attempts to reduce coupling and assumptions around hyper resources.

There are a few different degrees of a HATEOAS implementation, some are (but not limited to):

Simple (server response): Providing URIs for each resource

HTTP/1.1 200 OK
Content-Type: application/xml; charset=utf-8
Content-Location: http://domain/people/123
Date: Fri, 01 May 2009 05:36:40 GMT
Content-Length: 102

<?xml version="1.0" encoding="utf-8"?>
<person id="123" uri="http://domain/people/123">
<firstName>John</firstName>
<middleName>Quincy</middleName>
<lastame>Adams</lastame>
<addresses uri="http://domain/people/123/addresses"/>
</person>

More complex (server response): Providing URIs for each resource, establishing custom content-types

Although the service provider can choose the implementation the API should attempt to provide an interface that is easy to understand and easy to use. Consider the following case for extending our people resource:

Given: The service provider has added a "goesByName" node to the xml being returned and received. The service provider has determined that this change has potential to break existing consumer interface contracts. Therefore, a new content-type will be created so that the existing consumers will not be impacted by the change

A good formula that can be used when determining what to name a versioned custom content type might be:

Content-Type: application/[custom vendor moniker].[domain].
[realm].[resource].[version]+[root media type]
  • [custom vendor moniker]: The value for this is usually vnd, however this could be almost any notation. It is used to simply tell the consumer that this resource being used is a custom type that was generated by the service provider
  • [domain]: Usually the service providers base domain, or API domain
  • [realm]: This represents a logical grouping of data. Generally "realms" are used in APIs to either virtually (through code) or physically (through totally separate APIs) data. The reason that it might useful in the custom content type is so that the resources have a specific grouping. In the long run APIs that use realms tend to be able to implement more simplistic security models.
  • [resource]: The actual resource that is being worked with. With our example this value could be people, address, communication, etc...
  • [version]: It is recommended that this parameter be a simple version. Normal software versions can be and sometimes need to be complex (i.e. major.minor.branch.build or 1.3.2.6). This implementation should be more simplistic since the service provider should not be producing a multitude of different media types, the API is versioning resources not software, and complex version sequences are less meaningful to consumers
  • [root media type]: This is the base type or format that is being returned xml, json, etc...

So, given out scenario above the "more complex" implementation might look like:

HTTP/1.1 200 OK
Content-Type: application/vnd.mydomain.people.people.v1+xml; charset=utf-8
Content-Location: http://domain/people/123
Date: Fri, 01 May 2009 05:36:40 GMT
Content-Length: 102

<?xml version="1.0" encoding="utf-8"?>
<person id="123" uri="http://domain/people/123" type=
"application/vnd.mydomain.people.people.v1+xml">
<firstName>John</firstName>
<middleName>Quincy</middleName>
<lastame>Adams</lastame>
<goesByName>JohnQ</goesByName>
<addresses uri="http://domain/people/123/addresses" type=
"application/vnd.mydomain.people.addresses.v1+xml"/>
</person>

Even more complex (server response): Providing URIs for each resource, establishing custom content-types, providing actionable semantics

HTTP/1.1 200 OK
Content-Type: application/vnd.mydomain.people.people.v1+xml; charset=utf-8
Content-Location: http://domain/people/123
Date: Fri, 01 May 2009 05:36:40 GMT
Content-Length: 102

<?xml version="1.0" encoding="utf-8"?>
<person id="123"
uri="http://domain/people/123"
type="application/vnd.mydomain.people.people.v1+xml"
submit="http://domain/people/123" method="POST">
<firstName>John</firstName>
<middleName>Quincy</middleName>
<lastame>Adams</lastame>
<goesByName>JohnQ</goesByName>
<addresses
uri="http://domain/people/123/addresses"
type="application/vnd.mydomain.people.addresses.v1+xml"
submit="http://domain/people/123/addresses" method="POST"/>
</person>

There are a few things to note regarding HATEOAS:

  • Eliminates the need to the server to maintain an awareness of client state beyond the current request
  • Provide a state machine through URIs in the resource

Other considerations

The service provider should consider HTTP status codes. There are a predefined set of codes that inform the consumer about the state of the request. These codes help reduce obscurity across web based implementations by requiring that the proper code be returned for a given response. Although these status codes are not all "required" the consumers will expect them and they will expect them to be implemented as defined in the RFC 2616. For instance, consider the following scenarios and the status codes that are returned:

Status code for a successful GET would normally be:

200 OK
  • Entity body - The resource
  • Example - [GET] People/1

Status code for a Create would normally be:

201 CREATED
  • Response Header - Location will contain the canonical URI
  • Entity body - The resource
  • Example - [POST] People

Status code for a bad of malformed request would normally be:

400 BAD REQUEST
  • Response Header - No modification
  • Entity body - Optionally, information describing the failure
  • Example - passing over a malformed xml document

Status code returned when a user attempts to access data that the service provider has not provided access to that user for would normally be:

403 FORBIDDEN
  • Response Header - No modification
  • Entity body - explanation of why authorization failed, or why the user cannot access the requested resource

Status code returned when a consumer application tries to request a specific resource that does not exist:

404 NOT FOUND
  • Response Header - No modification
  • Entity body - should be empty
  • Example - [GET] People/1 does not exist, optionally a 410 may be used (see below)

Status code returned when a consumer application tries to request a specific resource as a specific media type that the service provider does not support (this status code provides the greatest help when a service provider has implemented some form of HATEOAS using custom media types):

415 UNSUPPORTED MEDIA TYPE
  • Response Header - Code detailed supported media types for the given resource
  • Entity body - should be empty
  •     

  • Example - Resource only supports XML and JSON, but the client sends application/atom+xml

The service provider should also consider HTTP headers. Request and response headers are instrumental to making web applications work, so they should be considered extremely important in API design and implementation. Although some headers are not "required" the more information and help that the API can provide to consumers the better. For instance, consider the following response and request headers:

Request Headers

Accept : type/subtype

  • Example - Accept : application/xml
  • Notes - Defaults to application/xml if one is not passed in, and when a user sends application/* the resulting content sub type will be XML. Multiple types/sub types can be sent in but as per the specification the first match in degree of specificity will be the first used.
    i.e. if user sends in: application/*, application/xml, / the order would be as follows:
    1. application/xml
    2. application/*
    3. */*
  • Acceptable values - application/xml, application/json, application/xsd, application/help
  • If an invalid value is passed in via Accept header the response will result in a 415 Unsupported Media Type

Accept-Charset : charset

  • Example - Accept-Charset: utf-8
  • Notes - Accept-Charset will not be used and will always default to utf-8

Accept-Encoding : encoding

  • Example - Accept-Encoding : deflate
  • Notes - If none is sent in then the API will default to no compression.
  • Acceptable values - deflate, compress, gzip
  • If an invalid value is passed in via Accept-Encoding header the response will result in a 406 Not acceptable

Date : HTTP-date

  • Example - Date: Thu, 29 Jan 2009 15:28:25 GMT
  • Notes - Optional, most commonly passed in with PUTs and POSTs

Response Headers

Allow : method

  • Example - Allow: GET, PUT
  • Notes - An Allow header field MUST be present in a 405 (Method Not Allowed) response.
  • Return values - GET, PUT, POST, DELETE

Content-Encoding : content-coding

  • Example - Content-Encoding : gzip
  • Notes - This will tell the client what type of compression was used on the resource
  • Return values - deflate, compress, gzip

Content-Length : DIGIT

  • Example - Content-Length : 1254
  • Notes - Sent back with each request. Will possibly be available via HEAD requests

Content-Location : absoluteURI | relativeURI

  • Example - Content-Location : http://domain/v1/people/1234
  • Notes - Sent back with each GET request

Content-Type : media-type

  • Example - Content-Type : application/xml, utf-8
  • Notes - Details the type of content being returned to the client

Date : HTTP-date

  • Example - Date: Thu, 29 Jan 2009 15:28:25 GMT
  • Notes - Will be returned with every response, possibly excluding responses returning status codes of 500

Location : absoluteURI

  • Example - Location: http://domain/v1/people/1234
  • Notes - Applies to 201 and 301 only

Summary

The RESTful approach to web services is ideal in a web based consumer environment; where consumers can leverage the protocols that make web architecture possible. Specifically the HTTP 1.1 specification (RFC2616) should be considered and followed in any REST based service. Key elements defined by that protocol such as status codes and HTTP headers help the service provider to extend the service without compromising the implementation while lowering knowledge barriers around consumer usage.


If you have read this article you may be interested to view :


RESTful Java Web Services Master core REST concepts and create RESTful web services in Java
Published: November 2009
eBook Price: $23.99
Book Price: $39.99
See more
Select your format and quantity:

About the Author :


Nicholas Floyd is the Integration Architect at Fellowship Technologies where he builds and creates APIs and integration points for all types of systems.  He has been working in web based software for 15 years developing a myriad of web applications and sites. He's married, father of 3 awesome boys, and a guy who loves God! Links to his articles may be found at his website nicholasfloyd.com and can be contacted via twitter @nickfloyd.

Books From Packt


Service Oriented Architecture with Java
Service Oriented Architecture with Java

SOA Patterns with BizTalk Server 2009
SOA Patterns with BizTalk Server 2009

Spring Persistence with Hibernate
Spring Persistence with Hibernate

JBoss RichFaces 3.3
JBoss RichFaces 3.3

Seam 2.x Web Development
Seam 2.x Web Development

JasperReports 3.5 for Java Developers
JasperReports 3.5 for Java Developers

Oracle SOA Suite Developer's Guide
Oracle SOA Suite Developer's Guide

Microsoft Dynamics AX 2009 Programming: Getting Started
Microsoft Dynamics AX 2009 Programming: Getting Started


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
q
g
7
T
W
S
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software