Christian HagerSoftware Engineer // Technical Director // Photographer

Implementing RESTful Webservices: Part 1 – The Basics

The following post is the first part of a blog series covering the design and implementation of RESTful webservices. This first part will cover the basics and give some general tips. The subsequent posts of the series will then cover the implementation of a demo service using jersey as well as more advanced topics like partial representations, pagingation, references, reference expansion, caching, errors and security.

What is REST?

The acronym REST stands for “Representational State Transfer”. The term was first defined in 2000 by Thomas Roy Fielding in his doctoral dissertation “Architectural Styles and the Design of Network-based Software Architectures”. It is an architectural style for designing distributed hypermedia systems.

Today REST is a well established way to build APIs and therefore to build loosely coupled scalable distributed applications.

REST is not strictly tied to http even though it is today mostly used in conjunction with http.

Some examples of prominent REST-APIs are

The key principles of RESTful api-desgin

  1. Every “thing” (Resource) is identified by an ID (URI)

  2. Resources can have multiple representations

  3. Standard methods are used (GET, PUT, POST, DELETE)

  4. Communication is stateless (state is either turned into resource state or kept on the client)

  5. Resources are linked together

Resources

Resources are the basic concept of REST. In his dissertation Fielding defines resources as “The key abstraction of information”. According to his definition  “Any information that can be named can be a resource: a document or image, a temporal service (e.g. “today’s weather in Los Angeles”), a collection of other resources, a non-virtual object (e.g. a person), and so on.”

Resources are identified by URIs. There are a number of best practices on designing restful URIs to be found in literature. The following best practices are the ones which I tend to use in my projects. As stated before this is my personal list which is not necessarily the best choice in every situation nor is it complete or static. It will always subject to change if I encounter the need to do so.

  1. Good resource URIs should be nouns not verbs (verbs are indicators for non restful apis), e.g.  /product or /customer

  2. URIs should be intuitively readable

  3. URIs should be composed in hierarchical structure, e.g. /customer/42/orders/0815

  4. Don’t couple resources and behaviour because it doesn’t scale and is very confusing

  5. APIs should be coarse grained (don’t try to model your domain entities as resources)

There are two fundamental types of resources.

  1. Collection resources (also called Container resources), e.g. /customers

  2. Instance resources, e.g. /customers/12345

As seen in the example above instance resources are identified by an ID part in their URI. When creating those IDs you should take care that they meet the following requirements. IDs should

  1. be opaque

  2. be globally unique

  3. avoid sequential numbers because of potential security risks and scalability issues (with multiple server nodes ID sequences would have to be synchronized which is bad for scalability)

A good candidate for resource IDs is UUID.

Implementing behaviour

As stated in the section above resources shouldn’t be coupled to behaviour. But how do we implement behaviour? The short answer is to implement behaviour we use the standard http methods. The somewhat longer answer is we use the http methods GET, PUT, POST and DELETE similar (but not 1:1) to CRUD. The following table shows how the http methods map to CRUD operations.

HTTP method

CRUD operation

GET

Read

DELETE

Delete

PUT

Create if identifier is known by client

Update if it is a full replacement of the object

POST

Create

Update (can be a partial update)

GET and DELETE are really easy because they map 1:1 on their corresponding CRUD operations Read and Delete.

The tricky part is the usage of PUT and POST because they can both be used for create and update operations. PUT can be used to create a resource if it’s identifier is known by the client and used to update it if a full replacement is done. The reason for this behaviour is that PUT is idempotent by design which means that it will produce the same results if executed multiple times.

POST can also be used to create resources but doesn’t require the identifier to be known by the client. Last but not least POST can be used as an update operation. This is especially preferable if we want to implement partial updates of resources, e.g. to save bandwith.

The following points apply wether the operation was executed by PUT or by POST. If a create is executed on a parent resource the operation creates a child. If the create operation has been successful the server should return http code 201 – CREATED to indicate success. Additionally it should return the location of the newly created resource. Successful update operations should return http code 200 – OK.

Resource Representations

REST separates resources and representations. Restful resources can have one or multiple representations. In the context of http representations are implemented using MediaTypes. MediaTypes tell the client something about how to handle the data it receives and how to make requests.

Let me give an example to make this more tangible. If we would just execute a GET on a resource /customer/1234 the client has still no idea how to handle the data it receives in response to it’s request. The data format could be plain text, xml or some proprietary format. What we need is some way to tell the client which format the transmitted data is in. The client needs some format specification and the corresponding parsing rules. This is the point where MediaTypes come in. Using the content-type header the server can tell the client which format the data is in.

Using the accept header the client can request a format from the server which it can handle. This process is called content negotiation.

It is preferable to stick with standard MediaTypes because developers as well as tools already know how to handle those. The currently most commonly used MediaTypes are application/json and application/xml. Nonetheless it is also possible to create custom mediatypes like application/foo or mix standard and custom types. application/foo+json would be json but structured by foo specification. Experience shows that you should start with standard types which are sufficient for most use cases and move to custom types when it becomes necessary to do so. As a standard type I currently mostly use json as it is very lightweight and integrates nicely with a lot of web technologies and framework.

Another way to indicate data format are resource extensions. Therefore you would append the MediaType to the resource URI, e.g. /customers/1234.json or /customers/1234.xml. Resource extensions should then  conventionally override the accept header.

In my opinion it it more of a philosophical question wich one to use. You should go with whatever variant you like better.

Summary

In this first post of the series attempted to cover the basic concepts of the REST architectural style. Additionally I gave some tips on how to put the theory into practice. As always if something is wrong or somebody has a different opinion about some points, please feel free to discuss in the comments.

The next part of the series will cover the implementation of a simple demo service using Java and Jersey.

 

Tags: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *