CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-jakarta-validation--jakarta-validation-api

Jakarta Validation API defines a metadata model and API for JavaBean and method validation

Pending
Overview
Eval results
Files

container-validation.mddocs/

Container Element Validation

Value extraction and validation for generic container types like collections and optionals with type-safe constraint application to container elements.

Capabilities

Value Extractor

Interface for extracting values from container types for validation.

/**
 * Defines how to extract values from a container type for validation
 * @param <T> the container type
 */
interface ValueExtractor<T> {
    /**
     * Extract values from the container and pass them to the receiver
     * @param originalValue the container instance
     * @param receiver receives extracted values for validation
     */
    void extractValues(T originalValue, ValueReceiver receiver);
    
    /**
     * Receives values extracted from containers
     */
    interface ValueReceiver {
        /**
         * Receive a simple extracted value
         * @param nodeName name for the path node (can be null)
         * @param object extracted value
         */
        void value(String nodeName, Object object);
        
        /**
         * Receive value from an iterable container
         * @param nodeName name for the path node (can be null)  
         * @param object extracted value
         */
        void iterableValue(String nodeName, Object object);
        
        /**
         * Receive value from an indexed container
         * @param nodeName name for the path node (can be null)
         * @param index index of the value
         * @param object extracted value
         */
        void indexedValue(String nodeName, int index, Object object);
        
        /**
         * Receive value from a keyed container (Map)
         * @param nodeName name for the path node (can be null)
         * @param key key of the value
         * @param object extracted value
         */
        void keyedValue(String nodeName, Object key, Object object);
    }
}

Value Extraction Annotations

Annotations for configuring value extraction behavior.

/**
 * Marks the extracted value in a ValueExtractor
 * Applied to type parameters in ValueExtractor implementations
 */
@Target({TYPE_USE})
@Retention(RUNTIME)
@interface ExtractedValue {
    /**
     * The type of the extracted value
     * @return extracted value type
     */
    Class<?> type() default Object.class;
}

/**
 * Marks types for default unwrapping behavior
 * Applied to container types that should be automatically unwrapped
 */
@Target({TYPE})
@Retention(RUNTIME)
@interface UnwrapByDefault {}

Unwrapping Configuration

Classes for controlling value unwrapping behavior.

/**
 * Unwrapping behavior configuration
 */
class Unwrapping {
    /**
     * Marker class indicating values should be unwrapped for validation
     */
    public static class Unwrap extends Unwrapping {}
    
    /**
     * Marker class indicating values should not be unwrapped for validation
     */
    public static class Skip extends Unwrapping {}
}

Usage Examples:

import jakarta.validation.*;
import jakarta.validation.constraints.*;
import jakarta.validation.valueextraction.*;
import java.util.*;

// 1. Container element validation with built-in extractors
public class ContainerValidationExample {
    // Validate elements in a List
    private List<@NotNull @Email String> emails;
    
    // Validate elements in a Set  
    private Set<@Valid @NotNull User> users;
    
    // Validate Map keys and values
    private Map<@NotBlank String, @Positive Integer> scores;
    
    // Validate Optional content
    private Optional<@NotNull @Valid User> optionalUser;
    
    // Validate nested containers
    private List<Set<@NotNull String>> nestedContainer;
}

// 2. Custom value extractor
public class CustomContainer<T> {
    private T value;
    
    public T getValue() { return value; }
    public void setValue(T value) { this.value = value; }
}

// Value extractor for CustomContainer
public class CustomContainerValueExtractor 
    implements ValueExtractor<CustomContainer<@ExtractedValue ?>> {
    
    @Override
    public void extractValues(CustomContainer<?> originalValue, ValueReceiver receiver) {
        if (originalValue != null) {
            receiver.value("value", originalValue.getValue());
        }
    }
}

// 3. Register custom extractor in configuration
public class CustomValidationConfiguration {
    public Validator createValidator() {
        Configuration<?> config = Validation.byDefaultProvider().configure();
        config.addValueExtractor(new CustomContainerValueExtractor());
        
        ValidatorFactory factory = config.buildValidatorFactory();
        return factory.getValidator();
    }
}

// 4. Usage with custom container
public class MyService {
    @Valid
    private CustomContainer<@NotNull @Email String> containerizedEmail;
    
    @Valid  
    private CustomContainer<@Valid User> containerizedUser;
}

// 5. Complex container validation
public class ComplexContainerExample {
    // Nested generics with constraints
    private Map<@NotBlank String, List<@Valid @NotNull Product>> productsByCategory;
    
    // Optional with nested container
    private Optional<List<@NotNull @Size(min=1, max=100) String>> optionalStringList;
    
    // Custom container with validation
    @Valid
    private CustomContainer<List<@Email String>> emailContainer;
}

// 6. Validation example
public class ContainerValidationDemo {
    private Validator validator;
    
    public ContainerValidationDemo() {
        // Create validator with custom extractor
        Configuration<?> config = Validation.byDefaultProvider().configure();
        config.addValueExtractor(new CustomContainerValueExtractor());
        ValidatorFactory factory = config.buildValidatorFactory();
        this.validator = factory.getValidator();
    }
    
    public void validateContainers() {
        // Create test object with invalid container elements
        ContainerValidationExample example = new ContainerValidationExample();
        
        // List with null and invalid emails
        example.setEmails(Arrays.asList(null, "invalid-email", "valid@example.com"));
        
        // Map with blank key and negative value
        Map<String, Integer> scores = new HashMap<>();
        scores.put("", -5);  // Invalid key and value
        scores.put("valid-key", 100);  // Valid entry
        example.setScores(scores);
        
        // Validate
        Set<ConstraintViolation<ContainerValidationExample>> violations = 
            validator.validate(example);
        
        for (ConstraintViolation<ContainerValidationExample> violation : violations) {
            System.out.println("Path: " + violation.getPropertyPath());
            System.out.println("Message: " + violation.getMessage());
            System.out.println("Invalid value: " + violation.getInvalidValue());
            System.out.println("---");
        }
        
        // Expected output shows path like:
        // emails[0] - NotNull violation
        // emails[1] - Email violation  
        // scores<K>[].key - NotBlank violation
        // scores<>[].value - Positive violation
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-jakarta-validation--jakarta-validation-api

docs

bean-validation.md

bootstrap-configuration.md

constraints.md

container-validation.md

custom-constraints.md

index.md

metadata.md

method-validation.md

validation-groups.md

tile.json