views:

162

answers:

1

I'm writing a web app with Java & Spring 2.5.6 and using annotations for bean validation. I can get the basic annotation validation working fine, and Spring will even call a custom Validator declared with @Validator on the target bean. But it always instantiates a brand new Validator object to do it. This is bad because the new validator has none of the injected dependencies it needs to run, and so it throws a null pointer exception on validate. I need one of two things and I don't know how to do either.

  1. Convince Spring to use the validator I have already configured.
  2. Convince Spring to honor the @Autowired annotations when it creates the new validator.

The validator has the @Component annotation, like this.

@Component
public class AccessCodeBeanValidator implements Validator {
    @Autowired
    private MessageSource messageSource;

Spring finds the validator in the component scan, injects the autowired dependencies, but then ignores it and creates a new one at validation time.

The only thing that I can do at the moment is add a validator reference into the controller for each validator object and use that ref directly, instead of relying on the bean validation framework to call the validator for me. It looks like this.

// first validate via the annotations on the bean
beanValidator.validate(accessCodeBean, result);
// then validate using the specific validator class
acbValidator.validate(accessCodeBean, result);
if (result.hasErrors()) {

If anyone knows how to convince spring to use the existing validator, instead of creating a new one, or how to make it do the autowiring when it creates a new one, I'd love to know.

Edit:
Here is the code that tells spring what validator to use for the bean.

@Validator(AccessCodeBeanValidator.class)
public class AccessCodeBean {

It works, but is limited as described above.
And so, currently, I have the @Validator line commented out and instead I'm autowiring the validator to the controller like this.

@Resource(name="accessCodeBeanValidator")
public void setAcbValidator(Validator acbValidator) {
    this.acbValidator = acbValidator;
}
+1  A: 

I suspect that you are just hitting a limitation of the module rather than a limitation of your usage. Can you show the code (annotation) that is attaching the validator to your controller?

jsight
I was thinking that might be the case, but it's a pretty large omission, don't you think? There are *many* cases where you need to validate against something in the database, or with a previously extant resource. I was hoping the developers had thought more carefully about it.
GMK
Yes, I agree, its a strange omission. I'm just thinking that if it was their intent for these to be Spring Beans, that they would have given some different options for lookup them up (eg, bean name) instead of just lookup by class. I'm not 100% sure though, since I haven't tried looking at their code.
jsight