Reputation: 7301
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?
Upvotes: 8
Views: 3267
Reputation: 144
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" );
}
}
}
Upvotes: 7