Spring-boot: Consider using RFC 7807 problem details for error responses

Created on 3 Jan 2020  路  9Comments  路  Source: spring-projects/spring-boot

Right now Spring Boot is using an ad hoc format for error responses. Often, applications are configured to support JSON/XML formats and the error map is serialized with such message converters for machine clients, alternatively errors are rendered as HTML pages for browsers.

We could consider using a better defined format for Spring Boot errors, here the RFC 7807 "problem details" specification. This specification can carry error responses like the following:

   HTTP/1.1 403 Forbidden
   Content-Type: application/problem+json
   Content-Language: en

   {
    "type": "https://example.com/probs/out-of-credit",
    "title": "You do not have enough credit.",
    "detail": "Your current balance is 30, but that costs 50.",
    "instance": "/account/12345/msgs/abc",
    "balance": 30,
    "accounts": ["/account/12345",
                 "/account/67890"]
   }

This could improve error handling in several ways.

First, we could add more contextual information to error maps, like "type", "title" and "detail" and provide application hook points to translate application exceptions to problem details (see the Zalando library for this).

Also, in cases like #19522 and spring-projects/spring-framework#23421, it could allow HTTP clients to add the specific media type "application/problem+json" to their "Accept" header - and would disambiguate about the format to use when rendering errors. Right now, "application/json" and "application/xml" are the common ones but it's hard to differentiate between application payload and error payloads.

noteworthy enhancement

Most helpful comment

I like to map exceptions to rfc-7807 compliant bodies on the server side and/or back to exceptions on the client side (note: they don't have to be the same exception, they only have to be compatible). I defined an API and wrote an implementation where you can rely on useful defaults for the fields or annotate your exceptions when you have specific requirements: https://github.com/t1/problem-details

I鈥檝e blogged about the topic in more detail: https://blog.codecentric.de/en/2020/01/rfc-7807-problem-details-with-spring-boot-and-jax-rs/

I also created a PR for Microprofile Sandbox, as I think it should be a common standard.

I would be glad to contribute the Spring Boot implementation.

In order to make the client side feel more organic, maybe we would need to scan for all exceptions?

Any feedback (except for silence ;-) is welcome!

All 9 comments

My two cents regarding JSON errors in general: in basically every project using Spring Boot for HTTP services, and a JavaScript framework (such as Angular or Vue), I always need to customize the JSON error sent by Spring Boot in order to

  • allow the client to distinguish between unexpected errors, that shouldn't happen if the client is correctly implemented (such as forgetting to provide a required input), and expected ones that must be handled in a specific way by the client (such as providing a value that only the server can check as invalid, like a duplicate identifier or a multipart file with invalid data)
  • allow the client to get an error key, used to display an i18ned error message (the i18n of the error messages is done at client side, as everything else in the pages), sometimes with a map of parameter keys and values (example: { "errorKey": "error.accountBanalnceTooLow", errorParams: { "currentBalance": 100 } })

I haven't read the RFC very carefully yet, but if Spring Boot could provide a standard way to support this common (in my experience) need, it would be great. Or at least not lose the possibility to do it ourselves, and maybe document what the best strategy is to do it by respecting the standard.

I like to map exceptions to rfc-7807 compliant bodies on the server side and/or back to exceptions on the client side (note: they don't have to be the same exception, they only have to be compatible). I defined an API and wrote an implementation where you can rely on useful defaults for the fields or annotate your exceptions when you have specific requirements: https://github.com/t1/problem-details

I鈥檝e blogged about the topic in more detail: https://blog.codecentric.de/en/2020/01/rfc-7807-problem-details-with-spring-boot-and-jax-rs/

I also created a PR for Microprofile Sandbox, as I think it should be a common standard.

I would be glad to contribute the Spring Boot implementation.

In order to make the client side feel more organic, maybe we would need to scan for all exceptions?

Any feedback (except for silence ;-) is welcome!

Yes agreed. A spring implementation of rfc 7807 would be great!

Currently I'm looking into error handling in Spring Boot applications and found RFC 7807 to be very interesting. I like that by default it allows me to give meaningful and helpful Problem responses while hiding implementation details like stacktraces or class names for advanced security.

So I would also welcome this in Spring (Boot).

@t1 thank you for the detailed and practical article

Spring HATEOAS provides basic support for RFC-7807 since 1.1, see spring-projects/spring-hateoas#1057 and the relevant chapter of reference manual.

Now, this might not mean too much for Spring (Boot) users that don't use Spring HATEOAS, but since RFC-7807 is IMO a generally very useful spec, I wonder whether this basic support could be moved to Spring Framework proper? Because it is something that has a clear use even without the involvement of Spring HATEOAS and/or Spring Boot. Both could then leverage the Framework support and build their own extended support on top of it. WDYT @bclozel and @gregturn?

Also, seeing this was twice marked as for: team-attention, could Spring Boot team share outcome of those discussions?

@vpavic I don't think there really was an outcome from the team discussions. We probably flagged it to discuss how easy it would be to get it into a release, but ultimately decided to prioritize other issues.

Naturally I鈥檇 favor this. At least the domain types from Spring HATEOAS could be moved, giving universal access to them.

But we鈥檇 need agreement between Framework and Boot on this approach.

Also timing will be a bit tricky given that we're not expecting a Framework 5.4 release.

Building the response Problem object by hand looks like a lot of boiler plate code to me. I think throwing a specific business exception and have that automatically mapped to a reasonable problem detail by default (with some annotations for specialization) is much easier, esp. if this also _works on the client side_! (for more details take a look at my blog mentioned above).

Was this page helpful?
0 / 5 - 0 ratings