I am using org.springframework.boot:spring-boot-starter-validation:2.7.0
(which in turn uses hibernate validator) to validate user input to rest controller.
I am using Spring Boot Web Starter (2.7.0) based project with @RestController
annotation
My @GetMapping
method is something like below -
@GetMapping(path = "/abcservice")
public Object abcService(
@RequestParam(value = "accountId", required = true) String accountId,
@Valid @RequestParam(value = "offset", required = false, defaultValue = "0") int offset,
@Valid @RequestParam(value = "limit", required = false, defaultValue = "10000") int limit
) throws Exception {
My problem is - I want the user to know about any input validation errors so they can correct and retry. But the framework is just giving 400
status code with below message.
{
"timestamp": "2022-08-03T16:10:14.554+00:00",
"status": 400,
"error": "Bad Request",
"path": "/somepath/abcservice"
}
On the server side the request is logged in warn
.
2022-08-03 21:40:14.535 WARN 98866 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.method.annotation.MethodArgumentTypeMismatchException: Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "0s"]
I want this above error message --> Failed to convert value of type 'java.lang.String' to required type 'int'; nested exception is java.lang.NumberFormatException: For input string: "0s"
also to be passed on to user. Is there a easy configuration based way to achieve.
I think i can add a ControllerAdvice
to handle this exception and include this message in the response from handler method. But this will be a couple of lines of code. Is there an even simpler way than the ControllerAdvice
approach.
Similarly if the client don't pass the mandatory accountId
param, the client is just getting the same 400 response as above. No details or hints to the client about what wrong they are doing or how they can fix it.. but on the server side i can see below warn
log.
2022-08-03 21:59:20.195 WARN 235 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required request parameter 'accountId' for method parameter type String is not present]
I want the client to know about this error/exception. Nothing secret here to hide (atleast in my case).
Edit - found this config -
server.error.include-message=always
Now the issue is, bad requests are sent with 500 status code, I want them to sent as 400. Then this Q is solved.
Validations made by @Valid
return with 500
Status Code. Is there anyway to tell the server to return 400
response when validations fail (without using ControllerAdvice
).
If you wish to test-- you can try -->
Annotate controller with @Validated.
And execute below method and you will see 500 error but would want this to be 400.
@GetMapping("/test")
public void test(@Valid @RequestParam(value = "studentId", required = false)
@Min(value=0, message="Can not be less than 0") @Max(value=200, message="Can not be above 200") Long studentId ) {
System.out.println("hit: ");
}
And hit - http://localhost:9099/test?studentId=400
The spring in-built solution without global exception handler and with minimal config is by adding the below property in the application.properties.
The above property can have three values:
Example Github Project Reference
Request:
Response: (with HTTP response code = 400)