problem-details
problem-details copied to clipboard
Problem Details [RFC-9457] Java API, TCK, and implementations for JAX-RS and (currently not) Spring Boot
= Problem Detail image:https://maven-badges.herokuapp.com/maven-central/com.github.t1/problem-details/badge.svg[link=https://search.maven.org/artifact/com.github.t1/problem-details] image:https://github.com/t1/problem-details/actions/workflows/maven.yml/badge.svg[link=https://github.com/t1/problem-details/actions/workflows/maven.yml]
== Abstract
Map standard and custom exceptions to a http response body containing problem details as specified in https://datatracker.ietf.org/doc/html/rfc9457[RFC-9457] (formerly https://datatracker.ietf.org/doc/html/rfc7807[RFC-7807]).
Most things work out of the box: the type and title fields are derived from the exception class name; the detail field is the message of the exception; the instance field is a random UUID URN that is also logged together with the complete stack trace.
These defaults and the status code can be overridden with annotations.
I wrote a https://www.codecentric.de/wissens-hub/blog/rfc-7807-problem-details-with-spring-boot-and-jax-rs[blog] about this.
== Motivation
Getting a consistent error response format for a REST API is a common problem and allows clients to handle specific business errors. Getting some generic HTML response is not helpful. There is a standard for this type of details about an error: RFC-9457. And this library provides a simple way to map exceptions to this format.
== Spec & API
This has been proposed to and rejected by several existing specs:
- https://github.com/jakartaee/rest/issues/839[Jakarta REST (JAX-RS)]; a second discussion was also https://github.com/jakartaee/rest/issues/1150[rejected].
- https://github.com/eclipse/microprofile-rest-client/issues/248[MP REST Client].
The API in the api module looks quite stable. Some first ideas for a full spec follow below. It's yet far from complete, but it's a start:
- MUST
application/problem+json,application/problem+xml; SHOULD any, e.g.+yaml - SHOULD render
text/html - map also
@ValidREST params - logging: 4xx = DEBUG, 5xx = ERROR; configurable?
- order of extensions is alphabetic (which is better for tests than random)
- multiple extensions with the same name: undefined behavior
- JAXB can't unmarshal a subclass with the same type and namespace
- Security considerations: nothing dangerous in problem details (i.e. exception message); stack-trace in logs
- TODO scan client classpath for @Type annotated exceptions (and document this in the spec and the annotation)
- TODO inherited annotations
- TODO cause annotations
- TODO type factory, e.g. URL to OpenAPI
- TODO instance factory, e.g. URL to the logging system filtering on an UUID
== Dummy-Impl [ri]
It's called ri, but it's actually only a POC, and it's incomplete. See the README for details.
== Test
The test module runs integration tests by using https://github.com/t1/jee-testcontainers[JEE Testcontainers], i.e. it can be configured to start different Docker containers with various JEE application servers. By default, it starts a Wildfly.
testcontainer-running
As the containers don't yet implement the API by themselves, the dummy implementation ri is hard-wired in the tests for now.
=== Wildfly
Default mvn or explicitly mvn -Djee-testcontainer=wildfly
=== Open Liberty
mvn -Djee-testcontainer=open-liberty:19.0.0.9-javaee8-java11 -Pwith-slf4j
needs tag for jdk11 support needs dependencies on slf4j-api and slf4j-jdk14
=== TomEE
mvn -Djee-testcontainer=tomee
3 tests fail, because this version of TomEE (9.0.20 / 8.0.0-M3) doesn't write the problem detail response entity in some cases for some reason: StandardExceptionMappingIT.shouldMapWebApplicationExceptionWithoutEntityButMessage StandardExceptionMappingIT.shouldMapWebApplicationExceptionWithoutEntityOrMessage ValidationFailedExceptionMappingIT.shouldMapValidationFailedException
=== Payara
mvn -Djee-testcontainer=payara -Pwith-slf4j
fails due to lack of jdk11 support of the https://hub.docker.com/r/payara/server-full[payara] image.
needs dependencies on slf4j-api and slf4j-jdk14
== Spring
We build for JDK 11 and the Jakarta EE 10 APIs. The current versions of Spring Boot don't support this combination. But you can still use the older com.github.t1:problem-details-api:1.0.10, which was based on Jakarta EE 8.