In this post, we feature a comprehensive article about RESTful services with HATEOAS. REST: The Refresher.
“Oh no! Please, not another article about REST!” many of you may scream, and rightly so. There are so many tutorials, posts, discussions and best practices published already, than it hardly makes any sense to come up with one more.
Frankly speaking, the perception of what is REST differs from person to person. Not everyone has the time (and the desire) to read the Representational State Transfer (REST) chapter of the Roy Fielding’s excellent dissertation and as such, for many the REST became mostly a synonym to HTTP-based APIs, whatever that means. However, there is one side of REST which stays in the dark most of the time, groundlessly forgotten and neglected: hypermedia.
Table Of Contents
So what is the idea behind this writing? The sole purpose of the tutorial is to get back to the roots, rethink what it means to design and implement the web APIs following the REST architectural style and how it could be practically achieved in Java services and applications, or generally speaking, on JVM platform.
Representational State Transfer (or simply REST) is not a specification but rather an architectural style, the set of principles and constraints to guide the design of the distributed software systems. The system designed after REST architectural style has to conform to five mandatory (and one optional) constraints. Let us just briefly glance over them.
- Client / Server
In the age of microservices, it sounds like an obvious one. However, just to restate this foundational principle, the clients and the servers are detached from each other. As such, each party has the ability and the opportunity to evolve independently.
The communication between clients and servers should be stateless. In practice, this means that each request from client to server must contain all of the information necessary to process the request. Servers should not store any session-related state or context therefore clients are the ones responsible for managing that. This principle is often cited as the necessary prerequisite for building reliable and horizontally scalable systems.
The server has to be able to hint to the client if the data within a response could be cached or not. The efficient caching implementation could shave off the unnecessary load from servers, improve overall scalability and significantly reduce the latency of the network interactions.
- Layered System
This yet another foundational principle advocates towards architecting the systems to be composed of hierarchical layers. In terms of the client/server communication, the client cannot tell whether it is connected to the server directly or through any kind of intermediary (the first such intermediary that comes into mind is load balancer).
- Uniform Interface
In the context of our discussions, this is probably the most important architectural principle which emphasizes on the presence of the uniform interface between components. In turn, it outlines five constraints which such an interface should follow:
- identification of resources
- semantics of access methods is the same for all resources
- manipulation of resources through representations
- self-descriptive messages
- and, hypermedia as the engine of application state (HATEOAS)
- Code-On-Demand (optional)
This optional constraint advises that the client capabilities could be extended by downloading and executing some code from the server.
To reinforce it one more time, REST lays down a set of principles and constraints to architect and to design systems, by no means it is an implementation.
The REST architectural style does not restrict the client / server communication to a particular protocol. However, these days it is mostly exclusively used to build web APIs and services which talk over HTTP, the protocol of the Web.
In this context, the individual resources are identified using URLs. JSON or XML are two predominant formats to represent the resources whereas the client can manipulate the resources using appropriate HTTP verbs. And frankly speaking, most web API designers and implementers stop right there, no mention about HATEOAS whatsoever. Do all these people misunderstand what the term REST implies? The Roy Fielding summarized it in one of his tweets nicely:
I disagree that the popular understanding of the term is different. What is different is the desire of certain companies, authors, and speakers to say REST when they know it is just HTTP; not because they don’t know the meaning of the term, but because $$$ >> meaning. https://twitter.com/fielding/status/1108092713516163072?lang=en
It concludes the sad state of REST architectural style adoption in the industry. Yes, it appears to be everywhere, yet unfortunately, the majority of the web applications out there expose these APIs and services over HTTP using the RPC style rather than following the constraints (particularly, the Uniform Interface) clearly defined by REST.
Why is that? Probably, part of the reason is that REST architectural style mentions hypermedia and HATEOAS but does not really says how precisely it has to be done (taking into account all the complex interactions which may happen between client and server).
To some extent, people get REST wrong because I failed to include enough detail on media type design within my dissertation. That’s because I ran out of time, not because I thought it was any less important than the other aspects of REST. https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-724
In the same vein, for many it may look like a significant overhead to think about designing not only resources naming, representations, semantics and manipulations but also state transitions (not even touching the subject of testing all that).
However, I think most people just make the mistake that it should be simple to design simple things. In reality, the effort required to design something is inversely proportional to the simplicity of the result. As architectural styles go, REST is very simple. https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven#comment-724
I would argue that following the REST architectural style is worth the effort. Yes, you might be overwhelmed by the choices. Yes, you may face a lot of challenges due to immature tooling and libraries for your programming language or platform, particularly with respect to hypermedia. On the other side, you would end up with much descriptive, understandable and maintainable web services and APIs.
A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations. The transitions may be determined (or limited by) the client’s knowledge of media types and resource communication mechanisms, both of which may be improved on-the-fly (e.g., code-on-demand). https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
Hopefully, along the course of this tutorial we are going to debunk some myths and prove in practical ways that the HATEOAS powered web services and APIs are possible and are not that hard.
Since many organizations and individuals were building the web services and APIs using own interpretation of what is REST, it led to confusion regarding what kind of applications and systems are actually following the REST architectural style. To make this distinction obvious, the term RESTful was born.
Web service APIs that adhere to the REST architectural constraints are called RESTful APIs. https://en.wikipedia.org/wiki/Representational_state_transfer
Essentially, this definition gives no room to mangle with: either all required constraints are met or please do not call your APIs RESTful. Unsurprisingly, Roy Fielding has even stricter opinion on the matter.
What needs to be done to make the REST architectural style clear on the notion that hypertext is a constraint? In other words, if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period. Is there some broken manual somewhere that needs to be fixed? https://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
The goal of this tutorial is to showcase the design of the RESTful APIs where HATEOAS is a first class citizen, along with all other required constraints. And no, we are not going to treat REST as the religion but rather demonstrate that every element matters and is there for a reason.
The fragmentation of web services and APIs living under REST umbrella screamed for action. In response, Leonard Richardson developed an API maturity model (often called just Richardson Maturity Model), which essentially defines 4 levels of API maturity.
This quite simple model helps to identify with ease where the particular web API stays with respect to its journey towards being RESTful (please notice that each level builds on top of the ones below it). You may also notice that the model is not universally applicable and explicitly focuses on REST over HTTP protocol (as we remember, REST architectural style is agnostic to underlying network protocol).
- Level 0 – The Swamp of POX
At the very bottom are the web APIs which use HTTP protocol for remote interaction to tunnel requests and responses. Usually, they use single HTTP method (POST as a rule) and expose the single API entry point. This is a typical RPC over HTTP style.
- Level 1 – Resources
Climbing the maturity ladder a bit we run into web APIs which expose more than one entry point, or following the REST nomenclature, individual resources. Certainly a progress but these APIs still use single HTTP method (POST as a rule) though.
- Level 2 – HTTP Verbs
To get one step closer to comply with RESTful principles, web APIs at this level utilize the HTTP verbs semantics to distinguish different actions over individual resources. This is the level most modern web APIs end up with, claiming to be “good enough”.
- Level 3 – Hypermedia Controls
At the very top we encounter the web APIs which use HATEOAS and hypermedia control to guide the client / server interactions. At this level, the APIs could be called truly RESTful.
Armed with this maturity model, whenever you hear “… in our organization we build applications which expose REST web APIs …”, it is very likely that we are talking about Level 2.
In this introductory part of the tutorial we have refreshed our knowledge about the REST architectural style and in particular, revisited its mandatory principles and constraints. We have also demystified the origins of the term RESTful and how it applies to the modern web APIs and services. Yet again, Roy Fielding nailed it down extremely well.
An API that provides network-based access to resources via a uniform interface of self-descriptive messages containing hypertext to indicate potential state transitions might be part of an overall system that is a RESTful application https://twitter.com/fielding/status/1125438763507654658
In the upcoming parts of the tutorial we are going to spend most of the time talking about HATEOAS, probably the hardest but also the most powerful element of any API which claims to be called genuinely RESTful.
In the next section of the tutorial we are going to begin discussing numerous ways to enrich your web services and APIs with HATEOAS capabilities.