1

The hibernate validations documentation describes how to create ConstraintMappingContributors here.

It states:

You then need to specify the fully-qualified class name of the contributor implementation in META-INF/validation.xml, using the property key hibernate.validator.constraint_mapping_contributors. You can specify several contributors by separating them with a comma.

Given I have many of these, what would be the most appropriate way to auto-discover these i.e. via @Component and add them dynamically at runtime to the ConstrainMappingConfiguration during Spring Boot startup.

For example.. if a developer creates a new ConstraintMappingContributor, it should be picked up and added automatically when spring boot starts, requiring no other file changes.

1 Answer 1

3

This is what I came up with, seems to be working for me.

package...
import org.hibernate.validator.spi.cfg.ConstraintMappingContributor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Configuration
public class ValidationConfiguration {

    private final List<ConstraintMappingContributor> contributors;
    public ValidationConfiguration(Optional<List<ConstraintMappingContributor>> contributors) {
        this.contributors = contributors.orElseGet(ArrayList::new);
    }

    @Bean
    public LocalValidatorFactoryBean validatorFactory() {
        return new ValidatorFactoryBean(this.contributors);
    }
}



package...
import org.hibernate.validator.HibernateValidatorConfiguration;
import org.hibernate.validator.internal.cfg.context.DefaultConstraintMapping;
import org.hibernate.validator.spi.cfg.ConstraintMappingContributor;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

import javax.validation.Configuration;
import java.util.List;

public class ValidatorFactoryBean extends LocalValidatorFactoryBean {

    private final List<ConstraintMappingContributor> contributors;

    ValidatorFactoryBean(List<ConstraintMappingContributor> contributors) {
        this.contributors = contributors;
    }

    @Override
    protected void postProcessConfiguration(Configuration<?> cfg) {
        if (cfg instanceof HibernateValidatorConfiguration) {
            HibernateValidatorConfiguration configuration = (HibernateValidatorConfiguration) cfg;
            this.contributors.forEach(contributor -> contributor.createConstraintMappings(() -> {
                DefaultConstraintMapping mapping = new DefaultConstraintMapping();
                configuration.addMapping(mapping);
                return mapping;
            }));
        }
    }
}

I invoke it like this...

if(SpringValidatorAdapter.class.isInstance(this.validatorFactory)){
    SpringValidatorAdapter.class.cast(this.validatorFactory).validate(entity, errors);
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.