CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-hibernate-validator--hibernate-validator

Hibernate Validator is the reference implementation of Jakarta Validation 3.1 providing annotation-based validation for JavaBeans and method parameters

Overview
Eval results
Files

resource-loading.mddocs/

Resource Bundle Loading

Multiple resource bundle locator implementations supporting platform resource bundles, aggregation of multiple bundles, caching, and delegation patterns for flexible message source configuration.

Capabilities

Platform Resource Bundle Locator

Default platform-based resource bundle locator using Java's standard ResourceBundle mechanism.

package org.hibernate.validator.resourceloading;

import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * Default implementation using platform's ResourceBundle mechanism.
 * Loads resource bundles using standard Java resource bundle loading.
 */
class PlatformResourceBundleLocator implements ResourceBundleLocator {
    /**
     * Create locator for specified bundle name.
     *
     * @param bundleName resource bundle name (without .properties extension)
     */
    PlatformResourceBundleLocator(String bundleName);

    /**
     * Create locator with custom class loader.
     *
     * @param bundleName resource bundle name
     * @param classLoader class loader for loading bundles
     */
    PlatformResourceBundleLocator(String bundleName, ClassLoader classLoader);

    /**
     * Create locator with class loader and control.
     *
     * @param bundleName resource bundle name
     * @param classLoader class loader for loading bundles
     * @param control resource bundle control for loading strategy
     */
    PlatformResourceBundleLocator(
        String bundleName,
        ClassLoader classLoader,
        ResourceBundle.Control control);

    /**
     * Get resource bundle for specified locale.
     *
     * @param locale locale for bundle
     * @return resource bundle
     */
    @Override
    ResourceBundle getResourceBundle(Locale locale);
}

Usage Example:

import org.hibernate.validator.resourceloading.PlatformResourceBundleLocator;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import jakarta.validation.*;
import java.util.*;

// Create locator for custom bundle
ResourceBundleLocator locator = new PlatformResourceBundleLocator("MyValidationMessages");

// Use with message interpolator
MessageInterpolator interpolator = new ResourceBundleMessageInterpolator(locator);

ValidatorFactory factory = Validation.byDefaultProvider()
    .configure()
    .messageInterpolator(interpolator)
    .buildValidatorFactory();

// MyValidationMessages.properties:
// user.name.required=User name is required
// user.email.invalid=Invalid email format
// user.age.range=Age must be between {min} and {max}

// MyValidationMessages_fr.properties:
// user.name.required=Le nom d'utilisateur est requis
// user.email.invalid=Format d'email invalide
// user.age.range=L'âge doit être entre {min} et {max}

Aggregate Resource Bundle Locator

Aggregates multiple resource bundle locators into a single combined bundle.

package org.hibernate.validator.resourceloading;

import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * Aggregates multiple ResourceBundleLocators.
 * Combines resource bundles from multiple sources into single bundle.
 * Messages are looked up in order of locators; first match wins.
 */
class AggregateResourceBundleLocator implements ResourceBundleLocator {
    /**
     * Create aggregating locator.
     *
     * @param resourceBundleLocators list of locators to aggregate
     */
    AggregateResourceBundleLocator(List<ResourceBundleLocator> resourceBundleLocators);

    /**
     * Get aggregated resource bundle for specified locale.
     * Returns AggregateResourceBundle combining all locators.
     *
     * @param locale locale for bundle
     * @return aggregated resource bundle
     */
    @Override
    ResourceBundle getResourceBundle(Locale locale);
}

Usage Example:

import org.hibernate.validator.resourceloading.*;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import java.util.*;

// Create multiple resource bundle locators
ResourceBundleLocator userMessages =
    new PlatformResourceBundleLocator("UserMessages");
ResourceBundleLocator productMessages =
    new PlatformResourceBundleLocator("ProductMessages");
ResourceBundleLocator orderMessages =
    new PlatformResourceBundleLocator("OrderMessages");

// Aggregate them
AggregateResourceBundleLocator aggregateLocator =
    new AggregateResourceBundleLocator(Arrays.asList(
        userMessages,
        productMessages,
        orderMessages
    ));

// Use aggregated locator
MessageInterpolator interpolator = new ResourceBundleMessageInterpolator(aggregateLocator);

// Message lookup order:
// 1. UserMessages.properties
// 2. ProductMessages.properties
// 3. OrderMessages.properties
// First matching key wins

Aggregate Resource Bundle

Resource bundle that aggregates multiple resource bundles.

package org.hibernate.validator.resourceloading;

import java.util.Enumeration;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * ResourceBundle aggregating multiple resource bundles.
 * Provides unified view over multiple resource bundle sources.
 */
class AggregateResourceBundle extends ResourceBundle {
    /**
     * Create aggregate bundle.
     *
     * @param locale locale for bundle
     * @param bundlesToAggregate bundles to aggregate
     */
    AggregateResourceBundle(Locale locale, Iterable<ResourceBundle> bundlesToAggregate);

    /**
     * Get object for key from aggregated bundles.
     *
     * @param key message key
     * @return message value from first bundle containing key
     */
    @Override
    protected Object handleGetObject(String key);

    /**
     * Get enumeration of all keys from all aggregated bundles.
     *
     * @return enumeration of all keys
     */
    @Override
    Enumeration<String> getKeys();
}

Caching Resource Bundle Locator

Wraps another resource bundle locator with caching capability.

package org.hibernate.validator.resourceloading;

import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * ResourceBundleLocator with caching support.
 * Caches resource bundles by locale to avoid repeated loading.
 */
class CachingResourceBundleLocator implements ResourceBundleLocator {
    /**
     * Create caching locator wrapping delegate.
     *
     * @param delegate underlying locator to cache
     */
    CachingResourceBundleLocator(ResourceBundleLocator delegate);

    /**
     * Get cached resource bundle for locale.
     * Loads from delegate and caches on first request.
     *
     * @param locale locale for bundle
     * @return cached resource bundle
     */
    @Override
    ResourceBundle getResourceBundle(Locale locale);
}

Usage Example:

import org.hibernate.validator.resourceloading.*;

// Create base locator
ResourceBundleLocator baseLocator =
    new PlatformResourceBundleLocator("ValidationMessages");

// Wrap with caching
CachingResourceBundleLocator cachingLocator =
    new CachingResourceBundleLocator(baseLocator);

// Use caching locator
// Subsequent calls with same locale will return cached bundle
ResourceBundle bundle1 = cachingLocator.getResourceBundle(Locale.US);
ResourceBundle bundle2 = cachingLocator.getResourceBundle(Locale.US);
// bundle1 and bundle2 are the same instance (cached)

Delegating Resource Bundle Locator

Delegates resource bundle loading to another locator.

package org.hibernate.validator.resourceloading;

import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import java.util.Locale;
import java.util.ResourceBundle;

/**
 * ResourceBundleLocator that delegates to another locator.
 * Base class for decorating locators with additional behavior.
 */
class DelegatingResourceBundleLocator implements ResourceBundleLocator {
    /**
     * Create delegating locator.
     *
     * @param delegate locator to delegate to
     */
    DelegatingResourceBundleLocator(ResourceBundleLocator delegate);

    /**
     * Get resource bundle by delegating to wrapped locator.
     *
     * @param locale locale for bundle
     * @return resource bundle from delegate
     */
    @Override
    ResourceBundle getResourceBundle(Locale locale);
}

Complete Resource Bundle Configuration Example

import org.hibernate.validator.resourceloading.*;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import jakarta.validation.*;
import java.util.*;

/**
 * Configure complex resource bundle hierarchy:
 * 1. Application-specific messages
 * 2. Module-specific messages
 * 3. Contributor messages
 * 4. Default ValidationMessages
 */
class ResourceBundleConfiguration {

    public ValidatorFactory createValidatorFactory() {
        // Create individual locators
        ResourceBundleLocator appMessages =
            new PlatformResourceBundleLocator("ApplicationMessages");

        ResourceBundleLocator userModuleMessages =
            new PlatformResourceBundleLocator("UserModuleMessages");

        ResourceBundleLocator productModuleMessages =
            new PlatformResourceBundleLocator("ProductModuleMessages");

        ResourceBundleLocator contributorMessages =
            new PlatformResourceBundleLocator("ContributorMessages");

        ResourceBundleLocator defaultMessages =
            new PlatformResourceBundleLocator("ValidationMessages");

        // Aggregate module messages
        AggregateResourceBundleLocator moduleMessages =
            new AggregateResourceBundleLocator(Arrays.asList(
                userModuleMessages,
                productModuleMessages
            ));

        // Create final hierarchy
        AggregateResourceBundleLocator allMessages =
            new AggregateResourceBundleLocator(Arrays.asList(
                appMessages,           // Highest priority
                moduleMessages,
                contributorMessages,
                defaultMessages        // Lowest priority
            ));

        // Add caching for performance
        CachingResourceBundleLocator cachedMessages =
            new CachingResourceBundleLocator(allMessages);

        // Create message interpolator
        ResourceBundleMessageInterpolator interpolator =
            new ResourceBundleMessageInterpolator(cachedMessages);

        // Build validator factory
        return Validation.byDefaultProvider()
            .configure()
            .messageInterpolator(interpolator)
            .buildValidatorFactory();
    }
}

// Message lookup order:
// 1. ApplicationMessages.properties (app-specific overrides)
// 2. UserModuleMessages.properties (user module messages)
// 3. ProductModuleMessages.properties (product module messages)
// 4. ContributorMessages.properties (contributor messages)
// 5. ValidationMessages.properties (defaults)

Custom Resource Bundle Locator

import org.hibernate.validator.spi.resourceloading.ResourceBundleLocator;
import java.util.*;

/**
 * Custom resource bundle locator loading messages from database.
 */
class DatabaseResourceBundleLocator implements ResourceBundleLocator {

    private final MessageRepository messageRepository;

    public DatabaseResourceBundleLocator(MessageRepository messageRepository) {
        this.messageRepository = messageRepository;
    }

    @Override
    public ResourceBundle getResourceBundle(Locale locale) {
        // Load messages from database
        Map<String, String> messages = messageRepository.findMessagesByLocale(locale);

        // Create resource bundle from database messages
        return new DatabaseResourceBundle(messages);
    }
}

/**
 * ResourceBundle backed by database messages.
 */
class DatabaseResourceBundle extends ResourceBundle {

    private final Map<String, String> messages;

    public DatabaseResourceBundle(Map<String, String> messages) {
        this.messages = messages;
    }

    @Override
    protected Object handleGetObject(String key) {
        return messages.get(key);
    }

    @Override
    public Enumeration<String> getKeys() {
        return Collections.enumeration(messages.keySet());
    }
}

// Usage
interface MessageRepository {
    Map<String, String> findMessagesByLocale(Locale locale);
}

class MessageRepositoryImpl implements MessageRepository {
    @Override
    public Map<String, String> findMessagesByLocale(Locale locale) {
        // Query database for messages
        Map<String, String> messages = new HashMap<>();
        // ... load from database ...
        return messages;
    }
}

// Configure validator with database messages
MessageRepository repository = new MessageRepositoryImpl();
ResourceBundleLocator dbLocator = new DatabaseResourceBundleLocator(repository);

// Combine database messages with file-based messages
ResourceBundleLocator fileLocator =
    new PlatformResourceBundleLocator("ValidationMessages");

AggregateResourceBundleLocator combinedLocator =
    new AggregateResourceBundleLocator(Arrays.asList(
        dbLocator,      // Database messages (higher priority)
        fileLocator     // File messages (fallback)
    ));

MessageInterpolator interpolator =
    new ResourceBundleMessageInterpolator(combinedLocator);

ValidatorFactory factory = Validation.byDefaultProvider()
    .configure()
    .messageInterpolator(interpolator)
    .buildValidatorFactory();

Resource Bundle Organization Best Practices

/**
 * Best practices for organizing validation messages:
 *
 * 1. Hierarchical structure:
 *    - ValidationMessages.properties (defaults from Jakarta Validation & Hibernate Validator)
 *    - ApplicationMessages.properties (application-wide overrides)
 *    - ModuleMessages.properties (module-specific messages)
 *    - CustomMessages.properties (custom constraint messages)
 *
 * 2. Message key conventions:
 *    - Standard constraints: Use default keys (e.g., jakarta.validation.constraints.NotNull.message)
 *    - Custom constraints: Use fully qualified names (e.g., com.example.constraints.CustomConstraint.message)
 *    - Domain-specific: Use domain prefixes (e.g., user.email.invalid, product.price.negative)
 *
 * 3. Localization:
 *    - Create locale-specific files: ValidationMessages_fr.properties, ValidationMessages_de.properties
 *    - Keep keys consistent across all locales
 *    - Provide fallback messages in default bundle
 *
 * 4. Parameter naming:
 *    - Use descriptive parameter names: {min}, {max}, {value}, {regexp}
 *    - Document expected parameters in comments
 *
 * 5. Performance:
 *    - Use caching locators for frequently accessed bundles
 *    - Preload bundles for known locales at startup
 *    - Avoid complex bundle hierarchies for simple applications
 */

// Example bundle structure:

// ValidationMessages.properties (defaults)
// jakarta.validation.constraints.NotNull.message=must not be null
// jakarta.validation.constraints.Size.message=size must be between {min} and {max}

// ApplicationMessages.properties (overrides)
// jakarta.validation.constraints.NotNull.message=This field is required
// user.email.invalid=Please provide a valid email address
// user.password.weak=Password must contain at least 8 characters with letters and numbers

// ModuleMessages.properties (module-specific)
// order.total.negative=Order total cannot be negative
// order.items.empty=Order must contain at least one item
// order.discount.invalid=Discount percentage must be between 0 and 100

// ValidationMessages_fr.properties (French)
// jakarta.validation.constraints.NotNull.message=ne doit pas être null
// user.email.invalid=Veuillez fournir une adresse email valide

// Usage
ResourceBundleLocator appLocator = new PlatformResourceBundleLocator("ApplicationMessages");
ResourceBundleLocator moduleLocator = new PlatformResourceBundleLocator("ModuleMessages");
ResourceBundleLocator defaultLocator = new PlatformResourceBundleLocator("ValidationMessages");

AggregateResourceBundleLocator aggregateLocator = new AggregateResourceBundleLocator(
    Arrays.asList(appLocator, moduleLocator, defaultLocator)
);

CachingResourceBundleLocator cachingLocator = new CachingResourceBundleLocator(aggregateLocator);

MessageInterpolator interpolator = new ResourceBundleMessageInterpolator(cachingLocator);

Install with Tessl CLI

npx tessl i tessl/maven-org-hibernate-validator--hibernate-validator

docs

configuration.md

constraint-validation.md

constraints.md

index.md

message-interpolation.md

path-navigation.md

programmatic-config.md

resource-loading.md

spi.md

tile.json