Site icon IT insights and commons things

Validation of @PathVariable in Spring MVC

Problem

One can’t use validation annotations on @PathVariable annotations with i.e. @Pattern annotation like this:

@RequestMapping(value = "/bank/{id}", method = RequestMethod.GET)
public ResponseEntity method_name(
    @Pattern(regexp = "\\d{9}", message = "Bank shoud be identified by exactly 9 digits")
    @PathVariable String id) {
    /// Some code
}

Solution

For validation to work we should make a few things

Declare method validation bean

In one of your @Configuration classes you should declare @Bean of type MethodValidationPostProcessor

@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
         return new MethodValidationPostProcessor();
}

MethodValidationPostProcessor:

A convenient BeanPostProcessor implementation that delegates to a JSR-303 provider for performing method-level validation on annotated methods.

Target classes with such annotated methods need to be annotated with Spring’s Validated annotation at the type level, for their methods to be searched for inline constraint annotations. Validation groups can be specified through @Validated as well. By default, JSR-303 will validate against its default group only.

Create exception handler

Declare @ControllerAdvice-annotated class with @ExceptionHandler-annotated method inside

@ControllerAdvice
class GlobalExceptionHandler {
    @ExceptionHandler(value = { ConstraintViolationException.class })
    @ResponseStatus(value = HttpStatus.BAD_REQUEST)
    public String handle(ConstraintViolationException e) {
         Set<ConstraintViolation<?>> violations = e.getConstraintViolations();
         StringBuilder strBuilder = new StringBuilder();
         for (ConstraintViolation<?> violation : violations ) {
              strBuilder.append(violation.getMessage() + "\n");
         }
         return strBuilder.toString();
    }
}

Several important lines:

Add validation annotation on controller

@Validated
@RestController
class BankController {
    @RequestMapping(value = "/bank/{id}", method = RequestMethod.GET)
    public ResponseEntity<BankInfo> bankInfo(
       @Pattern(regexp = "\\d{9}", message = "Bank shoud be identified by exactly 9 digits")
       @PathVariable String id) {
     /// Some code
    }
}

Add @Validated annotation to your controller class for PostProcessor to be able to handle requests to your method.

That’s all folks

Exit mobile version