I wanted to use bean-validation for parameters of a @RestController
method.
Turns out that even with the inclusion of the starter-validation dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
one needs to manually define a MethodValidationPostProcessor
as shown below.
If spring-boot provided such a bean ootb then user's could just work
with the annotations like @Validated
and the JSR-303/349 stuff.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.validation.annotation.Validated;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.Size;
import java.util.Map;
import static java.lang.String.format;
import static java.util.Collections.singletonMap;
@SpringBootApplication
public class MvcWebApp {
public static void main(String[] args) {
SpringApplication.run(MvcWebApp.class, args);
}
@Bean //this could be provided via auto-configuration
MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
@RestController
@Validated
@RequestMapping("/api")
class HelloResource {
@RequestMapping("/greet/{name}")
public Map<String, String> greet(@PathVariable("name") @Size(min = 3, max = 10, message = "You messed up!") String name) {
return singletonMap("greeting", format("Hello %s", name));
}
}
Would also be nice to have a default @ExceptionHandler(value = {ConstraintViolationException.class})
definition e.g.:
@ExceptionHandler(value = {ConstraintViolationException.class})
@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public String handleValidationFailure(ConstraintViolationException ex) {
StringBuilder messages = new StringBuilder();
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
messages.append(violation.getMessage() + "\n");
}
return messages.toString();
}
+1
@michael-simons please use the github reaction feature for simple +1. Thank you.
The current condition is too fragile in practice since Hibernate validator requires EL on the classpath and barfs if that's not the case. If a user tries tot use validation and forget that part, that's fine but this change makes it happen automatically and unconditionally so we should be more defensive.
Most helpful comment
Would also be nice to have a default
@ExceptionHandler(value = {ConstraintViolationException.class})
definition e.g.: