Spring Framework
Validation
Java
Programming
Spring Boot

How to manually trigger Spring validation?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In Spring MVC, validation often happens automatically when a controller parameter is annotated with @Valid or @Validated. But outside that request-binding flow, you may need to trigger validation yourself from a service, batch job, scheduled task, or custom workflow.

Spring supports this cleanly. The main question is whether you want Bean Validation through jakarta.validation.Validator or Spring's own Validator interface.

Manual Validation with Bean Validation

If your object uses annotations such as @NotBlank, @Email, or @Min, inject a Bean Validation Validator and call validate().

java
1import jakarta.validation.ConstraintViolation;
2import jakarta.validation.Validator;
3import jakarta.validation.constraints.Email;
4import jakarta.validation.constraints.NotBlank;
5import org.springframework.stereotype.Service;
6
7import java.util.Set;
8
9class UserRegistration {
10    @NotBlank
11    private String name;
12
13    @Email
14    private String email;
15
16    public UserRegistration(String name, String email) {
17        this.name = name;
18        this.email = email;
19    }
20}
21
22@Service
23public class RegistrationService {
24    private final Validator validator;
25
26    public RegistrationService(Validator validator) {
27        this.validator = validator;
28    }
29
30    public void register(UserRegistration request) {
31        Set<ConstraintViolation<UserRegistration>> violations =
32            validator.validate(request);
33
34        if (!violations.isEmpty()) {
35            throw new IllegalArgumentException(violations.toString());
36        }
37
38        // Continue with business logic.
39    }
40}

This is the most common manual-validation approach in Spring Boot applications.

Using Spring's Validator with Errors

If you have a custom Spring Validator, call it directly with a BindingResult implementation.

java
1import org.springframework.stereotype.Component;
2import org.springframework.validation.BeanPropertyBindingResult;
3import org.springframework.validation.Errors;
4import org.springframework.validation.Validator;
5
6class OrderRequest {
7    private int quantity;
8
9    public OrderRequest(int quantity) {
10        this.quantity = quantity;
11    }
12
13    public int getQuantity() {
14        return quantity;
15    }
16}
17
18@Component
19class OrderRequestValidator implements Validator {
20    @Override
21    public boolean supports(Class<?> clazz) {
22        return OrderRequest.class.isAssignableFrom(clazz);
23    }
24
25    @Override
26    public void validate(Object target, Errors errors) {
27        OrderRequest request = (OrderRequest) target;
28        if (request.getQuantity() <= 0) {
29            errors.rejectValue("quantity", "quantity.invalid", "Quantity must be positive");
30        }
31    }
32}
33
34OrderRequest request = new OrderRequest(0);
35BeanPropertyBindingResult errors = new BeanPropertyBindingResult(request, "orderRequest");
36new OrderRequestValidator().validate(request, errors);
37
38System.out.println(errors.getAllErrors());

This style is useful when validation logic is custom and not expressed as bean annotations.

When Manual Validation Makes Sense

Manual validation is useful when the object is not being created by Spring MVC request binding. Typical examples include:

  • messages read from a queue
  • rows imported from a CSV file
  • intermediate objects created inside a service
  • validation before calling a downstream system

In those cases, relying on @Valid alone is not enough because no controller method is triggering the validation step for you.

Validation Groups and Reuse

Manual validation also gives you precise control over validation groups.

java
Set<ConstraintViolation<UserRegistration>> violations =
    validator.validate(request, CreateUserGroup.class);

That is helpful when the same DTO has different rules for create versus update operations.

The broader design rule is simple: validation should live close to the boundary where incorrect data first becomes a problem. Sometimes that boundary is the controller. Sometimes it is a service or batch processor instead.

Common Pitfalls

  • Assuming @Valid runs automatically everywhere. It only runs where Spring is actually managing the validation trigger.
  • Throwing away detailed violation information too early instead of mapping it into a useful error response.
  • Mixing Bean Validation annotations and a custom Spring Validator without being clear about which one owns the rules.
  • Creating validation logic in controllers only, then forgetting to validate objects created elsewhere in the application.
  • Manually validating but ignoring validation groups when different workflows need different constraints.

Summary

  • Manual Spring validation is straightforward once you choose the right validator type.
  • Use jakarta.validation.Validator for annotation-based Bean Validation.
  • Use Spring's Validator plus Errors for custom validation logic.
  • Manual validation is especially useful outside controller request binding.
  • The goal is not just to "run validation," but to run it at the right application boundary.

Course illustration
Course illustration

All Rights Reserved.