Although, this question has been answered I'm interested why @Validated
is needed for a working cascaded validation of Map<String, @Valid Employee>
.
Update 2: For some deeper understanding I've found those posts (One,Two and Three), which explains, that @Validated
is neeeded to activate method level validation. With the help of this, collections can be validated, due they are no JavaBeans which are validated instead (JSR 303).
Solution: I've updated my code snippets and my repository with working code examples. All I have to do is to annotate my controller with @Validated
and add some getters in Employee
. MethodValidationPostProcessor
is not necessary at all.
Update: I've updated my question and forked Spring Boot Rest example to add a minimal Rest API to demonstrate:
Github Repo. The example values are inside README.md!
I've got an Spring Boot 2 API to store some employees. I can pass either one Employee
or either a Map<String, Employee>
.
@Validated //this is the solution to activate map validation
@RestController
class EmployeeController {
@PostMapping("/employees")
List<Employee> newEmployee(@RequestBody @Valid Employee newEmployee) {
...
}
@PostMapping("/employees/bulk")
List<Employee> newEmployee(@RequestBody Map<String, @Valid Employee>
newEmployees) {
...
}
}
Employee exists of some inner static classes which also needs to be validated:
public class Employee {
@NotBlank
public final String name;
@Valid
public final EmployeeRole role;
@JsonCreator
public Employee(@JsonProperty("name") String name,
@JsonProperty("role") EmployeeRole role) {
this.name = name;
this.role = role;
}
// getters
public static class EmployeeRole {
@NotBlank
public String rolename;
@Min(0)
public int rating;
@JsonCreator
public EmployeeRole(@JsonProperty("rolename") String rolename,
@JsonProperty("rating") int rating) {
this.rolename = rolename;
this.rating = rating;
}
// getters
}
}
For now, validation for single requests are working but not for my bulk requests. As far as i know this should be possible with Bean validation 2.0.
Do you know what I've did wrong? Do i need to write a custom validator?
To make it working you have to do following:
Add
MethodValidationPostProcessor
bean to configuration
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
Add
@Validated
to yourEmployeeController
@Validated
@RestController
public class EmployeeController {}'
Add
@Valid
toMap
or toEmployee
public List<Employee> newEmployee(@RequestBody @Valid Map<String, Employee> newEmployees) {}
public List<Employee> newEmployee(@RequestBody Map<String, @Valid Employee> newEmployees) {}
That's all. This is entire EmployeeController
:
@Validated
@RestController
public class EmployeeController {
@PostMapping("/employees")
public List<Employee> newEmployee(@RequestBody @Valid Employee newEmployee) {
return Collections.singletonList(newEmployee);
}
@PostMapping("/employees/bulk")
public List<Employee> newEmployee(@RequestBody @Valid Map<String, Employee> newEmployees) {
return new ArrayList<>(newEmployees.values());
}
}
And SpringBoot configuration file
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public MethodValidationPostProcessor methodValidationPostProcessor() {
return new MethodValidationPostProcessor();
}
}
Hope it help you.