What is REST and when is my service truly RESTful?
This article is a brief, conceptual introduction to REST. It describes what a REST service is, what are the main REST principles and answers when is a service truly restful. After reading it you should get an overview of the restful architectural approach and understand how the client and server communicate in this style. An example of a REST service can be found in allAroundJava’s github DoctorBooking project’s develop branch.
What is REST?
Some time ago a guy named Roy Fielding examined the properties of World-Wide Web in his doctoral thesis. Amongst others, he tried to answer the questions of what makes the web scale so well and why is it so widely accessible? While some of our applications’ architecture often requires change, what makes the web stay in a similar form for so long? Finally, how can we apply the thought behind WWW to application design? Having that, he came up with a set of architectural principles which make up a Representational State Transfer (REST) approach. These are:
Addressability
This REST principle states that every object within our system needs to have a unique identifier under which it can be found. In a World Wide Web and REST this is realized with URIs.
Let’s examine a /patients endpoint allowing to exchange patient representation with a server. Each patient is represented with a unique ID and thus has a unique URI. Request for /patients/1 will give us a different result than /patients/2. Also sending a new representation to /patients/2 over PUT method will update different patient than if we PUT for /patient/3.
GET http://localhost:8080/patients/1
HTTP/1.1 200
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Wed, 03 Jul 2019 16:13:15 GMT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<patientDto>
<id>1</id>
<name>Henry Fonda</name>
</patientDto>
GET http://localhost:8080/patients/2
HTTP/1.1 200
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Wed, 03 Jul 2019 16:14:25 GMT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<patientDto>
<id>2</id>
<name>James Bond</name>
</patientDto>
Client-Server
Communication is based on two objects – one serving the data and another one consuming it. Along with the popular decoupling principle, both client and server should be able to change independently. They’re usually free to change internally but because they exchange information, any changes to the interface may be problematic.
Representation Orientation
Both client and server exchange resource representations. The result of a GET operation is a representation of a particular resource in the system. When passing a resource representation to the server with POST, a particular resource is usually created. Take a look at an example of a Patient resource exchange. Here we’re creating a new Patient in server memory.
POST http://localhost:8080/patients
Content-Type: application/xml
<patientDto>
<name>Mary Queen</name>
</patientDto>
HTTP/1.1 201
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Wed, 03 Jul 2019 16:23:22 GMT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<patientDto>
<id>3</id>
<name>Mary Queen</name>
</patientDto>
Uniform Interface
The communication between client and server bases on a simple, well-known interface with a defined and finite set of operations. For web we use an HTTP protocol with its methods like GET, POST, PUT, DELETE, etc. Each of them has a defined functionality and a standard thanks to which developers know what to expect when calling it.
Stateless Communication
This REST principle states that there should be no client session data stored on the server-side. Any session-related data should be maintained by the client and sent to the server with each request.
Rest services naturally store their resource state, but the communication itself is stateless. This is what makes the web scale so well.
HATEOAS – Hypermedia as the engine of application state
This principle means that the client should be able to understand how to change application state with the use of hypermedia links. This practically means we’re embedding links into our XML or JSON documents.
The principle in itself is similar to traversing a website. We usually know the address of a homepage, let’s say java.com. By reading a menu or buttons available on the page we can find our way through the service and locate the spaces that interest us. We should not need to know the full URL of space that is of interest beforehand.
Take a look at below example
GET http://localhost:8080/doctors/1
HTTP/1.1 200
Content-Type: application/xml
Transfer-Encoding: chunked
Date: Sun, 07 Jul 2019 11:04:48 GMT
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<doctorDto xmlns:atom="http://www.w3.org/2005/Atom">
<atom:link rel="self" href="http://localhost:8080/doctors/1" type="application/xml"/>
<atom:link rel="collection" href="http://localhost:8080/doctors" type="application/xml"/>
<entityId>1</entityId>
<name>Doctor John</name>
</doctorDto>
By requesting a doctor with id 1, we also got information under which URI and content type our doctor is accessible along with the URI of a collection which he is a member of.
Unfortunately guidelines to what documents and relations we should link to are not easy to find. Some information is available under W3C Relationship values or HAL approach.
To summarize, a restful service is a one which uses stateless communication over a unified, well-known interface where all the objects or resources are uniquely addressable. The service should exchange resource representation with its clients and at each stage should give us a list of unique ids under which we can access and alter its resources.
When is my service RESTful enough?
Ok, so we’ve got a set of ingredients to create a RESTful service. Lets now try to understand the full recipe.
A good reference as to how to create a service following REST principles is a Richardson Maturity model. It’s very well described by Martin Fowler in his blog post so I will not repeat it here, but I’ll try to capture the essence.
According to Richardson’s model, there are four levels to REST maturity. The model transitions from SOAP-style web service to RESTful, but it does not mean that RESTful services are more mature than SOAP. Richardson Maturity Model describes the levels in which services comply with all the REST principles described above.
Level 0 – Single URI over a single HTTP method
This level resembles SOAP style remote procedure calls the most, although it’s neither SOAP nor REST. In Level 0, all the calls to our service are done through a single HTTP method (typically POST) and all are done through the same URI. Referring to our previous examples, this means we would be calling
POST http://localhost:8080/doctors
regardless of whether we need to get a list of doctors, get a particular doctor or save a new doctor. The only thing that changes is the data that we pass.
Level 1 – Multiple URIs over a single HTTP method
This level introduces unique ids through URIs. Doctors would now be uniquely identified by their id say,
POST http://localhost:8080/doctors/2
or
POST http://localhost:8080/doctors/james-jones
Therefore all the operations on James Jones would be executed on his unique URI on a single HTTP method again.
Level 2 – Multiple URIs over multiple HTTP methods
Level 2 makes use of the Uniform interface REST principle and ensures all the operations we can perform on a resource are tied to proper interface methods. Therefore a call to
POST http://localhost:8080/doctors
with a doctor representation as payload would create a new doctor in service memory and
PUT http://localhost:8080/doctors/2
with new resource representation would update properties for doctor identified by id 2.
Level 2 is usually the REST API we know as it seems to be the most popular level to which API creators bring their REST services to.
Level 3 – Hypermedia Links
Level 3 adds Hypermedia Links to Level 2 services so that they are self-descriptive.
When to choose SOAP service over REST
The discussion of REST vs SOAP seems to be very active. Some voices say that comparing REST and SOAP is like comparing apples to oranges as SOAP is a protocol and REST is an architectural approach. That’s true, however when we attempt to make two applications communicate with each other, which approach do we choose? How do we choose between exposing a REST endpoint or a SOAP web service?
When we attempt to exchange information between two applications, we can either exchange a file, use a shared database, use a queue or call an exposed service. Both SOAP and REST services attempt to integrate applications by allowing to remotely execute some piece of exposed functionality. They both do it differently. SOAP resembles a remote function invocation, where we call an external function with some parameters. REST service, on the other hand, is focused around representation, so with REST service we pass or retrieve a resource from an external service.
We can follow a common dilemma though and try to wonder which type of service we’d chose when designing our own application. The thing that seems to stand out the most is the degree of coupling between servers and clients built with both approaches.
SOAP web service is prefered when:
- When a fixed contract in the form of WSDL is required between communicating applications. When the contract breaks, client and server are not able to communicate anymore.
- When we want to avoid building custom error handling. Soap protocol defines a Fault section carrying error information.
- When we want our integration to be oriented around calling a service method.
- When you’re sure that xml is the only format you can exchange information in
REST web service usage is prefered when:
- When you’re considering exchanging different data formats to xml. Rest services can carry data in XML, JSON, CSV etc.
- When you can cache response data.
- When you’re likely to be talking to JavaScript frontent. JavaScript seems to tolerate JSON much better than XML. Usual JSON messages are more light weight than XML
- When you want to avoid message contract and strong typing data types, which may be beneficial if your service consumers are running on different languages and platforms
The debate of SOAP vs REST services still seems very open. There are arguments in some articles that are quickly negated in next. I will leave a few articles here for inspiration.
- AllAroundJava’s REST Service referred to in this article
- A debate of Soap vs REST
- When is REST better than SOAP
- Some SOAP disadvantages
Beautiful overview of REST :)
I appreciate mentioning HATEOAS as it’s still not so popular standard.
Two comments regarding SOAP vs REST.
Now REST has some form of contract via Swagger (OpenAPI) which is much easier to maintenance than WSDL in SOAP.
There is one big advantage of REST when you create service interface based on it. REST as a representational state is designed for manipulating resources – it makes the interface much more clear, You can easier integrate with it because the REST methods often are self-explaining. In contrast SOAP doesn’t have a standard of designing and even when you know contract you don’t really know what exactly a particular method can do, or there is additional detailed description. I saw many SOAP services designed in wrong way – playing with them was a nightmare. Modifying big WSDL was a nightmare as well :)
Thanks ever so much for a valuable, practical addon Marek :)