Jakarta Validation API defines a metadata model and API for JavaBean and method validation
npx @tessl/cli install tessl/maven-jakarta-validation--jakarta-validation-api@3.1.0Jakarta Validation API provides a comprehensive framework for validating JavaBean objects and method parameters through annotations and constraint definitions. It offers a rich set of built-in validation constraints and enables developers to create custom validation logic with detailed error reporting and internationalization capabilities.
<dependency>
<groupId>jakarta.validation</groupId>
<artifactId>jakarta.validation-api</artifactId>
<version>3.1.1</version>
</dependency>import jakarta.validation.Validation;
import jakarta.validation.Validator;
import jakarta.validation.ValidatorFactory;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.Valid;
import jakarta.validation.Path;
import jakarta.validation.Configuration;
import jakarta.validation.executable.ExecutableValidator;
import jakarta.validation.constraints.*;import jakarta.validation.*;
import jakarta.validation.constraints.*;
import java.util.Set;
// Define a bean with validation constraints
class User {
@NotNull
@Size(min = 2, max = 50)
private String name;
@Min(18)
private int age;
@Email
private String email;
// Constructors, getters, setters...
}
// Validate the bean
ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();
User user = new User("", 15, "invalid-email");
Set<ConstraintViolation<User>> violations = validator.validate(user);
for (ConstraintViolation<User> violation : violations) {
System.out.println(violation.getPropertyPath() + ": " + violation.getMessage());
}Jakarta Validation API is built around several key components:
Validation, Configuration) for setting up validationValidator, ValidatorFactory) for performing validation@NotNull, @Size, etc.) and custom constraint definitionList<@NotNull String>Core API for setting up and configuring the validation framework with factories and context objects.
class Validation {
static ValidatorFactory buildDefaultValidatorFactory();
static GenericBootstrap byDefaultProvider();
static <T extends Configuration<T>, U extends ValidationProvider<T>>
ProviderSpecificBootstrap<T> byProvider(Class<U> providerType);
}
interface ValidatorFactory extends AutoCloseable {
Validator getValidator();
ValidatorContext usingContext();
MessageInterpolator getMessageInterpolator();
TraversableResolver getTraversableResolver();
ConstraintValidatorFactory getConstraintValidatorFactory();
ParameterNameProvider getParameterNameProvider();
ClockProvider getClockProvider();
<T> T unwrap(Class<T> type);
void close();
}
interface ValidatorContext {
ValidatorContext messageInterpolator(MessageInterpolator messageInterpolator);
ValidatorContext traversableResolver(TraversableResolver traversableResolver);
ValidatorContext constraintValidatorFactory(ConstraintValidatorFactory factory);
ValidatorContext parameterNameProvider(ParameterNameProvider parameterNameProvider);
ValidatorContext clockProvider(ClockProvider clockProvider);
Validator getValidator();
}
interface GenericBootstrap {
GenericBootstrap providerResolver(ValidationProviderResolver resolver);
Configuration<?> configure();
}
interface ProviderSpecificBootstrap<T extends Configuration<T>> {
ProviderSpecificBootstrap<T> providerResolver(ValidationProviderResolver resolver);
T configure();
}
interface Configuration<T extends Configuration<T>> {
T ignoreXmlConfiguration();
T messageInterpolator(MessageInterpolator interpolator);
T traversableResolver(TraversableResolver resolver);
T constraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory);
T parameterNameProvider(ParameterNameProvider parameterNameProvider);
T clockProvider(ClockProvider clockProvider);
T addValueExtractor(ValueExtractor<?> extractor);
T addMapping(InputStream stream);
T addProperty(String name, String value);
MessageInterpolator getDefaultMessageInterpolator();
TraversableResolver getDefaultTraversableResolver();
ConstraintValidatorFactory getDefaultConstraintValidatorFactory();
ParameterNameProvider getDefaultParameterNameProvider();
ClockProvider getDefaultClockProvider();
BootstrapConfiguration getBootstrapConfiguration();
ValidatorFactory buildValidatorFactory();
}
interface BootstrapConfiguration {
String getDefaultProviderClassName();
List<String> getConstraintValidatorFactoryClassName();
List<String> getMessageInterpolatorClassName();
List<String> getTraversableResolverClassName();
List<String> getParameterNameProviderClassName();
List<String> getClockProviderClassName();
List<String> getValueExtractorClassNames();
Set<String> getConstraintMappingResourcePaths();
Map<String, String> getProperties();
Set<ExecutableType> getExecutableValidation();
boolean isExecutableValidationEnabled();
}Primary validation interface for validating JavaBean objects, properties, and values with comprehensive constraint violation reporting.
interface Validator {
<T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateValue(Class<T> beanType, String propertyName, Object value, Class<?>... groups);
BeanDescriptor getConstraintsForClass(Class<?> clazz);
ExecutableValidator forExecutables();
<T> T unwrap(Class<T> type);
}
interface ConstraintViolation<T> {
String getMessage();
String getMessageTemplate();
T getRootBean();
Class<T> getRootBeanClass();
Object getLeafBean();
Object[] getExecutableParameters();
Object getExecutableReturnValue();
Path getPropertyPath();
Object getInvalidValue();
ConstraintDescriptor<?> getConstraintDescriptor();
<U> U unwrap(Class<U> type);
}Comprehensive set of pre-defined constraint annotations for common validation scenarios including null checks, size validation, numeric ranges, and format validation.
// Null value constraints
@interface NotNull { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Null { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
// String/Collection constraints
@interface NotEmpty { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface NotBlank { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Size { int min() default 0; int max() default Integer.MAX_VALUE; String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
// Numeric constraints
@interface Min { long value(); String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Max { long value(); String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface DecimalMin { String value(); boolean inclusive() default true; String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface DecimalMax { String value(); boolean inclusive() default true; String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Positive { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface PositiveOrZero { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Negative { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface NegativeOrZero { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Digits { int integer(); int fraction(); String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
// Date/Time constraints
@interface Future { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface FutureOrPresent { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Past { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface PastOrPresent { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
// Boolean constraints
@interface AssertTrue { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface AssertFalse { String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
// Format constraints
@interface Email { String regexp() default ".*"; Pattern.Flag[] flags() default {}; String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
@interface Pattern { String regexp(); Pattern.Flag[] flags() default {}; String message() default "..."; Class<?>[] groups() default {}; Class<? extends Payload>[] payload() default {}; }
enum Pattern.Flag {
UNIX_LINES, CASE_INSENSITIVE, COMMENTS, MULTILINE, DOTALL, UNICODE_CASE, CANON_EQ
}Framework for defining custom validation constraints through annotations and validator implementations with support for composed constraints.
@interface Constraint {
Class<? extends ConstraintValidator<?, ?>>[] validatedBy();
}
interface ConstraintValidator<A extends Annotation, T> {
default void initialize(A constraintAnnotation) {}
boolean isValid(T value, ConstraintValidatorContext context);
}
interface ConstraintValidatorContext {
void disableDefaultConstraintViolation();
String getDefaultConstraintMessageTemplate();
ClockProvider getClockProvider();
ConstraintViolationBuilder buildConstraintViolationWithTemplate(String messageTemplate);
<T> T unwrap(Class<T> type);
}
@interface Valid {}
@interface ReportAsSingleViolation {}
@interface OverridesAttribute {
String constraint();
String name();
int constraintIndex() default -1;
}
@interface SupportedValidationTarget {
ValidationTarget[] value();
}Validation support for method parameters, return values, and constructor parameters with cross-parameter constraint capabilities.
interface ExecutableValidator {
<T> Set<ConstraintViolation<T>> validateParameters(T object, Method method, Object[] parameterValues, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateReturnValue(T object, Method method, Object returnValue, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateConstructorParameters(Constructor<? extends T> constructor, Object[] parameterValues, Class<?>... groups);
<T> Set<ConstraintViolation<T>> validateConstructorReturnValue(Constructor<? extends T> constructor, T createdObject, Class<?>... groups);
}
enum ExecutableType {
IMPLICIT, NONE, CONSTRUCTORS, NON_GETTER_METHODS, GETTER_METHODS, ALL
}
@interface ValidateOnExecution {
ExecutableType[] type() default {ExecutableType.IMPLICIT};
}Group-based validation for conditional constraint application and validation sequencing with group conversion support.
interface Default {}
@interface GroupSequence {
Class<?>[] value();
}
@interface ConvertGroup {
Class<?> from();
Class<?> to();
}Value extraction and validation for generic container types like collections and optionals with type-safe constraint application.
interface ValueExtractor<T> {
void extractValues(T originalValue, ValueReceiver receiver);
interface ValueReceiver {
void value(String nodeName, Object object);
void iterableValue(String nodeName, Object object);
void indexedValue(String nodeName, int index, Object object);
void keyedValue(String nodeName, Object key, Object object);
}
}
@interface ExtractedValue {
Class<?> type() default Object.class;
}
@interface UnwrapByDefault {}Comprehensive metadata API providing descriptors and introspection capabilities for validation constraints and bean structure.
interface BeanDescriptor extends ElementDescriptor {
boolean isBeanConstrained();
PropertyDescriptor getPropertyDescriptor(String propertyName);
Set<PropertyDescriptor> getConstrainedProperties();
MethodDescriptor getMethodDescriptor(String methodName, Class<?>... parameterTypes);
Set<MethodDescriptor> getConstrainedMethods(MethodType methodType, MethodType... methodTypes);
ConstructorDescriptor getConstructorDescriptor(Class<?>... parameterTypes);
Set<ConstructorDescriptor> getConstrainedConstructors();
}
interface ConstraintDescriptor<T extends Annotation> {
T getAnnotation();
String getMessageTemplate();
Set<Class<?>> getGroups();
Set<Class<? extends Payload>> getPayload();
List<Class<? extends ConstraintValidator<T, ?>>> getConstraintValidatorClasses();
Map<String, Object> getAttributes();
Set<ConstraintDescriptor<?>> getComposingConstraints();
}Service Provider Interface (SPI) for pluggable validation provider implementations and bootstrap configuration.
interface ValidationProvider<T extends Configuration<T>> {
T createSpecializedConfiguration(BootstrapState state);
Configuration<?> createGenericConfiguration(BootstrapState state);
ValidatorFactory buildValidatorFactory(ConfigurationState configurationState);
}
interface BootstrapState {
ValidationProviderResolver getValidationProviderResolver();
ValidationProviderResolver getDefaultValidationProviderResolver();
}
interface ConfigurationState {
boolean isIgnoreXmlConfiguration();
MessageInterpolator getMessageInterpolator();
Set<InputStream> getMappingStreams();
Set<ValueExtractor<?>> getValueExtractors();
ConstraintValidatorFactory getConstraintValidatorFactory();
TraversableResolver getTraversableResolver();
ParameterNameProvider getParameterNameProvider();
ClockProvider getClockProvider();
Map<String, String> getProperties();
}
interface ValidationProviderResolver {
List<ValidationProvider<?>> getValidationProviders();
}// Core exception hierarchy
class ValidationException extends RuntimeException {}
class ConstraintViolationException extends ValidationException {
Set<ConstraintViolation<?>> getConstraintViolations();
}
class ConstraintDeclarationException extends ValidationException {}
class ConstraintDefinitionException extends ValidationException {}
class GroupDefinitionException extends ValidationException {}
class NoProviderFoundException extends ValidationException {}
class UnexpectedTypeException extends ValidationException {}
class ValueExtractorDeclarationException extends ValidationException {}
class ValueExtractorDefinitionException extends ValidationException {}
// Supporting component interfaces
interface MessageInterpolator {
String interpolate(String messageTemplate, Context context);
String interpolate(String messageTemplate, Context context, Locale locale);
interface Context {
ConstraintDescriptor<?> getConstraintDescriptor();
Object getValidatedValue();
<T> T unwrap(Class<T> type);
}
}
interface TraversableResolver {
boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType);
boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType);
}
interface ParameterNameProvider {
List<String> getParameterNames(Constructor<?> constructor);
List<String> getParameterNames(Method method);
}
interface ClockProvider {
Clock getClock();
}
interface ConstraintValidatorFactory {
<T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key);
void releaseInstance(ConstraintValidator<?, ?> instance);
}
// Path navigation
interface Path extends Iterable<Path.Node> {
String toString();
interface Node {
String getName();
boolean isInIterable();
Integer getIndex();
Object getKey();
ElementKind getKind();
<T extends Path.Node> T as(Class<T> nodeType);
String toString();
}
interface BeanNode extends Node {}
interface PropertyNode extends Node {}
interface MethodNode extends Node {
List<Class<?>> getParameterTypes();
}
interface ConstructorNode extends Node {
List<Class<?>> getParameterTypes();
}
interface ParameterNode extends Node {
int getParameterIndex();
}
interface CrossParameterNode extends Node {}
interface ReturnValueNode extends Node {}
interface ContainerElementNode extends Node {
Class<?> getContainerClass();
Integer getTypeArgumentIndex();
}
}
// Element classification
enum ElementKind {
BEAN, PROPERTY, METHOD, CONSTRUCTOR, PARAMETER, CROSS_PARAMETER, RETURN_VALUE, CONTAINER_ELEMENT
}
// Constraint targeting
enum ConstraintTarget {
IMPLICIT, PARAMETERS, RETURN_VALUE
}
// Validation targeting
enum ValidationTarget {
ANNOTATED_ELEMENT, PARAMETERS
}
// Method types for metadata
enum MethodType {
GETTER, NON_GETTER
}
// Value extraction configuration
enum Unwrapping {
AUTOMATIC, SKIP
}
enum ValidateUnwrappedValue {
DEFAULT, SKIP, UNWRAP
}
// Payload marker
interface Payload {}