Dachstein
Dachstein

Reputation: 4282

Spring Webflux ErrorHandling - @RestControllerAdvice with @ExceptionHandler or DefaultErrorAttributes?

In Spring Webflux what is the prefered way of Exception Handling?

@RestControllerAdvice comes from Spring MVC whereas DefaultErrorAttributes comes from Spring Webflux.

However, in Spring Webflux someone could use @RestControllerAdvice. What would be the advantages/disadvantages?

@RestControllerAdvice

@RestControllerAdvice
public class ControllerAdvice
{
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Mono<Map<String, Object>> exceptions(Throwable e)
    {
        return Mono.just(Map.of("message", "bad"));
    }
}

Extend DefaultErrorAttributes

@Component
public class ErrorAttributes extends DefaultErrorAttributes
{
    @Override
    public Map<String, Object> getErrorAttributes(ServerRequest request, boolean includeStackTrace)
    {
        var ex = getError(request);

        var attributes = new LinkedHashMap<String, Object>();
        attributes.put("status", HttpStatus.BAD_REQUEST.value());
        attributes.put("message", "bad");

        return attributes;
    }
}

I want to stay in the reactive world, so I tend more towards DefaultErrorAttributes (which plays well with DefaultErrorWebExceptionHandler in Webflux). However, in @RestControllerAdvice I could also use Mono.just(...).

Upvotes: 7

Views: 9324

Answers (2)

Dmitry Kokora
Dmitry Kokora

Reputation: 827

In Spring Webflux in case functional routes declaration, you can also implement your own ExceptionHandler instead of DefaultErrorWebExceptionHandler:

    class SystemErrorWebExceptionHandler extends AbstractErrorWebExceptionHandler {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable throwable) {
        return super.handle(exchange, throwable)
                    // debug, process
                    .contextWrite(...);
    }

    @Override
    protected RouterFunction<ServerResponse> getRoutingFunction(ErrorAttributes errorAttributes) {
        // for all routs
        return route(all(), this::renderErrorResponse);
    }

    private Mono<ServerResponse> renderErrorResponse(ServerRequest request) {
        Map<String, Object> error = getErrorAttributes(request, ErrorAttributeOptions.of());
        Throwable t = this.getError(request);
        // map exception on response
        return ServerResponse.status(status).body(...);
    }
}

Then use your implementation of AbstractErrorWebExceptionHandler in the spring configuration with @AutoConfigureBefore(WebFluxAutoConfiguration.class)

Upvotes: 0

Numichi
Numichi

Reputation: 1092

It is same. Like WebMvc.

@RestControllerAdvice
public class ControllerAdvice {
    @ExceptionHandler(AnyException.class)
    public Mono<EntityResponse<YourModel>> example(AnyException exception) {
        return EntityResponse.fromObject(new YourModel()).status(HttpStatus.NOT_FOUND).build();
    }
}

Upvotes: 2

Related Questions