`RestControllerAdvice`在Spring Boot 2.3中未被调用。

huangapple go评论96阅读模式
英文:

RestControllerAdvice not called with Spring Boot 2.3

问题

我想要将我的应用程序从Spring Boot 2.2.8更新到2.3.1。
在更新后运行应用程序时,我的globalExceptionHandler将不再正常工作。
我的情况是在请求中存在无效的JSON主体时处理错误。

应用程序

    // 省略部分代码...

控制器

    // 省略部分代码...

异常处理器

    // 省略部分代码...

自更新后,我没有更改任何代码。响应代码仍然是之前的400 Bad Request,但响应主体为空,并且我的处理程序不会被调用。

日志:

> 13:13:53.987 [http-nio-8080-exec-3] TRACE org.hibernate.internal.SessionImpl - 已打开会话 [6570b352-8067-49d2-bc46-c503917f4c8d],时间戳为:1595502833972
13:13:53.991 [http-nio-8080-exec-3] TRACE o.s.t.s.TransactionSynchronizationManager - 将值 [org.springframework.orm.jpa.EntityManagerHolder@72dd1712] 绑定到键 [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@38c55a8a],线程为 [http-nio-8080-exec-3]
13:13:54.011 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.ServletInvocableHandlerMethod - 无法解析参数 [0]:public com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandReturnDto com.schaerer.coffeelink.remote.boundary.v1.BidiCommandResource.applyBidiCommand(com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto) 中的参数 [0]:JSON解析错误:意外的字符('\'(代码92)):期望双引号以开始字段名称;嵌套异常为 com.fasterxml.jackson.databind.JsonMappingException:意外的字符('\'(代码92)):期望双引号以开始字段名称
 at [Source: (PushbackInputStream); line: 8, column: 54](通过引用链:com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"])
13:13:54.012 [http-nio-8080-exec-3] TRACE o.s.b.f.s.DefaultListableBeanFactory - 返回单例bean 'globalExceptionHandler' 的缓存实例
13:13:54.012 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - 使用 @ExceptionHandler com.schaerer.coffeelink.remote.boundary.v1.GlobalExceptionHandler#handleException(Exception, WebRequest)
13:13:54.013 [http-nio-8080-exec-3] TRACE o.s.w.s.m.m.a.ServletInvocableHandlerMethod - 参数:[org.springframework.http.converter.HttpMessageNotReadableException:JSON解析错误:意外的字符('\'(代码92)):期望双引号以开始字段名称;嵌套异常为 com.fasterxml.jackson.databind.JsonMappingException:意外的字符('\'(代码92))):期望双引号以开始字段名称
 at [Source: (PushbackInputStream); line: 8, column: 54](通过引用链:com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"]),ServletWebRequest:uri=/v1/remote/;client=0:0:0:0:0:0:0:1]
13:13:54.015 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.HttpEntityMethodProcessor - 不匹配 [*/*],支持的:[]
13:13:54.016 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - 已解析 [org.springframework.http.converter.HttpMessageNotReadableException:JSON解析错误:意外的字符('\'(代码92)):期望双引号以开始字段名称;嵌套异常为 com.fasterxml.jackson.databind.JsonMappingException:意外的字符('\'(代码92))):期望双引号以开始字段名称
 at [Source: (PushbackInputStream); line: 8, column: 54](通过引用链:com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"])]
13:13:54.016 [http-nio-8080-exec-3] TRACE o.s.web.servlet.DispatcherServlet - 无视图渲染,返回空的 ModelAndView。

有什么想法吗?
英文:

I want to update my application from Spring Boot 2.2.8 to 2.3.1
When I run the application after the update, my globalExceptionHandler won't work anymore correctly.
My case was to handle the error, when a invalid JSON-Body is in the request.

Application

package com.schaerer.coffeelink.remote;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.kafka.annotation.EnableKafka;

@Slf4j
@SpringBootApplication
@EnableKafka
public class Application {

  public static void main(final String[] args) { //NOSONAR
    SpringApplication.run(Application.class, args);
    log.info("Started application. Swagger available at http://localhost:8080/swagger-ui.html");
  }
}

Controller

package com.schaerer.coffeelink.remote.boundary.v1;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.schaerer.coffeelink.remote.boundary.v1.dto.*;
import com.schaerer.coffeelink.remote.controller.v1.ActionController;
import com.schaerer.coffeelink.remote.controller.v1.BidiCommandController;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

@Slf4j
@RestController
@Validated
@RequestMapping(value = "v1/remote", produces = MediaType.APPLICATION_JSON_VALUE)
@Tag(name = "remote-bidi-command")
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class BidiCommandResource {

  private final BidiCommandController bidiCommandController;
  private final ActionController actionController;
  private final ObjectMapper mapper;

  @ExceptionHandler({IllegalArgumentException.class})
  public ResponseEntity<Object> handleException(final IllegalArgumentException illegalArgumentException) {
    return new ResponseEntity<>(illegalArgumentException.getMessage(), HttpStatus.BAD_REQUEST);
  }

  @PostMapping
  @Operation(summary = "apply bidi command 2.0")
  public BidiCommandReturnDto applyBidiCommand(@Parameter(name = "applyBidiCommand")
                                                         @Validated({ActionDto.CreateValidation.class, BidiCommandDto.CreateValidation.class})
                                           @RequestBody final BidiCommandDto bidiCommandDto) {
        return bidiCommandController.applyBidiCommand(bidiCommandDto);
  }
}

ExceptionHandler

package com.schaerer.coffeelink.remote.boundary.v1;

import com.fasterxml.jackson.databind.JsonMappingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

  @ExceptionHandler(value = {JsonMappingException.class})
  public ResponseEntity<Object> handleJacksonError(final JsonMappingException ex, final WebRequest request) {
    log.error("Cannot parse request. {}", request.getDescription(true), ex);
    return handleExceptionInternal(ex, ex.getMessage(), new HttpHeaders(), HttpStatus.BAD_REQUEST, null);
  }
}

I haven't change any code since the update. The response code is as before 400 Bad Request but the response body is empty and my handler isn't called.

Logs:

> 13:13:53.987 [http-nio-8080-exec-3] TRACE org.hibernate.internal.SessionImpl - Opened Session [6570b352-8067-49d2-bc46-c503917f4c8d] at timestamp: 1595502833972
13:13:53.991 [http-nio-8080-exec-3] TRACE o.s.t.s.TransactionSynchronizationManager - Bound value [org.springframework.orm.jpa.EntityManagerHolder@72dd1712] for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@38c55a8a] to thread [http-nio-8080-exec-3]
13:13:54.011 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.ServletInvocableHandlerMethod - Could not resolve parameter [0] in public com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandReturnDto com.schaerer.coffeelink.remote.boundary.v1.BidiCommandResource.applyBidiCommand(com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto): JSON parse error: Unexpected character ('' (code 92)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('' (code 92)): was expecting double-quote to start field name
at [Source: (PushbackInputStream); line: 8, column: 54] (through reference chain: com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"])
13:13:54.012 [http-nio-8080-exec-3] TRACE o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'globalExceptionHandler'
13:13:54.012 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Using @ExceptionHandler com.schaerer.coffeelink.remote.boundary.v1.GlobalExceptionHandler#handleException(Exception, WebRequest)
13:13:54.013 [http-nio-8080-exec-3] TRACE o.s.w.s.m.m.a.ServletInvocableHandlerMethod - Arguments: [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('' (code 92)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('' (code 92)): was expecting double-quote to start field name
at [Source: (PushbackInputStream); line: 8, column: 54] (through reference chain: com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"]), ServletWebRequest: uri=/v1/remote/;client=0:0:0:0:0:0:0:1]
13:13:54.015 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.HttpEntityMethodProcessor - No match for [/], supported: []
13:13:54.016 [http-nio-8080-exec-3] DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unexpected character ('' (code 92)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('' (code 92)): was expecting double-quote to start field name
at [Source: (PushbackInputStream); line: 8, column: 54] (through reference chain: com.schaerer.coffeelink.remote.boundary.v1.dto.BidiCommandDto["parameters"])]
13:13:54.016 [http-nio-8080-exec-3] TRACE o.s.web.servlet.DispatcherServlet - No view rendering, null ModelAndView returned.

Any ideas?

答案1

得分: 2

我发现了一个解决方案,当我移除了ResponseEntityExceptionHandler扩展后。以下是我的解决方案:

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(value = {HttpMessageNotReadableException.class})
  public ResponseEntity<Object> handleJacksonError(final JsonMappingException ex, final WebRequest request) {
    log.error("无法解析请求。 {}", request.getDescription(true), ex);
    return new ResponseEntity<>(ex.getMessage(), HttpStatus.BAD_REQUEST);
  }
}
英文:

I've found a solution when I remove the ResponseEntityExceptionHandler extension.
Here my solution:

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

  @ExceptionHandler(value = {HttpMessageNotReadableException.class})
  public ResponseEntity&lt;Object&gt; handleJacksonError(final JsonMappingException ex, final WebRequest request) {
    log.error(&quot;Cannot parse request. {}&quot;, request.getDescription(true), ex);
    return new ResponseEntity&lt;&gt;(ex.getMessage(), HttpStatus.BAD_REQUEST);
  }
}

huangapple
  • 本文由 发表于 2020年7月23日 18:33:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/63052223.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定