1.13 The Richardson Maturity Model

In this tutorial, we'll learn about the Richardson Maturity Model, a way for REST APIs to be classified, and the "RESTfulness" of an API determined.

Notes

This is the final tutorial in section 1 API design. We've looked at different factors when building the RESTful API for the Messenger application. In this tutorial, we'll wrap up and take an overall look at how far we've come and what that means.

Below is the API documentation summary of what we have so far. I hope the choices and the design approach for this API is clear to you now. If you are unsure of why any part of the API is a particular way, I encourage you to revisit the relevant tutorial.

Messages

Operation URI Method Success / Failure Status code
Get message /messages/{messageId} GET Success 200
Not found 404
Failure 500
Delete message /messages/{messageId} DELETE Success 200 or 204
Not found 404
Failure 500
Edit message /messages/{messageId} PUT Success 200
Wrong format / data 400 or 415
Not found 404
Failure 500
Create message /messages POST Success 201
Wrong format / data 400 or 415
Failure 500

Profiles

Operation URI Method Success / Failure Status code
Get profile /profiles/{profileName} GET Success 200
Not found 404
Failure 500
Delete profile /profiles/{profileName} DELETE Success 200 or 204
Not found 404
Failure 500
Edit profile /profiles/{profileName} PUT Success 200
Wrong format / data 400 or 415
Not found 404
Failure 500
Create profile /profiles POST Success 201
Wrong format / data 400 or 415
Failure 500

Comments (and similarly Likes and Shares)

Operation URI Method Success / Failure Status code
Get comment /messages/{messageId}/comments/{commentId} GET Success 200
Not found 404
Failure 500
Delete comment /messages/{messageId}/comments/{commentId} DELETE Success 200 or 204
Not found 404
Failure 500
Edit comment /messages/{messageId}/comments/{commentId} PUT Success 200
Wrong format / data 400 or 415
Not found 404
Failure 500
Create comment /messages/{messageId}/comments POST Success 201
Wrong format / data 400 or 415
Failure 500

Now that we have designed the API this way, let's look at what this means. Are we in a position to say this API is "fully RESTful"? Remember, in the first tutorial, I mentioned that this isn't a yes or no question, and that there is a spectrum of anywhere from "not fully RESTful" to "almost RESTful" to "not RESTful at all". These terms are hard to work with. How do you know how RESTful an API is? Well, there is one way to know, and that's using a model developed by Leonard Richardson. It's called the Richardson Maturity Model, and it breaks down all the concepts we've discussed into 3 levels. Every REST API belongs to one of these 3 levels. The model also defines a Level 0 which is not a RESTful API. It is not necessary that every API score highly as per this model. But it helps to understand this model when designing any RESTful API so that you at least know where you stand. And try to make it better if possible.

Let's start with Level 0. I hope you are familiar with some of the basics of a SOAP web service. The way a SOAP web service generally works is that there is a URL called the endpoint where the service is exposed. One URL. That URL receives all requests from the client. If you were to write the Messenger API as a SOAP web service, you'd probably have one URI at /messenger. This URL receives all requests. How does it know what to do? How does the client tell it to do different stuff, like look up messages or delete a comment? Well, that happens in the message that's sent to this common URL. The message contains both the operation that needs to be performed, and the data that's needed for that operation. For example, the XML below could create a new message:

<create-message>
    <message-content>Hello World!</message-content>
    <message-author>koushik</message-author>
</create-message>

And a delete comment request (sent to the same URL) could look like this.

<delete-comment>
    <message-id>30</message-id>
    <comment-id>2</comment-id>
</delete-comment>

Notice that the operation that needs to be performed is a part of the request that's sent. This is how the same URL can be used for different operations. In fact, the same HTTP method can be used for each operation, because, all the details are in the request body. In fact, that's what SOAP does. The requests are always POST, with the POST body containing all the information.

This is Level 0 in the Richardson Maturity Model. This is often called the The swamp of POX. This refers to the common use of Plain Old XML (or POX) to define everything that an operation needs. No HTTP concepts are leveraged for communicating information between the server and client.

This design approach is obviously not something we want to do in this course. If you were to refine this model to introduce the concept of resource URIs, you will reach level 1 in the RMM. This is the starting level for RESTful APIs. The earlier level isn't even considered REST. We designed resource URIs for messages (/messages), profiles (/profiles) and so on. If you did just this, and nothing else, you stand at level 1. Now you have message requests going to one URI and all comments requests going to another URI. There would still be information about the operation in the requests, because the message URI needs to handle adding deleting or updating messages.

If you take the next step and use different HTTP methods for these different operations, then you've reached Level 2 in RMM. An API on Level 2 uses standard HTTP methods like GET, POST, PUT and DELETE to do different operations, on the resource URI. The URI specifies what resource is operated upon, and the HTTP method specifies what the operation is. There also needs to be better use of HTTP status codes, and the right use of idempotent and non-idempotent methods for an API to be at Level 2.

Finally, Level 3 is when you implement HATEOAS. That is, the responses have links that control the application state for the client. The client doesn't need to be aware of the different API URIs. All the URIs that the client would need is a part of the response that the server sends. If an API implements this, it is said to be at Level 3 of RMM, and is considered fully RESTful.

And there you go. Now you can look at any REST API design and easily identify which level in RMM it belongs to. Again, this is not supposed to be a strict rule. I encourage you to use this model as a guideline when designing your REST APIs, as a tool for learning and understanding, rather than a scorecard to measure with. You may not choose to make every API achieve Level 3 of RMM, but it helps to understand what the theoretical ideal is.

In the next section, we'll start looking at JAX-RS and start implementing this API. There's a lot to REST API design, and these tutorials have only scratched the surface. So, I do encourage you to explore more about REST APIs, and treat these tutorials as a starting point, rather than as complete learning.