1. Context

This is a Java library for working with RFC 9457 standardized Belgif problems.

With this library, RFC 9457 Problems can be automagically treated as standard java exceptions:

  • the server side can throw io.github.belgif.rest.problem.api.Problem exceptions (or subclasses), which are transparently converted to RFC 9457 compliant "application/problem+json" responses

  • the client side can catch io.github.belgif.rest.problem.api.Problem exceptions (or subclasses), which are transparently thrown when an RFC 9457 compliant "application/problem+json" response is received

The library consists of these modules:

  • belgif-rest-problem: library for RFC 9457 standardized Belgif problems

  • belgif-rest-problem-java-ee: Java EE / Jakarta EE integration for belgif-rest-problem

  • belgif-rest-problem-spring-boot-2: Spring Boot 2.x integration for belgif-rest-problem

  • belgif-rest-problem-spring-boot-3: Spring Boot 3.x integration for belgif-rest-problem

  • belgif-rest-problem-quarkus: Quarkus integration for belgif-rest-problem

  • belgif-rest-problem-validator: validation library that generates Belgif-compliant BadRequestProblem with InputValidationIssues

2. Release notes

2.1. Version 0.15

belgif-rest-problem:

  • Align MismatchedInputException detail message with Bean Validation

  • Fix input path for MismatchedInputException on array properties

belgif-rest-problem-quarkus:

  • Add experimental support for Quarkus in native mode

2.2. Version 0.14

belgif-rest-problem:

  • Map Jackson MismatchedInputException (for missing required properties on request body) to BadRequestProblem

2.3. Version 0.13

belgif-rest-problem-spring:

  • Extract ProblemResponseErrorHandler and ProblemRestTemplateCustomizer to belgif-rest-problem-spring-boot-2 and belgif-rest-problem-spring-boot-3 to fix NoSuchMethodError compatibility issue

2.4. Version 0.12

belgif-rest-problem:

  • Add internationalization support for localized detail messages based on Accept-Language HTTP request header

  • Don’t include null (issue) input values when serializing

  • Replace urn:problem-type:cbss:input-validation:referencedResourceNotFound by standardized urn:problem-type:belgif:input-validation:referencedResourceNotFound

  • Add fluent setter methods:

    • Problem: detail, href, instance, additionalProperties

    • InputValidationProblem: issues

    • RetryAfterProblem: retryAfter, retryAfterSec

  • Improve WWW-Authenticate header for token-related problem types:

    • Support setting the "realm" attribute

    • Add "error_description" and "scope" attributes for missing_scope

belgif-rest-problem-spring:

  • Fix compatibility issue with Spring Boot 3.4

belgif-rest-problem-quarkus:

  • New module for Quarkus support (only in JVM mode)

belgif-rest-problem-bom:

  • Added jakarta classifier artifacts

2.5. Version 0.11

belgif-rest-problem:

  • Add in(Input<?>) to InputValidationIssue for a fluent single input setter

belgif-rest-problem-spring:

  • Fix non-deterministic configuration for retrieving parameter names from Spring MVC annotations

2.6. Version 0.10

belgif-rest-problem:

  • Remove @ApplicationException annotation on Problem, because it could potentially cause compilation errors when used in combination with annotation processors

  • Disallow creation of InputValidationIssue with inputs[] of size 1

    Potentially breaking:

    • removed InputValidationIssue.setInputs(List<Input<?>> inputs)

    • removed InputValidationIssue.setInputs(Input<?>…​ inputs)

    • removed InputValidationIssue.input(Input<?> input)

belgif-rest-problem-java-ee:

  • Add EJBExceptionMapper that unwraps Problem cause, to address the removed @ApplicationException annotation

belgif-rest-problem-spring:

2.7. Older versions

3. Getting started

3.1. Dependencies

3.1.1. Spring Boot

Spring Boot 3 (Maven)
<dependency>
  <groupId>io.github.belgif.rest.problem</groupId>
  <artifactId>belgif-rest-problem-spring-boot-3</artifactId>
  <version>latest</version>
