Jakarta Validation API defines a metadata model and API for JavaBean and method validation
—
Comprehensive metadata API providing descriptors and introspection capabilities for validation constraints, bean structure, and executable validation configuration.
Describes validation metadata for a bean class including properties, methods, and constructors.
/**
* Describes validation metadata for a bean
*/
interface BeanDescriptor extends ElementDescriptor {
/**
* Check if the bean has any validation constraints
* @return true if bean has constraints or cascaded properties
*/
boolean isBeanConstrained();
/**
* Get descriptor for a specific property
* @param propertyName property name
* @return PropertyDescriptor or null if property doesn't exist
*/
PropertyDescriptor getPropertyDescriptor(String propertyName);
/**
* Get all constrained properties
* @return set of PropertyDescriptor for constrained properties
*/
Set<PropertyDescriptor> getConstrainedProperties();
/**
* Get descriptor for a specific method
* @param methodName method name
* @param parameterTypes parameter types
* @return MethodDescriptor or null if method doesn't exist
*/
MethodDescriptor getMethodDescriptor(String methodName, Class<?>... parameterTypes);
/**
* Get all constrained methods of specified types
* @param methodType first method type to include
* @param methodTypes additional method types
* @return set of MethodDescriptor for constrained methods
*/
Set<MethodDescriptor> getConstrainedMethods(MethodType methodType, MethodType... methodTypes);
/**
* Get descriptor for a specific constructor
* @param parameterTypes parameter types
* @return ConstructorDescriptor or null if constructor doesn't exist
*/
ConstructorDescriptor getConstructorDescriptor(Class<?>... parameterTypes);
/**
* Get all constrained constructors
* @return set of ConstructorDescriptor for constrained constructors
*/
Set<ConstructorDescriptor> getConstrainedConstructors();
}Describes metadata for a specific constraint including annotation details and validator classes.
/**
* Describes a single constraint and its metadata
* @param <T> the constraint annotation type
*/
interface ConstraintDescriptor<T extends Annotation> {
/**
* Get the constraint annotation instance
* @return annotation instance
*/
T getAnnotation();
/**
* Get the constraint message template
* @return message template string
*/
String getMessageTemplate();
/**
* Get the groups the constraint belongs to
* @return set of group classes
*/
Set<Class<?>> getGroups();
/**
* Get the constraint payload
* @return set of payload classes
*/
Set<Class<? extends Payload>> getPayload();
/**
* Get constraint validator classes
* @return list of ConstraintValidator classes
*/
List<Class<? extends ConstraintValidator<T, ?>>> getConstraintValidatorClasses();
/**
* Get constraint attributes (annotation element values)
* @return map of attribute names to values
*/
Map<String, Object> getAttributes();
/**
* Get composing constraints for composed constraints
* @return set of composing constraint descriptors
*/
Set<ConstraintDescriptor<?>> getComposingConstraints();
/**
* Check if composed constraint reports as single violation
* @return true if @ReportAsSingleViolation is present
*/
boolean isReportAsSingleViolation();
/**
* Get validation applies to setting (parameters vs return value)
* @return ConstraintTarget value
*/
ConstraintTarget getValidationAppliesTo();
/**
* Get value unwrapping setting
* @return ValidateUnwrappedValue enum value
*/
ValidateUnwrappedValue getValueUnwrapping();
}Base descriptor interface and specialized descriptors for different validation elements.
/**
* Base interface for validation element descriptors
*/
interface ElementDescriptor {
/**
* Check if element has any constraints
* @return true if element has constraints
*/
boolean hasConstraints();
/**
* Get the element class
* @return class of the element
*/
Class<?> getElementClass();
/**
* Get all constraint descriptors for this element
* @return set of ConstraintDescriptor instances
*/
Set<ConstraintDescriptor<?>> getConstraintDescriptors();
/**
* Find constraints matching criteria
* @return ConstraintFinder for building constraint queries
*/
ConstraintFinder findConstraints();
/**
* Builder for finding constraints with various criteria
*/
interface ConstraintFinder {
ConstraintFinder unorderedAndMatchingGroups(Class<?>... groups);
ConstraintFinder lookingAt(Scope scope);
ConstraintFinder declaredOn(ElementType... types);
Set<ConstraintDescriptor<?>> getConstraintDescriptors();
}
}
/**
* Describes property validation metadata
*/
interface PropertyDescriptor extends ElementDescriptor, CascadableDescriptor, ContainerDescriptor {
/**
* Get the property name
* @return property name
*/
String getPropertyName();
}
/**
* Describes method validation metadata
*/
interface MethodDescriptor extends ExecutableDescriptor {
/**
* Get methods this method overrides
* @return set of overridden method descriptors
*/
Set<MethodDescriptor> getOverriddenMethods();
}
/**
* Describes constructor validation metadata
*/
interface ConstructorDescriptor extends ExecutableDescriptor {
// Inherits all methods from ExecutableDescriptor
}
/**
* Base descriptor for executables (methods and constructors)
*/
interface ExecutableDescriptor extends ElementDescriptor {
/**
* Get the executable name
* @return method name or "<init>" for constructors
*/
String getName();
/**
* Get parameter descriptors
* @return list of parameter descriptors
*/
List<ParameterDescriptor> getParameterDescriptors();
/**
* Get cross-parameter descriptor
* @return CrossParameterDescriptor for cross-parameter constraints
*/
CrossParameterDescriptor getCrossParameterDescriptor();
/**
* Get return value descriptor
* @return ReturnValueDescriptor for return value constraints
*/
ReturnValueDescriptor getReturnValueDescriptor();
/**
* Check if executable has constrained parameters
* @return true if any parameters have constraints
*/
boolean hasConstrainedParameters();
/**
* Check if executable has constrained return value
* @return true if return value has constraints
*/
boolean hasConstrainedReturnValue();
}Enums used by the metadata API for classification and configuration.
/**
* Method types for descriptor queries
*/
enum MethodType {
/** Getter methods (following JavaBean naming conventions) */
GETTER,
/** Non-getter methods */
NON_GETTER
}
/**
* Scope for constraint searches
*/
enum Scope {
/** Include inherited constraints */
HIERARCHY,
/** Only local constraints */
LOCAL_ELEMENT
}
/**
* Settings for validating unwrapped values
*/
enum ValidateUnwrappedValue {
/** Use default unwrapping behavior */
DEFAULT,
/** Force unwrapping */
UNWRAP,
/** Skip unwrapping */
SKIP
}Usage Examples:
import jakarta.validation.*;
import jakarta.validation.metadata.*;
import java.util.Set;
public class MetadataInspectionExample {
private Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
public void inspectBeanMetadata() {
// Get bean descriptor
BeanDescriptor beanDescriptor = validator.getConstraintsForClass(User.class);
System.out.println("Bean constrained: " + beanDescriptor.isBeanConstrained());
System.out.println("Element class: " + beanDescriptor.getElementClass().getSimpleName());
// Inspect constrained properties
Set<PropertyDescriptor> properties = beanDescriptor.getConstrainedProperties();
for (PropertyDescriptor property : properties) {
System.out.println("\nProperty: " + property.getPropertyName());
System.out.println(" Has constraints: " + property.hasConstraints());
System.out.println(" Is cascaded: " + property.isCascaded());
// Get constraints for this property
Set<ConstraintDescriptor<?>> constraints = property.getConstraintDescriptors();
for (ConstraintDescriptor<?> constraint : constraints) {
System.out.println(" Constraint: " +
constraint.getAnnotation().annotationType().getSimpleName());
System.out.println(" Message: " + constraint.getMessageTemplate());
System.out.println(" Groups: " + constraint.getGroups());
System.out.println(" Attributes: " + constraint.getAttributes());
}
}
// Inspect constrained methods
Set<MethodDescriptor> methods = beanDescriptor.getConstrainedMethods(
MethodType.NON_GETTER, MethodType.GETTER);
for (MethodDescriptor method : methods) {
System.out.println("\nMethod: " + method.getName());
System.out.println(" Constrained parameters: " + method.hasConstrainedParameters());
System.out.println(" Constrained return: " + method.hasConstrainedReturnValue());
// Inspect parameters
List<ParameterDescriptor> parameters = method.getParameterDescriptors();
for (int i = 0; i < parameters.size(); i++) {
ParameterDescriptor param = parameters.get(i);
System.out.println(" Parameter " + i + ": " + param.getName());
System.out.println(" Has constraints: " + param.hasConstraints());
}
// Inspect return value
ReturnValueDescriptor returnValue = method.getReturnValueDescriptor();
if (returnValue.hasConstraints()) {
System.out.println(" Return value constraints: " +
returnValue.getConstraintDescriptors().size());
}
}
}
public void findSpecificConstraints() {
BeanDescriptor beanDescriptor = validator.getConstraintsForClass(User.class);
// Find constraints for a specific property
PropertyDescriptor emailProperty = beanDescriptor.getPropertyDescriptor("email");
if (emailProperty != null) {
// Find only @Email constraints
Set<ConstraintDescriptor<?>> emailConstraints = emailProperty
.findConstraints()
.lookingAt(Scope.LOCAL_ELEMENT)
.getConstraintDescriptors();
for (ConstraintDescriptor<?> constraint : emailConstraints) {
if (constraint.getAnnotation().annotationType().equals(Email.class)) {
System.out.println("Found @Email constraint");
System.out.println("Validator classes: " +
constraint.getConstraintValidatorClasses());
}
}
}
}
public void inspectComposedConstraints() {
// Assuming we have a composed constraint @ValidName
BeanDescriptor beanDescriptor = validator.getConstraintsForClass(User.class);
PropertyDescriptor nameProperty = beanDescriptor.getPropertyDescriptor("name");
if (nameProperty != null) {
for (ConstraintDescriptor<?> constraint : nameProperty.getConstraintDescriptors()) {
System.out.println("Constraint: " +
constraint.getAnnotation().annotationType().getSimpleName());
// Check if it's a composed constraint
Set<ConstraintDescriptor<?>> composingConstraints =
constraint.getComposingConstraints();
if (!composingConstraints.isEmpty()) {
System.out.println(" Composed of:");
for (ConstraintDescriptor<?> composing : composingConstraints) {
System.out.println(" - " +
composing.getAnnotation().annotationType().getSimpleName());
}
System.out.println(" Reports as single violation: " +
constraint.isReportAsSingleViolation());
}
}
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-jakarta-validation--jakarta-validation-api