It’s not unusual to see examples where people think they are “doing REST”, but are not. A lot of people are trying to use simple web technologies in their microservice architectures, but I suspect there’s a prevalent idea that if you are using HTTP and sending JSON back and forth, you’re doing REST, which is simply not the case. (We’re talking about the Representational State Transfer style of software architecture here, in case you’re lost.)
Spring’s REST
Spring’s Web MVC Framework documentation says in the first paragraph: “With the introduction of Spring 3.0, the @Controller
mechanism also allows you to create RESTful Web sites and applications…” Further on, introducing its @RestController
interface, it says: “It’s a very common use case to have Controllers implement a REST API, thus serving only JSON, XML or custom MediaType content.” So, does creating a web service using a @RestController
-annotated class magically make it a RESTful service?
No. Such no.
Not so REST
The big thing I see developers getting wrong when trying to use web technologies for inter-service communication is that they continue to think about operations. They continue to think at a procedural code level: “I want this piece of code to call that piece of code, but over the network.” This is just good old (bad old?) RPC – Remote Procedure Calls – not REST. In fact, I think the design of Spring’s @RequestMapping
method annotation technology actually encourages the creation of non-RESTful services, because it is all about making it easy to connect up the request for a particular URL path to the execution of a method.
Why is this an issue?
Because REST is not primarily about operations and executing code.
REST is primarily about resources, and transferring representations of them.
So, this is the first thing you should know about REST: if your URLs don’t refer to resources, you’re doing it wrong.
RESTful URLs do not identify operations. In REST architectures, the operation is always specified separately to the resource. When using HTTP as the transport, this means the operation is always specified as the HTTP method, not as part of the URL. Another way to remember this it is that the URL should never contain a verb. Observe:
Task | RESTful example | Non-RESTful examples |
---|---|---|
Retrieve a User record | GET /users/123456 |
GET /getUser?id=123456 |
You can see the key problem here: the non-RESTful examples contain the verb “get” in the URL. They are naming an operation, not a resource. Note that moving the ID into the path instead of a query parameter does not make this “getUser” example RESTful.
Here’s some more examples:
Task | RESTful example | Non-RESTful examples |
---|---|---|
Create a User record | POST /users |
POST /users/createUser |
Update a User record | PUT /users/123456 |
POST /users/updateUser |
Delete a User record | DELETE /users/123456 |
POST /users/deleteUser |
In the last two examples, we see the same resource, at the same location, being manipulated in two different ways.
Starting to think in terms of resources, and doing that by carefully designing the words in your URLs, is not always easy, and it doesn’t magically make what you’re doing RESTful. It’s a great place to start, though, because it will encourage you to think less about invoking code on a server and more about moving representations of your resources between the server and the client.
There’s obviously way more to REST than just what I’ve described here. Martin Fowler has a good discussion of a ‘maturity model’ for REST with examples. But if you know nothing else about REST, what you really need to know is to stop putting operations into your URLs and start thinking about the resources that you’re manipulating.
Want to learn more?
I’ve written a follow-up blog with two REST tips for tackling tricky resource examples.
Better than a couple of intro blogs, though, would be one of these books…
Updated 2015-06-24: The original article did not refer to @RestController.
It’s a bit unfair to blame Spring for not magically making everything RESTful when “allows you to create RESTful Web sites” is their only claim. The wording “allows you to…” makes it clear that the use of REST is optional. It’s the developers choice; and yes, some developers will opt for RPC-style instead.
Spring MVC is a generic web framework and not just “Spring’s REST” as your heading implies – that heritage is probably the reason why JAX-RS and other more specialized solutions offer APIs closer to the principles of REST, better guiding developers in the right direction.
Hi Henning. Thanks for your thoughts.
You’re right, of course, Spring is a generic web framework and not a REST-only framework. It’s not my intent to blame Spring for making people do it wrong. However, its creators do promote the framework as being good for REST, for instance with the @RestController annotation (which I didn’t originally mention in the blog but have added now) that, again, doesn’t make things magically RESTful.
My intention in bringing up Spring’s Web MVC framework is to highlight that, while it doesn’t force people to do it wrong, it also does little to help people get it right. I think it would be improved if, for those who wanted to design RESTful interfaces, it made the concept of “a resource” explicit, because that’s the central concept in REST, and kept the operation on the resource as a separate concept rather than simply letting people hook a URL up to some code to be executed.
I do not believe Spring MVC and RestController are suitable for developing Restful apps. I think their purpose is to provide an alternative way to create a view e.g. We don’t need to rely on a view tech to perform server-side rendering of the response.
Pingback: Two REST tips for tackling tricky resource examples - Evolvable Me