</dependency>
Spring Boot 3 (Gradle)
compile 'io.github.belgif.rest.problem:belgif-rest-problem-spring-boot-3:latest'
Spring Boot 2 (Maven)
<dependency>
  <groupId>io.github.belgif.rest.problem</groupId>
  <artifactId>belgif-rest-problem-spring-boot-2</artifactId>
  <version>latest</version>
</dependency>
Spring Boot 2 (Gradle)
compile 'io.github.belgif.rest.problem:belgif-rest-problem-spring-boot-2:latest'

3.1.2. Jakarta EE

Jakarta EE 9+ (Maven)
<dependency>
  <groupId>io.github.belgif.rest.problem</groupId>
  <artifactId>belgif-rest-problem-java-ee</artifactId>
  <version>latest</version>
  <classifier>jakarta</classifier>
</dependency>
Jakarta EE 9+ (Gradle)
compile 'io.github.belgif.rest.problem:belgif-rest-problem-java-ee:latest:jakarta'
Java EE 8- (Maven)
<dependency>
  <groupId>io.github.belgif.rest.problem</groupId>
  <artifactId>belgif-rest-problem-java-ee</artifactId>
  <version>latest</version>
</dependency>
Java EE 8- (Gradle)
compile 'io.github.belgif.rest.problem:belgif-rest-problem-java-ee:latest'

3.1.3. Quarkus

Quarkus support is currently still experimental.
Maven
<dependency>
  <groupId>io.github.belgif.rest.problem</groupId>
  <artifactId>belgif-rest-problem-quarkus</artifactId>
  <version>latest</version>
</dependency>
Gradle
compile 'io.github.belgif.rest.problem:belgif-rest-problem-quarkus:latest'

3.2. Usage

At the core of this library lies an exception hierarchy of Belgif-standardized problem types, with the possibility to define your own custom problem types. Integration with Spring Boot and Jakarta EE works out of the box.

3.2.1. Returning a problem from a REST API

When implementing a REST API, returning a problem is as simple as throwing the problem exception from your application code:

Throwing a problem
throw new BadRequestProblem(
        new InputValidationIssue(InEnum.PATH, "sectorCode", sectorCode)
                .title("Invalid sector code"));

This will return following HTTP response:

400 Bad Request
Content-Type: application/problem+json

{
  "type": "urn:problem-type:belgif:badRequest",
  "href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
  "title": "Bad Request",
  "status": 400,
  "detail": "The input message is incorrect",
  "issues": [
    {
      "title": "Invalid sector code",
      "in": "path",
      "name": "sectorCode"
    }
  ]
}

3.2.2. Catching problems when calling a REST API

When calling a REST API, handling a problem is as simple as catching the problem exception in your application code:

Handling a problem on the client
try {
    api.someOperation();
} catch (BadRequestProblem p) {
    String detail = p.getDetail();
    List<InputValidationIssue> issues = p.getIssues();
    // handle the BadRequestProblem
} catch (ResourceNotFoundProblem p) {
    String detail = p.getDetail();
    List<InputValidationIssue> issues = p.getIssues();
    // handle the ResourceNotFoundProblem
} catch (Problem e) {
    // handle all other problems
}
If the REST API returns a problem type for which you do not have a corresponding @ProblemType on your classpath, a DefaultProblem is thrown instead as fallback. See @ProblemType and ProblemTypeRegistry for more details.

3.3. Spring Boot

As of version 6.0, Spring Framework also contains basic integration for RFC 9475 problem types.
This is disabled by default, and MUST NOT be enabled.

3.3.1. RestController

Problem exceptions and framework exceptions thrown by RestController components are automatically converted to a proper RFC 9457 application/problem+json response.

Bean validation

Exceptions thrown by the Java Bean Validation Framework are automatically converted to a proper RFC 9457 application/problem+json response.

When using a Spring MVC annotation without name (e.g. @RequestParam String name instead of @RequestParam("name") String name), the parameter name for Bean Validation errors is retrieved via reflection as fallback. For this to work, your application code must be compiled with the -parameters flag (see maven-compiler-plugin). Otherwise, you will see parameter names like arg0.
Atlassian swagger-request-validator

InvalidRequestExceptions thrown by the Atlassian swagger-request-validator are automatically converted to a proper RFC 9457 application/problem+json response.

3.3.2. RestTemplate

Problem support is automatically enabled when constructing your RestTemplate through an autowired RestTemplateBuilder.

When manually constructing a RestTemplate instance, you’ll need to apply the ProblemRestTemplateCustomizer yourself.

3.3.3. Reactive WebClient

Problem support is automatically enabled when constructing your WebClient through an autowired WebClient.Builder.

When manually constructing a WebClient instance, you’ll need to apply the ProblemWebClientCustomizer yourself.

3.3.4. RestClient

Problem support is automatically enabled when constructing your RestClient through an autowired RestClient.Builder.

When manually constructing a RestClient instance, you’ll need to apply the ProblemRestClientCustomizer yourself.

3.4. Jakarta EE

While this library may work on other application servers, it has only been thoroughly tested on JBoss EAP 7.4 (with MicroProfile XP 4.0) and WildFly 31.

Furthermore, the following dependencies are expected to be "provided" by the application server. If not, you’ll need to add these dependencies to your application:

  • com.fasterxml.jackson.core:jackson-databind

  • org.slf4j:slf4j-api

3.4.1. JAX-RS service

Problem exceptions and framework exceptions (including bean validation) thrown by JAX-RS service components are automatically converted to a proper RFC 9457 application/problem+json response.

3.4.2. JAX-RS client

Problem support is automatically enabled for @Inject-ed javax.ws.rs.client.Client(Builder).

When manually constructing a JAX-RS client instance, you’ll need to wrap it yourself with client = ProblemSupport.enable(client).

JAX-RS async and reactive client API are not fully supported yet.

3.4.3. MicroProfile REST Client

Problem support is automatically enabled for MicroProfile REST Client.

3.4.4. RESTEasy Proxy Framework

Problem support must be manually enabled for RESTEasy Proxy Framework by wrapping the proxy with client = ProblemSupport.enable(client).

3.5. Quarkus

Quarkus support is currently still experimental.

Similar to Jakarta EE, transparent problem support is provided for JAX-RS, Bean Validation and MicroProfile REST Client.

Note that, in order for @ProblemType classes to be discovered on Quarkus, the standard bean discovery constraints apply (e.g. beans.xml or jandex index).

3.6. Code generators

Code generators should be configured to use the belgif-rest-problem types for problem-related model classes, instead of generating them.

3.6.1. openapi-generator-maven-plugin

When using openapi-generator-maven-plugin, configure <schemaMappings> as follows:

<schemaMappings>
  Problem=io.github.belgif.rest.problem.api.Problem,
  InputValidationProblem=io.github.belgif.rest.problem.api.InputValidationProblem,
  InputValidationIssue=io.github.belgif.rest.problem.api.InputValidationIssue,
  InvalidParamProblem=io.github.belgif.rest.problem.api.InputValidationProblem,
  InvalidParam=io.github.belgif.rest.problem.api.InvalidParam
</schemaMappings>

3.6.2. swagger-codegen-maven-plugin

When using swagger-codegen-maven-plugin, configure <importMappings> as follows:

<importMappings>
  Problem=io.github.belgif.rest.problem.api.Problem,
  InputValidationProblem=io.github.belgif.rest.problem.api.InputValidationProblem,
  InputValidationIssue=io.github.belgif.rest.problem.api.InputValidationIssue,
  InvalidParamProblem=io.github.belgif.rest.problem.api.InputValidationProblem,
  InvalidParam=io.github.belgif.rest.problem.api.InvalidParam
</importMappings>

4. Problems

The Belgif REST Guidelines define a standard error handling approach, based on RFC 9457 "Problem Details for HTTP APIs".

The belgif-rest-problem library implements these standardized problem types as an exception hierarchy, with an abstract io.github.belgif.rest.problem.api.Problem base class (containing the standardized "type", "href", "title", "status", "detail" and "instance" properties).

Problem
├── ClientProblem (4xx)
|   └── InputValidationProblem 1..* InputValidationIssue
├── ServerProblem (5xx)
└── DefaultProblem (fallback)

