getting ConstraintViolationException instead of MethodArgumentNotValidException when using @valid with @RequestBody in the controller

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

getting ConstraintViolationException instead of MethodArgumentNotValidException when using @valid with @RequestBody in the controller

问题

我正在继续学习Spring Boot的旅程,目前我在两种相似的异常之间陷入困境,无论我在控制器/服务级别与@RequestBody一起使用@valid或@validate,都应该获得MethodArgumentNotValidException,而在进行Post和Update API调用时我得到了ConstraintViolationException。一再调用全局异常处理程序ExceptionHAndler类的方法,显示ConstraintViolationException。

PostController.java

@RestController
@RequestMapping("/api/posts")
public class PostController {
    
    @Autowired
    private PostService postService;

    @PostMapping
    public ResponseEntity<PostDTO> createPost(@Valid @RequestBody PostDTO postDTO){
        return new ResponseEntity<>(postService.createPost(postDTO),HttpStatus.CREATED);
    }
    
    @PostMapping(path = "/multiple")
    public ResponseEntity<List<PostDTO>> createMultiplePosts(@Valid @RequestBody List<PostDTO> postDTO){
        return new ResponseEntity<>(postService.createMultiplePosts(postDTO),HttpStatus.CREATED);
    }
}

Entity Class: Posts.java

@Entity
@Table(name = "posts", uniqueConstraints = {@UniqueConstraint(columnNames = {"titles"})})
public class Posts {
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    @Column(name = "titles")
    @NotEmpty
    @Size(min = 2,message = "post title should contain atleast 2 character")
    private String title;
    @Column(name = "description")
    @NotEmpty
    @Size(min = 10,message = "post description should contain atleast 2 character")
    private String description;
    @Column(name = "content")
    @NotEmpty
    private String content;
}

GlobalException.java

@ControllerAdvice
public class GlobalException extends ResponseEntityExceptionHandler {
    
    private static final Logger logger = LoggerFactory.getLogger(GlobalException.class);
    
    @ExceptionHandler(ResouceNotFoundException.class)
    ResponseEntity<ErrorDetails> PostNotFoundExceptionHandler(ResouceNotFoundException exception, WebRequest webRequest){
        // ... (unchanged)
    }
    
    @ExceptionHandler(BlogApiException.class)
    ResponseEntity<ErrorDetails> CommentNotFoundExceptionHandler(BlogApiException exception, WebRequest webRequest){
        // ... (unchanged)
    }
    
    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request){
        // ... (unchanged)
    }
    
    @ExceptionHandler(Exception.class)
    ResponseEntity<ErrorDetails> GlobalExceptionHandler(Exception exception, WebRequest webRequest){
        // ... (unchanged)
    }
}

我尝试修改RequestBody JSON,在类级别和方法级别在@RequestBody注解之后尝试@validated注解,仍然得到相同的异常。请帮助我理解为什么我会得到这个异常,尝试与Spring Boot Starter Validation依赖项的版本进行调整,目前使用的是3.0.4版本的starter-validation依赖项,Java版本是17.0.7。

英文:

i am continuing my journey to learn Spring boot, right now i am stuck between two similar kind of exceptions, wherever i found i have got the answer that if @valid or @validate used at controller/service level along with @RequestBody we should get MethodArgumentNotValidException
whereas, i am getting ConstraintViolationException during post and update API calls. again and again the call is going in globalExceptionHandler method of ExceptionHAndler class, where it is showing constraintviolationexception.

PostController.java

@RestController
@RequestMapping(&quot;/api/posts&quot;)
public class PostController {
	
	@Autowired
	private PostService postService;

	//rest API endpoint to post http:localhost:8080/api/posts
	@PostMapping
	public ResponseEntity&lt;PostDTO&gt; createPost(@Valid @RequestBody PostDTO postDTO){
		return new ResponseEntity&lt;&gt;(postService.createPost(postDTO),HttpStatus.CREATED);
	}
	
