However, representing errors or problems cleanly in a RESTful way may not be immediately obvious since Spring MVC is so often referenced for building user interfaces. Because there is no direct
UI concept in REST APIs, how then do you use Spring MVC to represent errors or problems in a clean and intuitive way?
This article is Part 1 of a 2 part series. In this article, we’ll cover RESTful error reporting best practice conventions. Part 2 will show how to implement them with Spring MVC in a complete example web application.
If an error occurs, RESTful practices expect that we set an HTTP status code in the response to generally classify why the request failed. It is considered best practice by most REST API designers to re-use the status codes in the HTTP specification whenever possible, since so many existing HTTP clients understand most of these error conditions already and re-use encourages consistent behavior, which is always good for development.
However, there are only 24 commonly referenced HTTP status codes that are used for representing errors; there are 18 4xx codes representing client errors and 6 5xx codes representing server errors (there are other codes defined in specifications like WebDav, but they are not ubiquitous). A problem here is that these 24 are really general purpose codes – they likely don’t describe everything there is to know about a particular problem.
To best help your REST API customers, you ideally want to give them as much information as possible to help them diagnose and hopefully fix the problem. The name of the game is simplicity: the easier it is for them to use your REST API, the more likely it is they will adopt your service.
Because the status code is probably not enough, what else then can we provide to assist our end users whenever they encounter errors? An obvious item is human readable error message, to be easily read by developers. But there is even more information that we can add to provide a truly intuitive and helpful error representation.
Here is an example of what we consider a ‘best practice’ REST error response body representation to show relevant error data (the example is JSON, but XML would be fine too depending on what your API serves):
"message": "Oops! It looks like that file does not exist.",
"developerMessage": "File resource for path /uploads/foobar.txt does not exist. Please wait 10 minutes until the upload batch completes before checking again.",
We’ll describe the properties next.
The status property is merely the same HTTP status code (integer) in the response header. This is a convenience mechanism: by including the status code in the body, any REST client that processes the error has one and only one place to look to fully understand the error: the error representation itself. There is no need to check header values or other locations to understand the message.
The code property is an error code specific to your particular REST API. It is usually something that conveys information very specific to your problem domain.
This is convenient because of the limitation of having only 24 widely known general purpose HTTP error codes. By using your own codes, you can convey much more specific and richer reasons as to why something failed. Again, the more information that the API client can receive, the better.
In the example above, the code property has a value of 40483. While the general purpose “status”: 404 indicates that the requested resource was not found, perhaps there is an application-specific code of 40483 that indicates not only that the resource wasn’t found, but it wasn’t found due to the fact that it wasn’t yet uploaded to the server.
Granted, this particular ‘uploaded file’ example is somewhat contrived, but the key point here is that your API can convey a much richer set of error information if you leverage your own codes.
TIP: If your application does not have a specific error code for a particular error, it can be a good idea to default the code value to be the same as the status value. This ensures that the client always sees a code value and does not need to perform ‘does this property exist?’ logic. This is cleaner/easier for API consumers, and that’s a good thing for adoption.
The message property is a nice human readable error message that can potentially be shown directly to an application end user (not a developer). It should be friendly and easy to understand and convey a concise reason as to why the error occurred. It should probaby not contain technical information. Technical information should be in the developerMessage property instead (covered next).
Why is this useful?
If you have a REST API consumer (e.g. your customer), and that consumer wishes to relay the message value directly to the end user, they can do so. This allows API consumers to write user interfaces and support their own end-users very quickly without much work on their end. The more things you do to save them time and keep them happy using your API, the better.
The developerMessage property conveys any and all technical information that a developer calling your REST API might find useful. This is where you might include exception messages, stack traces, or anything else that you think will help a developer.
The moreInfo property specifies a URL that anyone seeing the error message can click (or copy and paste) in a browser. The target web page should describe the error condition fully, as well as potential solutions to help them resolve the error condition.
This is probably THE most important property of all because the target web page can be freely formatted to represent whatever information you wish. You could have links to your support department, ‘get help now’ chat dialogs, or whatever else you think might be useful. Show the developers love, and they’ll continue using your API.
Twilio for example has a great Error and Warning Dictionary that shows this concept in action. Learn it, love it, replicate it. Again, as much information as is possible is desired. Supply whatever you might think is necessary to help your API consumers/customers and keep them happy.
Continue on to part 2, where we show you how to ensure these error messages are easily returned from a Spring MVC-based REST API.