4.1. Belgif problem types

The package io.github.belgif.rest.problem contains all problem types defined in the Belgif REST Guidelines.

Problem
├── ClientProblem (4xx)
|   ├── InputValidationProblem 1..* InputValidationIssue
|   |   ├── BadRequestProblem (400)
|   |   ├── MissingPermissionProblem (403)
|   |   └── ResourceNotFoundProblem (404)
|   ├── ExpiredAccessTokenProblem (401)
|   ├── InvalidAccessTokenProblem (401)
|   ├── NoAccessTokenProblem (401)
|   ├── MissingScopeProblem (403)
|   ├── PayloadTooLargeProblem (413)
|   ├── TooManyRequestsProblem (429)
|   └── TooManyFailedRequestsProblem (429)
└── ServerProblem (5xx)
    ├── InternalServerErrorProblem (500)
    ├── BadGatewayProblem (502)
    └── ServiceUnavailableProblem (503)
  • The BadRequestProblem is backwards compatible with the deprecated InvalidParamProblem (with invalidParams[] instead of issues[]) of openapi-problem 1.1.

  • Besides the standard in/name/value properties for referencing a single input, the InputValidationIssue class also supports an inputs[] array for referencing multiple in/name/value inputs. This is not currently standardized.

  • MissingPermissionProblem extending InputValidationProblem is not currently standardized.

4.2. Custom problem types

Besides the standardized Belgif problem types, custom problem types can also be defined.

The naming convention should be respected for custom problem type URIs:

  • urn:problem-type:<org>:<type> for organization-wide problem types

  • urn:problem-type:<org>:<api>:<type> for API-local problem types

Implementing an API-local custom problem type
@ProblemType(TooManyResultsProblem.TYPE)
public static class TooManyResultsProblem extends ClientProblem
        implements FluentProblem<TooManyResultsProblem> {

    public static final String TYPE = "urn:problem-type:cbss:legallog:tooManyResults";
    public static final URI TYPE_URI = URI.create(TYPE);
    public static final URI HREF =
            URI.create("https://api.ksz-bcss.fgov.be/legallog/v1/refData/problemTypes/" + TYPE);
    public static final String TITLE = "Too Many Results";
    public static final int STATUS = 400;

    private static final long serialVersionUID = 1L;

    public TooManyResultsProblem() {
        super(TYPE_URI, HREF, TITLE, STATUS);
        setDetail("Result's number of global transactions exceeds the limit");
    }

    public TooManyResultsProblem(int limit) {
        this();
        setDetail("Result's number of global transactions exceeds the limit of " + limit);
    }

}

If you want fluent setter properties in your custom problem type, you can implement the FluentProblem interface. Your custom problem type can define additional properties if necessary. For problem types related to input parameters, you can extend from InputValidationProblem instead of Problem.

Don’t forget to add the @ProblemType annotation.

On Jakarta EE containers, custom problem types are discovered automagically through CDI.

On Spring Boot, only package io.github.belgif.rest.problem is scanned for @ProblemType annotations.
Additional packages to scan can be configured in your application.properties:

io.github.belgif.rest.problem.scan-additional-problem-packages=com.acme.custom

5. belgif-rest-problem-validator

The io.github.belgif.rest.problem.validation.RequestValidator can be used to perform validations on the input parameters of an API request. This validation does not stop on the first invalid input. It performs all configured validations and if any of them failed, a BadRequestProblem is thrown, containing each encountered InputValidationIssue.

RequestValidator
// example for an API resource with query parameters:
// ssin, enterpriseNumber, startDate, endDate and password
new RequestValidator()
        .ssin(Input.query("ssin", ssin)) (1)
        .enterpriseNumber(Input.query("enterpriseNumber", enterpriseNumber)) (2)
        .period(Input.query("startDate", startDate), Input.query("endDate", endDate)) (3)
        .exactlyOneOf(Input.query("ssin", ssin),
                Input.query("enterpriseNumber", enterpriseNumber)) (4)
        .custom(() -> { (5)
            // custom validation logic returning Optional<InputValidationIssue>
            if (!"secret".equals(password)) {
                return Optional.of(new InputValidationIssue(InEnum.QUERY, "password", password)
                        .type("urn:problem-type:cbss:input-validation:example:invalidPassword")
                        .title("Invalid password"));
            }
            return Optional.empty();
        })
        .validate(); (6)