	@PostMapping(path = &quot;/multiple&quot;)
	public ResponseEntity&lt;List&lt;PostDTO&gt;&gt; createMultiplePosts(@Valid @RequestBody List&lt;PostDTO&gt; postDTO){
		
		return new ResponseEntity&lt;&gt;(postService.createMultiplePosts(postDTO),HttpStatus.CREATED);
	}

Entity Class:

Posts.java

@Entity
@Table(name = &quot;posts&quot;, uniqueConstraints = {@UniqueConstraint(columnNames = {&quot;titles&quot;})})
public class Posts {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private Long id;
	@Column(name = &quot;titles&quot;)
	@NotEmpty
	@Size(min = 2,message = &quot;post title should contain atleast 2 character&quot;)
	private String title;
	@Column(name = &quot;description&quot;)
	@NotEmpty
	@Size(min = 10,message = &quot;post description should contain atleast 2 character&quot;)
	private String description;
	@Column(name = &quot;content&quot;)
	@NotEmpty
	private String content;

GlobalException.java

@ControllerAdvice
public class GlobalException extends ResponseEntityExceptionHandler {
	
	private static final Logger logger = LoggerFactory.getLogger(GlobalException.class);
	
	@ExceptionHandler(ResouceNotFoundException.class)
	ResponseEntity&lt;ErrorDetails&gt; PostNotFoundExceptionHandler(ResouceNotFoundException exception, WebRequest webRequest){
		
		ErrorDetails errorDetails =new ErrorDetails(new Date(),exception.getMessage(),webRequest.getDescription(false));
		return new ResponseEntity&lt;&gt;(errorDetails,HttpStatus.NOT_FOUND);
	}
	
	@ExceptionHandler(BlogApiException.class)
	ResponseEntity&lt;ErrorDetails&gt; CommentNotFoundExceptionHandler(BlogApiException exception, WebRequest webRequest){
		
		ErrorDetails errorDetails =new ErrorDetails(new Date(),exception.getMessage(),webRequest.getDescription(false));
		return new ResponseEntity&lt;&gt;(errorDetails,HttpStatus.NOT_FOUND);
	}
	
	
	@Override
//	@ExceptionHandler(MethodArgumentNotValidException.class)
	protected ResponseEntity&lt;Object&gt; handleMethodArgumentNotValid(
			MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatusCode status, WebRequest request){
		
		logger.info(&quot;inside handleMethodArgumentNotValid class&quot;);
		Map&lt;String, String&gt; errorsMap =new HashMap&lt;&gt;();
		ex.getBindingResult().getAllErrors().forEach((error)-&gt;{
		
			String fieldNameString = ((FieldError)error).getField();
			String messageString = error.getDefaultMessage();
			errorsMap.put(fieldNameString, messageString);
		});
		return new ResponseEntity&lt;&gt;(errorsMap,HttpStatus.BAD_REQUEST);
	}
	
	@ExceptionHandler(Exception.class)
	ResponseEntity&lt;ErrorDetails&gt; GlobalExceptionHandler(Exception exception, WebRequest webRequest){
		logger.info(&quot;inside GlobalExceptionHandler class&quot;);
		ErrorDetails errorDetails =new ErrorDetails(new Date(),exception.getMessage(),webRequest.getDescription(false));
		return new ResponseEntity&lt;&gt;(errorDetails,HttpStatus.BAD_REQUEST);
	}

}

i tried modifying RequestBody JSON, tried @validated annotation at class level, and at method level after @RequestBody annotation as well, still getting same exception.
please help me to understand why am I getting this exception, tried playing with versions of spring boot starter validation dependency.
currently using 3.0.4 version of starter-validation dependency
Java version is 17.0.7

答案1

得分: 0

为什么你认为应该获得 MethodArgumentNotValidException?当请求体违反了一些约束时,似乎期望 ConstraintViolationException 是完全合理的异常。我在这里看不到问题。只需将你的 ExceptionHandler 更改为捕获 ConstraintViolationException 并按照你的需求处理它。

英文:

Why do you think you should get MethodArgumentNotValidException? ConstraintViolationException seems to be totally reasonable exception to expect, when some constraints were violated by your request body. I don't see a problem here. Just change your ExceptionHandler to catch ConstraintViolationException and do whatever you want with it.

huangapple
  • 本文由 发表于 2023年5月7日 20:10:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193841.html
匿名

发表评论

匿名网友

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

确定