最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

spring boot - how to implement same exception handling logic as dispatcher in a @ControllerAdvice? - Stack Overflow

programmeradmin3浏览0评论

There is some magic code in the dispatcher which turns exceptions thrown and not caught in a spring boot 3.4 rest api (using @RestController and @GetMapping("/xx") into nice JSON responses & doing the logging:

  1. formats the error into a json object
  2. assigns a http status code depending on the type of the exception
  3. logs the exception. (MDC context not available here as is set (and removed) in a filter )

We need to customize the logging, to include correlation token which is set in the request MDC contact via a filter, which is not available to the context. We cant extend or change the way dispatcher does it, we have to start from scratch and try to replicate it.

We could do something like this:

@ControllerAdvice
public class ControllerConfig {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleGeneralException(Exception ex) {
        
        String jsonBody = turnTheExceptionIntoJson(ex); 
        HttpStatus httpStatus = figureOutTheStatus(3)  
        log.error("Some controller through an error", ex);  // This will use our custom logback which includes correlation token in the MDC context for this request

        return new ResponseEntity<>(jsonBody, httpStatus);
    }
}

However, we need to replicate what the dispatcher currently outputs (see below), and how it maps exceptions to status codes, so we can maintain compatibility with existing clients.

Any ideas how to do this (e.g. where the source code for the dispatcher function which does this is so we can copy it). Especially how it gets the controller path, and how it maps statuses.

It will also have to handle Custom defined exceptions with @ResponseStatus(HttpStatus.xxx)

This is what the dispatcher does automatically:

{
    "timestamp": "2025-02-14T13:30:59.422+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "trace": "net.snowflake.client.jdbc.SnowflakeSQLException: JWT token is invalid. [59166e77-2ff6-4c90-80e5-7d40b3121297]\r\n\tat net.snowflake.client.core.SessionUtil.newSession(SessionUtil.java:577)\r\n\tat......"
    "message": "JWT token is invalid. [59166e77-2ff6-4c90-80e5-7d40b3121297]",
    "path": "/my/controller"
}

We tried using @ExceptionHandler:

ControllerAdvice
public class ControllerConfig {
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponseModel> handleGeneralException(Exception ex) {
        // Return a custom error message with HTTP 500 status

        HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;

        ErrorResponseModel response = new ErrorResponseModel();

        response.setTimetamp(new Date());
        response.setMessage(ex.toString() + ":" +ex.getMessage());
        response.setError(status.getReasonPhrase());
        response.setStatus(status.value());

        return new ResponseEntity<>(response, status);
    }
}

The crux is this returns 500 error for every exception, including resource not found problems where the dispatchers built in system would have returned 404. If someone knows where the source code is for the dispatchers handling of exceptions, we could perhaps reverse engineer it, including logic to figure out the required status, and how it knows the path.

发布评论

评论列表(0)

  1. 暂无评论