1 validate SSIN structure
2 validate enterprise number structure
3 validate endDate >= startDate
4 cross-parameter validation: either ssin or enterprise number should be present, but not both
5 custom validations are also supported
6 perform the configured validations, throws BadRequestProblem if any validations failed
Example BadRequestProblem for invalid request /resource?ssin=00000000000&enterpriseNumber=1111111111&startDate=2023-12-31&endDate=2023-01-01&password=oops
{
  "type": "urn:problem-type:belgif:badRequest",
  "href": "https://www.belgif.be/specification/rest/api-guide/problems/badRequest.html",
  "title": "Bad Request",
  "status": 400,
  "detail": "The input message is incorrect",
  "issues": [
    {
      "type": "urn:problem-type:cbss:input-validation:invalidStructure",
      "title": "Input value has invalid structure",
      "detail": "SSIN 11111111111 is invalid",
      "in": "query",
      "name": "ssin",
      "value": "11111111111"
    },
    {
      "type": "urn:problem-type:cbss:input-validation:invalidStructure",
      "title": "Input value has invalid structure",
      "detail": "Enterprise number 2222222222 is invalid",
      "in": "query",
      "name": "enterpriseNumber",
      "value": "2222222222"
    },
    {
      "type": "urn:problem-type:cbss:input-validation:invalidPeriod",
      "title": "Period is invalid",
      "detail": "endDate should not preceed startDate",
      "inputs": [
        {
          "in": "query",
          "name": "startDate",
          "value": "2023-12-31"
        },
        {
          "in": "query",
          "name": "endDate",
          "value": "2023-01-01"
        }
      ]
    },
    {
      "type": "urn:problem-type:cbss:input-validation:exactlyOneOfExpected",
      "title": "Exactly one of these inputs must be present",
      "detail": "Exactly one of these inputs must be present: ssin, enterpriseNumber",
      "inputs": [
        {
          "in": "query",
          "name": "ssin",
          "value": "11111111111"
        },
        {
          "in": "query",
          "name": "enterpriseNumber",
          "value": "2222222222"
        }
      ]
    },
    {
      "type": "urn:problem-type:cbss:input-validation:example:invalidPassword",
      "title": "Invalid password",
      "in": "query",
      "name": "password",
      "value": "oops"
    }
  ]
}

Extending the RequestValidator

You may have a need to extend the RequestValidator with custom organization- or domain-specific validations.
This is possible by extending the AbstractRequestValidator base class.

If in turn, you want your own validator implementation to be extensible as well, you can propagate the extensible fluent builder pattern as follows:

Extensible request validator
 public abstract class AbstractMyRequestValidator<SELF extends AbstractMyRequestValidator<SELF>>
         extends AbstractRequestValidator<SELF> {

     public SELF something(Input<String> input) {
         addValidator(new SomethingValidator(input));
         return getThis();
     }

 }

 public final class MyRequestValidator extends AbstractMyRequestValidator<MyRequestValidator> {

 }

6. Internationalization (I18N)

The detail messages of Belgif problem and issue types can be localized to the language requested in the Accept-Language HTTP request header.

The default language is English, and translations are available in the 3 official Belgian languages (Dutch, French and German).

An I18N helper class is available in case you want to provide localized messages for your own custom problem and issue types.

The I18N feature of the problem library can be disabled by configuring property:

io.github.belgif.rest.problem.i18n=false

On Spring Boot, this can be configured via any of the standard externalized configuration mechanisms.

On Jakarta EE, this can be configured as a system property, environment variable, or web.xml context-param (in that order of precedence).

On Quarkus, this can be configured via any of the standard MicroProfile Config Sources.

On Quarkus, you also need to add the following configuration property if you want the Bean Validation messages to be localized too: quarkus.locales=en,fr-BE,nl-BE,de-BE.

