-
SpEL Error with @Value
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
Code:
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;
}
}
ConfigurableSizeValidator.java - This is the fixed class
Code:
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();
}
}
ConfigurableSizeConfiguration.java - the supporting configuration object
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