All-
I am trying to implement configurable constraints on my domain model using JSR-303 Beans Validation annotations and Spring's @Value annotations. This allows me to configure my validation constraints via a properties file.
When I try to use the @Value annotation on an instance field within my ConstraintValidator I get an error message (full message below) having to do with autowiring a field and the evaluation of an SpEL expression. If I pull the @Value annotations into a separate class and inject that object into my ConstraintValidator it works just fine. I'd like to avoid the extra class if possible.
Can somone explain the error message below? Am I using @Value improperly? Am I headed down the wrong path for configurable validation?
The relevant classes are below. The full, Mavenized projects are posted here:
http://www.rationalpi.com/spring/Con...tionBroken.zip
http://www.rationalpi.com/spring/Con...ionWorking.zip
Thanks,
Joshua Smith
ConfigurableSizeValidator.java - JSR-303 custom ConstraintValidator - This is the problem class
ConfigurableSizeValidator.java - This is the fixed classCode:package ex.validation; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; @Configuration @ImportResource("classpath:/properties-config.xml") public class ConfigurableSizeValidator implements ConstraintValidator<ConfigurableSize, String> { private @Value("#{validation['configurable.size.max']}") int max; // <--------the problem @Override public void initialize(ConfigurableSize configurableSize) {} @Override public boolean isValid(String field, ConstraintValidatorContext context) { if (field == null) { return false; } return field.length() <= max; } }
ConfigurableSizeConfiguration.java - the supporting configuration objectCode:package ex.validation; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.springframework.beans.factory.annotation.Autowired; public class ConfigurableSizeValidator implements ConstraintValidator<ConfigurableSize, String> { @Autowired(required=true) private ConfigurableSizeConfiguration configurableSizeConfiguration; // <-- the separate bean fix @Override public void initialize(ConfigurableSize configurableSize) {} @Override public boolean isValid(String field, ConstraintValidatorContext context) { if (field == null) { return false; } return field.length() <= configurableSizeConfiguration.getMax(); } }
Code:package ex.validation; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; @Configuration @ImportResource("classpath:/properties-config.xml") public class ConfigurableSizeConfiguration { private @Value("#{validation['configurable.size.max']}") int max; // <-- works fine public int getMax() { return max; } }
The Error Message
Code:Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'ex.validation.ConfigurableSizeValidator': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private int ex.validation.ConfigurableSizeValidator.max; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'validation' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:286) at org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory.getInstance(SpringConstraintValidatorFactory.java:50) at org.hibernate.validator.engine.ConstraintTree.createAndInitializeValidator(ConstraintTree.java:204) at org.hibernate.validator.engine.ConstraintTree.getInitializedValidator(ConstraintTree.java:183) at org.hibernate.validator.engine.ConstraintTree.validateConstraints(ConstraintTree.java:135) at org.hibernate.validator.metadata.MetaConstraint.validateConstraint(MetaConstraint.java:121) at org.hibernate.validator.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:327) at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForRedefinedDefaultGroup(ValidatorImpl.java:273) at org.hibernate.validator.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:256) at org.hibernate.validator.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:210) at org.hibernate.validator.engine.ValidatorImpl.validate(ValidatorImpl.java:119) at org.springframework.validation.beanvalidation.SpringValidatorAdapter.validate(SpringValidatorAdapter.java:145) at ex.RecordValidator.validate(RecordValidator.java:18) at ex.Main.main(Main.java:14) Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private int ex.validation.ConfigurableSizeValidator.max; nested exception is org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'validation' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:502) at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:282) ... 17 more Caused by: org.springframework.beans.factory.BeanExpressionException: Expression parsing failed; nested exception is org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'validation' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:141) at org.springframework.beans.factory.support.AbstractBeanFactory.evaluateBeanDefinitionString(AbstractBeanFactory.java:1287) at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:715) at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:703) at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:474) ... 19 more Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1008E:(pos 0): Field or property 'validation' cannot be found on object of type 'org.springframework.beans.factory.config.BeanExpressionContext' at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:207) at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:71) at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:52) at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93) at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:88) at org.springframework.context.expression.StandardBeanExpressionResolver.evaluate(StandardBeanExpressionResolver.java:138) ... 23 more


Reply With Quote