6.1. LocaleResolver

The java ServiceLoader SPI is used to make the LocaleResolver implementation (used for retrieving the current request locale) pluggable.

On Spring Boot, a default implementation is provided that retrieves the locale from the LocaleContextHolder.

On Jakarta EE, a default implementation is provided that retrieves the locale from a thread-local variable that gets initialized with the value from the Accept-Language header.

On Quarkus, a default implementation is provided that retrieves the locale from a request-scoped CDI bean that gets initialized with the value from the Accept-Language header.

Applications can provide and register their own LocaleResolver if needed (/META-INF/services/io.github.belgif.rest.problem.i18n.LocaleResolver).

7. Implementation details

This section describes the internal implementation details of this library.

7.1. @ProblemType and ProblemTypeRegistry

This library makes use of Jackson’s polymorphic deserialization feature, so the Jackson ObjectMapper knows which problem type to instantiate when deserializing a problem. The problem subclasses have their problem type URI configured in the @ProblemType annotation.

These are discovered automagically by a ProblemTypeRegistry implementation.

  • in a Jakarta EE container, this is done by the CdiProblemTypeRegistry CDI extension, integrated with the Jackson ObjectMapper by the CdiProblemModule.

  • in a Spring Boot container, this is done by the SpringProblemTypeRegistry, integrated with the Jackson ObjectMapper by the SpringProblemModule.

When deserializing a problem for which no corresponding @ProblemType was found on the classpath, a DefaultProblem is used as fallback.

7.2. belgif-rest-problem-java-ee

This module provides components that handle Java EE / Jakarta EE integration with the belgif-rest-problem library:

  • CdiProblemTypeRegistry: ProblemTypeRegistry implementation that uses CDI component scanning to detect @ProblemType annotations.

  • CdiProblemModule: a Jackson Module that registers the CdiProblemTypeRegistry.

  • ProblemObjectMapperContextResolver: a JAX-RS ContextResolver for a Jackson ObjectMapper with the CdiProblemModule registered. Its priority of "Priorities.USER + 200" allows it to be overridden if needed by the client application.

  • ConstraintViolationExceptionMapper: a JAX-RS ExceptionMapper that converts ConstraintViolationException to an HTTP 400 BadRequestProblem.

  • JacksonMismatchedInputExceptionMapper: a JAX-RS ExceptionMapper that converts jackson MismatchedInputException to an HTTP 400 BadRequestProblem.

  • ProblemExceptionMapper: a JAX-RS ExceptionMapper that converts Problem exceptions to a proper application/problem+json response.

  • WebApplicationExceptionMapper: a JAX-RS ExceptionMapper that handles WebApplicationExceptions thrown by the JAX-RS runtime itself, to prevent them from being handled by the DefaultExceptionMapper.

  • DefaultExceptionMapper: a JAX-RS ExceptionMapper that converts any other uncaught exception to an HTTP 500 InternalServerErrorProblem.

  • EJBExceptionMapper: a JAX-RS ExceptionMapper that handles EJBExceptions. Routes to ProblemExceptionMapper when the EJBException is caused by a Problem exception. Otherwise, routes to DefaultExceptionMapper.

  • JaxRsParameterNameProvider: a bean validation ParameterNameProvider that retrieves parameter names from JAX-RS annotations

  • JAX-RS Client integration:

    • ProblemClientResponseFilter: JAX-RS ClientResponseFilter that converts problem response to a ProblemWrapper exception.

      In accordance with the spec, any exception thrown by a JAX-RS ClientResponseFilter gets wrapped in a ResponseProcessingException, unless the exception itself is a ResponseProcessingException. For that reason, the ProblemClientResponseFilter wraps the Problem exception in a "ProblemWrapper" class that extends ResponseProcessingException.
    • ProblemSupport: for programmatically enabling unwrapping of ProblemWrapper to Problem exceptions on a JAX-RS Client (also works for RESTEasy Proxy Framework clients).

      private Client client = ProblemSupport.enable(ClientBuilder.newClient());
    • ProblemClientBuilderProducer: makes ProblemSupport-enabled ClientBuilder and Client beans available for CDI @Inject

      @Inject
      public void setClient(Client client) {
          this.client = client;
      }
  • MicroProfile REST Client integration:

    • ProblemResponseExceptionMapper: a ResponseExceptionMapper that converts problem responses to Problem exceptions.

    • ProblemRestClientListener: a RestClientListener that registers the ProblemObjectMapperContextResolver and ProblemResponseExceptionMapper.

  • Jakarta EE 9+: the main belgif-rest-problem-java-ee artifact targets Java EE (javax package namespace). A secondary artifact that targets Jakarta EE 9+ (jakarta package namespace) is available with <classifier>jakarta</classifier>.

