Beyond Controller Validation: 90% Miss Spring’s Advanced Validation Techniques
The article explains how standard Spring Boot controller‑level validation leaves service methods unchecked, and demonstrates using @Validated with MethodValidationPostProcessor, custom exception handling, and a MethodValidationExcludeFilter to apply, convert, and selectively disable validation across the application.
In Spring Boot projects, parameter validation is essential for ensuring request data integrity, but the default approach only validates at the @Controller layer, leaving service‑level methods unprotected and potentially causing business logic errors.
1. Introduction
Typical controller validation uses @Validated and BindingResult, as shown:
@PostMapping("/create")
public Object create(@Validated @RequestBody User user, BindingResult result) {
if (result.hasErrors()) {
return result.getFieldErrors()
.stream()
.map(error -> error.getField() + "," + error.getDefaultMessage())
.toList();
}
return user;
}This approach cannot validate parameters in @Service or other non‑controller beans.
2. Practical Cases
2.1 Validation in Non‑Controller Methods
After adding the spring-boot-starter-validation dependency, Spring automatically registers a MethodValidationPostProcessor that validates beans annotated with @Validated. Applying it to a service class is as simple as:
@Service
@Validated
public class UserService {
public void save(@Valid User user) {
// ...
}
public void query(@NotEmpty(message = "Keyword must be provided") String keyword) {
// ...
}
}When these methods are invoked, Spring validates the parameters and throws ConstraintViolationException on failure.
private final UserService userService;
public ValidationController(UserService userService) { this.userService = userService; }
@PostMapping("/create")
public Object create(@RequestBody User user) {
this.userService.save(user);
return user;
}
@ExceptionHandler(ConstraintViolationException.class)
public Object violationException(ConstraintViolationException e) {
return e.getConstraintViolations().stream()
.map(cv -> cv.getPropertyPath() + "," + cv.getMessage())
.toList();
}The console shows the ConstraintViolationException details, and the response contains the formatted error messages.
2.2 Exception Conversion
To unify exception handling, Spring can adapt ConstraintViolationException to MethodValidationException by enabling the following property:
spring:
validation:
method:
adapt-constraint-violations: trueThen define a handler for MethodValidationException:
@ExceptionHandler(MethodValidationException.class)
public Object validationException(MethodValidationException e) {
return e.getAllErrors().stream()
.map(err -> err.getDefaultMessage())
.toList();
}This returns a simple list of validation messages.
2.3 Custom Method‑Validation Exclude Filter
If third‑party libraries or framework components are annotated with @Validated but should be excluded from validation, implement MethodValidationExcludeFilter:
@Component
public class PackMethodValidationExcludeFilter implements MethodValidationExcludeFilter {
@Value("${pack.validation.excludes:}")
private Set<String> excludes;
@Override
public boolean isExcluded(Class<?> type) {
return excludes.contains(type.getPackageName());
}
}Configure the packages to skip:
pack:
validation:
excludes: com.pack.validationWhen a bean belongs to an excluded package, its methods are not validated, as demonstrated by the same controller call producing no validation errors for the filtered class.
Alternatively, the interface provides static factory methods to create filters based on annotation presence:
public interface MethodValidationExcludeFilter {
static MethodValidationExcludeFilter byAnnotation(Class<? extends Annotation> annotationType) {
return byAnnotation(annotationType, SearchStrategy.INHERITED_ANNOTATIONS);
}
static MethodValidationExcludeFilter byAnnotation(Class<? extends Annotation> annotationType, SearchStrategy searchStrategy) {
return (type) -> MergedAnnotations.from(type, searchStrategy).isPresent(annotationType);
}
}These utilities allow fine‑grained control over which beans participate in method‑level validation.
Overall, the article demonstrates how to extend Spring Boot’s validation beyond controllers, unify exception handling, and selectively disable validation for specific packages, providing a more robust and flexible validation strategy for complex applications.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Spring Full-Stack Practical Cases
Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
