javaintermediate
Spring Boot — Custom Validator Annotation
Create custom validation annotations with ConstraintValidator for domain-specific field validation.
javaPress ⌘/Ctrl + Shift + C to copy
import jakarta.validation.*;
import java.lang.annotation.*;
import java.util.regex.Pattern;
// 1. Define custom annotation
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneNumberValidator.class)
public @interface ValidPhone {
String message() default "Invalid phone number format";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
// 2. Implement validator
public class PhoneNumberValidator implements ConstraintValidator<ValidPhone, String> {
private static final Pattern PHONE_PATTERN =
Pattern.compile("^\\+?[1-9]\\d{1,14}$"); // E.164 format
@Override
public boolean isValid(String value, ConstraintValidatorContext ctx) {
if (value == null) return true; // use @NotNull separately
return PHONE_PATTERN.matcher(value).matches();
}
}
// 3. Cross-field validation
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PasswordMatchValidator.class)
public @interface PasswordMatch {
String message() default "Passwords do not match";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
public class PasswordMatchValidator implements ConstraintValidator<PasswordMatch, RegisterRequest> {
@Override
public boolean isValid(RegisterRequest req, ConstraintValidatorContext ctx) {
if (req.password() == null) return true;
return req.password().equals(req.confirmPassword());
}
}
// 4. Usage in DTO
@PasswordMatch
record RegisterRequest(
@NotBlank String name,
@Email String email,
@ValidPhone String phone,
@Size(min = 8) String password,
String confirmPassword
) {}Use Cases
- Domain-specific input validation
- Cross-field validation for forms
- Reusable validation logic across DTOs
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
javaintermediate
Spring Boot REST Controller with CRUD
Create a complete REST API with Spring Boot: GET, POST, PUT, DELETE with validation and error handling.
Best for: Building RESTful APIs with Spring Boot
#spring-boot#rest-api
javaintermediate
Spring Boot Global Exception Handler
Centralized error handling with @ControllerAdvice for validation errors, 404s, and custom exceptions.
Best for: Consistent error responses across all endpoints
#spring-boot#error-handling
javaadvanced
Spring Security — JWT Authentication
Implement JWT authentication with Spring Security: token generation, validation, and filter chain.
Best for: Securing REST APIs with JWT tokens
#spring-boot#jwt
javaadvanced
Spring WebFlux — Reactive REST API
Build reactive REST APIs with Spring WebFlux using Mono, Flux, and non-blocking operations.
Best for: High-throughput non-blocking APIs
#spring-boot#webflux