7.3. belgif-rest-problem-spring

This module provides auto-configuration for components that handle Spring Boot integration with the belgif-rest-problem library:

  • SpringProblemTypeRegistry: ProblemTypeRegistry implementation that uses classpath scanning to detect @ProblemType annotations. By default, only package io.github.belgif.rest.problem is scanned for @ProblemType annotations. Additional packages to scan can be configured in your application.properties:

io.github.belgif.rest.problem.scan-additional-problem-packages=com.acme.custom
  • SpringProblemModule: a Jackson Module that registers the SpringProblemTypeRegistry.

  • ProblemExceptionHandler: an exception handler for RestControllers that handles the response serialization for Problem exceptions, and converts all other uncaught exceptions to an InternalServerErrorProblem.

  • BeanValidationExceptionsHandler: an exception handler for RestControllers that converts bean validation related exceptions to HTTP 400 BadRequestProblem.

  • InvalidRequestExceptionHandler: an exception handler for the Atlassian swagger-request-validator that converts InvalidRequestException to the correct Problem type.

  • RoutingExceptionsHandler: an exception handler for RestControllers that converts routing related validation exceptions to HTTP 400 BadRequestProblem.

In general, these components make it possible to use standard java exception handling (throw and try-catch) for dealing with problems in Spring Boot REST APIs.

7.3.1. belgif-rest-problem-spring-boot-2

Rather than depending on belgif-rest-problem-spring directly, Spring Boot 2.x users are recommended to depend on belgif-rest-problem-spring-boot-2, which adds some Spring Boot 2.x specific integrations:

  • ProblemWebClientCustomizer: a WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions. This handles integration with the Reactive WebClient.

  • ProblemResponseErrorHandler: a RestTemplate error handler that converts problem responses to Problem exceptions.

  • ProblemRestTemplateCustomizer: a RestTemplateCustomizer that registers the ProblemResponseErrorHandler.

  • AnnotationParameterNameDiscoverer: a bean validation ParameterNameDiscoverer that retrieves parameter names from Spring MVC annotations

  • ProblemValidatorConfiguration: registers a LocalValidatorFactoryBean with the AnnotationParameterNameDiscoverer

7.3.2. belgif-rest-problem-spring-boot-3

Rather than depending on belgif-rest-problem-spring directly, Spring Boot 3.x users are recommended to depend on belgif-rest-problem-spring-boot-3, which adds some Spring Boot 3.x specific integrations:

  • ProblemWebClientCustomizer: a WebClientCustomizer that registers a filter that converts problem responses to Problem exceptions. This handles integration with the Reactive WebClient.

  • ProblemResponseErrorHandler: a RestTemplate and RestClient error handler that converts problem responses to Problem exceptions.

  • ProblemRestTemplateCustomizer: a RestTemplateCustomizer that registers the ProblemResponseErrorHandler.

  • NoResourceFoundExceptionHandler: an exception handler for RestControllers that converts NoResourceFoundException to HTTP 404 ResourceNotFoundProblem.

  • ProblemRestClientCustomizer: a RestClientCustomizer that registers the ProblemResponseErrorHandler.

  • AnnotationParameterNameProvider: a bean validation ParameterNameProvider that retrieves parameter names from Spring MVC annotations

  • ProblemValidationConfigurationCustomizer: a ValidationConfigurationCustomizer that registers the AnnotationParameterNameProvider