Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple @ConfigurationProperties validator beans in Spring environment

When using the @ConfigurationProperties annotation to inject properties into a bean, Spring provides the ability to define a custom validator to validate those properties.

The ConfigurationPropertiesBindingPostProcessor looks up this validator using the fixed bean name "configurationPropertiesValidator" and class org.springframework.validation.Validator.

Now assume I have a @ConfigurationProperties with its validator in a module A. Another module B has a dependency on module A. Module B also defines its own @ConfigurationProperties and its own validator.

When the app loads up, the post-processor picks up only one of these beans. This disables the other part of the validation.

Is there a solution to this? How can I keep both configuration property validators enabled in my application?

like image 630
metacubed Avatar asked Nov 21 '15 02:11

metacubed


1 Answers

I just encountered the same problem and realized that ConfigurationPropertiesBindingPostProcessor verifies if the class annotated with @ConfigurationProperties implements the Validator interface itself. (see org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor#determineValidator)

So the solution is to move all property validation to the annotated property class:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

@ConfigurationProperties("test.properties")
@Component
public class TestProperties implements Validator {

    private String myProp;

    public String getMyProp()
    {
        return myProp;
    }

    public void setMyProp( String myProp )
    {
        this.myProp = myProp;
    }

    public boolean supports( Class<?> clazz )
    {
        return clazz == TestProperties.class;
    }

    public void validate( Object target, Errors errors )
    {
        ValidationUtils.rejectIfEmpty( errors, "myProp", "myProp.empty" );

        TestProperties properties = (TestProperties) target;

        if ( !"validThing".equals( properties.getMyProp() ) ) {
            errors.rejectValue( "myProp", "Not a valid thing" );
        } 
    }
}
like image 50
Alexandre H. Avatar answered Nov 14 '22 21:11

Alexandre H.