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