In Spring MVC, the standard way to validate form data is to use Jakarta Bean Validation annotations on a form/DTO object, then check validation results in your controller with BindingResult.
Since your project uses Jakarta EE, use jakarta.validation.* imports.
1. Add validation annotations to your form object
Example form/DTO:
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
public class UserForm {
@NotBlank(message = "Name is required")
@Size(max = 100, message = "Name must be at most 100 characters")
private String name;
@NotBlank(message = "Email is required")
@Email(message = "Please enter a valid email address")
private String email;
@NotBlank(message = "Password is required")
@Size(min = 8, message = "Password must be at least 8 characters")
private String password;
// getters and setters
}
With Lombok:
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Size;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class UserForm {
@NotBlank(message = "Name is required")
@Size(max = 100, message = "Name must be at most 100 characters")
private String name;
@NotBlank(message = "Email is required")
@Email(message = "Please enter a valid email address")
private String email;
@NotBlank(message = "Password is required")
@Size(min = 8, message = "Password must be at least 8 characters")
private String password;
}
2. Use @Valid in your controller
import jakarta.validation.Valid;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@Controller
public class UserController {
@GetMapping("/register")
public String showRegisterForm(Model model) {
model.addAttribute("userForm", new UserForm());
return "register";
}
@PostMapping("/register")
public String register(
@Valid UserForm userForm,
BindingResult bindingResult
) {
if (bindingResult.hasErrors()) {
return "register";
}
// Save user or call service layer here
return "redirect:/register/success";
}
}
Important: BindingResult must come immediately after the validated object.
Correct:
public String register(@Valid UserForm userForm, BindingResult bindingResult)
Incorrect:
public String register(@Valid UserForm userForm, Model model, BindingResult bindingResult)
3. Display errors in Thymeleaf
If you use Thymeleaf:
<form th:action="@{/register}" th:object="${userForm}" method="post">
<div>
<label>Name</label>
<input type="text" th:field="*{name}">
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
</div>
<div>
<label>Email</label>
<input type="email" th:field="*{email}">
<span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
</div>
<div>
<label>Password</label>
<input type="password" th:field="*{password}">
<span th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></span>
</div>
<button type="submit">Register</button>
</form>
4. Common validation annotations
@NotNull
@NotBlank
@NotEmpty
@Size(min = 2, max = 100)
@Min(18)
@Max(120)
@Email
@Pattern(regexp = "...")
@Past
@Future
@Positive
@PositiveOrZero
Use:
@NotNullfor any value that must not benull@NotBlankfor strings that must contain non-whitespace text@NotEmptyfor strings, collections, arrays, or maps that must not be empty@Sizefor string length or collection size@Emailfor email format validation
5. Maven dependency
If you use Spring Boot, add:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
For Gradle:
implementation("org.springframework.boot:spring-boot-starter-validation")
6. Service-layer validation
You can also validate method parameters in Spring services:
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@Service
@Validated
public class UserService {
public void createUser(@Valid UserForm userForm) {
// business logic
}
}
7. REST API validation example
For JSON request bodies:
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class UserRestController {
@PostMapping("/api/users")
public String createUser(@Valid @RequestBody UserForm userForm) {
return "User created";
}
}
For REST APIs, invalid input usually results in a 400 Bad Request.
Summary
Use this pattern:
@PostMapping("/submit")
public String submit(@Valid MyForm form, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "form-page";
}
return "redirect:/success";
}
That is the typical Spring MVC form validation flow.
