简体   繁体   中英

Custom generic request validator in Spring boot

I am new to Spring boot and I have a question about request fields validation. I figured out how to use annotations on fields level to specify the custom error message:

public class EmployeeRequest {

    @NotEmpty( message = "field name cannot be empty" )
    @NonNull
    private String name;

    @NotEmpty( message = "field address cannot be empty" )
    @NonNull
    private String address;
}

But for using these annotations I have to specify error message for every field in every request class. Also for some reason I am getting not very neat response:

"org.springframework.validation.BeanPropertyBindingResult: 1 errors\\nField error in object 'employeeRequest' on field 'name': rejected value [null]; codes [NotEmpty.employeeRequest.name,NotEmpty.name,NotEmpty.java.lang.String,NotEmpty]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [employeeRequest.name,name]; arguments []; default message [name]]; default message [provide a name]"

Is there more elegant and generic way to do such field validations for every request assuming all fields must be NotEmpty and NonNull ?

public class EmployeeController {

    @PostMapping("/test")
    @ResponseBody
    public EmployeeResponse testMethod(@RequestBody EmployeeRequest request) {
        genericFieldsValidatorForAllRequests(request);
        doSomeStuffIfRequestIsValid(request);
}

Could anybody provide some ideas how that request validator could be implemented?

It seems like you asked two questions, hopefully I can try to answer both.

Why does the JSON response look "not very neat"?

By default Spring Boot catches any uncaught exception thrown in a web request handler (such as @RequestMapping , @GetMapping , etc...) and converts it into a JSON response of this structure below:

{
 "timestamp": 1500597044204,
 "status": 400,
 "error": "Bad Request",
 "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
 "message": "JSON parse error: Unrecognized token .....",
 "path": "/birds"
}

One way to get your error response JSON to look a different way is to make an exception handler. Basically you catch the errors you want before they go to Spring Boot's default error handler. To do that you make one of these somewhere in the same package or a higher lever package than your controller:

@ControllerAdvice
public class GlobalErrorHandler {

    @ExceptionHandler(ExceptionICareAbout.class)
    public MyErrorResponseObject handleExceptionICareAbout(ExceptionICareAbout e) {
        return new MyErrorResponseObject(<ADD CODE HERE>)
    }

}

In your case, you could make an exception handler for MethodArgumentNotValidException and convert it into the error response of your liking. (I believe that is the exception that is thrown when a JSR303 annotation validation fails, but please double check me)

You can also wrap your error response object in a ResponseEntity<> object that Spring provides to customize other things in the response, or just annotate the exception handler method with @ResponseStatus to customize just the http status code that is returned.

Also, if you want to catch every single exception and prevent them from going to Spring Boot's default exception handler, just make a exception handler for the Exception class itself, such as @ExceptionHandler(Exception.class) .

Is there a more "elegant and generic" way to do field validation?

Using the JSR303 annotations like you are ( @NotNull , @Size , etc...) per field on every object you care about in combination with the @Valid annotation is the best way I know. I would spend time thinking about ways to reuse code and error messages, but that's all I can think of off the top of my head. Maybe we can get some good answers in the comments.

Spring does offer these Validators you could do instead of JSR303 annotation, but I don't have much experience with them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM