Problem Spring Web

repository·main·Indexed 21 days ago

https://github.com/zalando/problem-spring-web

A library for Spring MVC and Spring WebFlux applications to produce RFC 9457 compliant application/problem+json error responses. It utilizes a composable 'advice trait' pattern to map exceptions to problem details via @ControllerAdvice, supporting integrations with Spring Security, Failsafe, and Swagger/OpenAPI Request Validator.

Tokens
4.9K
Snippets
16
Records
18
Agent score
75%

What's inside problem-spring-web

  1. What are advice traits in Problem Spring Web

    main
    An advice trait is a small, reusable @ExceptionHandler implemented as a default method within a single method interface. This design allows you to favor composition over inheritance: you can combine multiple advice traits freely within a single @ControllerAdvice without needing a common base class. This approach makes it easy to produce application/problem+json (RFC 9457) responses in Spring MVC or WebFlux applications.
  2. Use Advice Traits to customize error handling

    main

    The library uses 'Advice Traits' to map specific exceptions to Problem details. You can implement the ProblemHandling interface in a @ControllerAdvice class to get a default set of handlers, or implement specific traits individually to pick and choose which errors you want to handle.

    A typical implementation uses ProblemHandling to cover all standard web errors:

    @ControllerAdvice
    class ExceptionHandling implements ProblemHandling {
    
    }
  3. How advice traits work in Spring WebFlux

    main

    The library uses 'Advice Traits' to handle specific error scenarios. You can implement these traits individually or group them by implementing interfaces like ProblemHandling.

    Important WebFlux Note: In WebFlux, if a request handler is never called (e.g., a 404 or 405 error), @ControllerAdvice is not triggered. To handle these cases, you must register a ProblemExceptionHandler with high precedence using @Order(-2) to override default Spring Boot error handlers.

    @Bean
    @Order(-2) // Must precede WebFluxResponseStatusExceptionHandler and Spring Boot's ErrorWebExceptionHandler
    public WebExceptionHandler problemExceptionHandler(ObjectMapper mapper, ProblemHandling problemHandling) {
        return new ProblemExceptionHandler(mapper, problemHandling);
    }
  4. Integrate with Failsafe (Circuit Breaker)

    main

    To support CircuitBreakerOpenException from Failsafe, implement the CircuitBreakerOpenAdviceTrait. This will translate open circuit breakers into a 503 Service Unavailable problem response.

    @ControllerAdvice
    class ExceptionHandling implements ProblemHandling, CircuitBreakerOpenAdviceTrait {
    
    }
  5. Install Problem: Spring Web MVC

    main

    Depending on your project type, choose one of the following installation methods:

    Add the starter module to your dependencies. This provides a default working configuration and automatically handles Spring Security problems if Spring Security is detected in the classpath.

    Standard WebMVC

    If you are not using Spring Boot, add both the core library and the Jackson datatype module to your project.

    <!-- Spring Boot -->
    <dependency>
        <groupId>org.zalando</groupId>
        <artifactId>problem-spring-web-starter</artifactId>
        <version>${problem-spring-web.version}</version>
    </dependency>
    
    <!-- WebMVC -->
    <dependency>
        <groupId>org.zalando</groupId>
        <artifactId>problem-spring-web</artifactId>
        <version>${problem-spring-web.version}</version>
    </dependency>
    <dependency>
        <groupId>org.zalando</groupId>
        <artifactId>jackson-datatype-problem</artifactId>
        <version>0.27.1</version>
    </dependency>
  6. Install problem-spring-webflux

    main

    Add the following dependencies to your Maven project to use Problem for Spring WebFlux. Ensure you include jackson-datatype-problem to support the problem JSON format.

    <dependency>
        <groupId>org.zalando</groupId>
        <artifactId>problem-spring-webflux</artifactId>
        <version>${problem-spring-webflux.version}</version>
    </dependency>
    <dependency>
        <groupId>org.zalando</groupId>
        <artifactId>jackson-datatype-problem</artifactId>
        <version>0.27.1</version>
    </dependency>
  7. Enable causal chains in Problem responses

    main

    Causal chains (showing the nested cause of an error) are disabled by default. To enable them, implement the isCausalChainsEnabled() method in your @ControllerAdvice class that implements ProblemHandling and return true.

    @ControllerAdvice
    class ExceptionHandling implements ProblemHandling {
    
        @Override
        public boolean isCausalChainsEnabled() {
            return true;
        }
    
    }
  8. Enable stack traces in Problem responses

    main

    To include stack traces in your application/problem+json responses, configure your ProblemModule with the .withStackTraces() method when registering it with your Jackson ObjectMapper.

    ObjectMapper mapper = new ObjectMapper()
        .registerModule(new ProblemModule().withStackTraces());
  9. Integrate with Spring Security

    main

    To handle security-related exceptions (like authentication or access denied) using the Problem format, you must implement SecurityAdviceTrait in a @ControllerAdvice and configure SecurityProblemSupport in your security filter chain.

    @ControllerAdvice
    class ExceptionHandling implements ProblemHandling, SecurityAdviceTrait {
    }
    
    @Configuration
    @Import(SecurityProblemSupport.class)
    public class SecurityConfiguration {
    
        @Autowired
        private SecurityProblemSupport problemSupport;
    
        @Bean
        public SecurityWebFilterChain securityWebFilterChain(final ServerHttpSecurity http) {
            return http.exceptionHandling()
                    .authenticationEntryPoint(problemSupport)
                    .accessDeniedHandler(problemSupport)
                    .and().build();
        }
    }
  10. Configure ObjectMapper modules

    main

    To correctly serialize problem details, register the ProblemModule and ConstraintViolationProblemModule as beans in your Spring configuration.

    @Bean
    public ProblemModule problemModule() {
        return new ProblemModule();
    }
    
    @Bean
    public ConstraintViolationProblemModule constraintViolationProblemModule() {
        return new ConstraintViolationProblemModule();
    }
  11. Configure NoHandlerFoundAdviceTrait

    main

    To enable NoHandlerFoundAdviceTrait (which produces 404 Not Found), you must configure Spring MVC to throw exceptions when no handler is found and disable resource mapping additions.

    spring:
      resources:
        add-mappings: false
      mvc:
        throw-exception-if-no-handler-found: true

    If using Spring Boot, you must also exclude ErrorMvcAutoConfiguration:

    @EnableAutoConfiguration(exclude = ErrorMvcAutoConfiguration.class)
  12. Configure ObjectMapper for WebMVC

    main

    If you are not using the problem-spring-web-starter module, you must manually register the required Jackson modules with your ObjectMapper to ensure problem details are serialized correctly.

    @Bean
    public ProblemModule problemModule() {
        return new ProblemModule();
    }
    
    @Bean
    public ConstraintViolationProblemModule constraintViolationProblemModule() {
        return new ConstraintViolationProblemModule();
    }