DeejUK
DeejUK

Reputation: 13471

JSR-303 Annotation on Spring Bean Properties

Is there a straightforward way to have Spring beans validated on context startup using JSR-303 annotations? I've inherited some classes that represent configuration as JSR-303-annotated POJOs. These are passed all around an object hierarchy, so I'm kinda stuck using them.

I could imagine defining beans setting the properties of such a class, and then having a JSR-303 validator run on context startup that would ensure all values are set correctly.

Note that I'm not asking about validation of bound form submissions in Spring MVC.

Upvotes: 1

Views: 578

Answers (2)

sinuhepop
sinuhepop

Reputation: 20297

If you want to do this validation just after context initialization, you could do something like:

@Component
public class MyValidator ApplicationListener<ContextRefreshedEvent> {

    @Autowired private ListableBeanFactory bf;
    @Autowired private Validator validator;


    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        for (String name : bf.getBeanDefinitionNames()) {
            Object bean = bf.getBean(name);
            validator.validate(bean);
        }
    }
}

But I haven't tested it.

Upvotes: 2

nobeh
nobeh

Reputation: 10039

Short answer is no. Although not originally mentioned in JSR-303 it is typically used for MVC data binding and validation. I would try the following.

Since you have JSR-303 annotations, so configure a JSR-303 validator in Spring context. In this case, it will be a LocalValidatorFactoryBean that bootstraps a standard JSR-303 validation mechanism. Note that you still need to have a vendor/implementor of JSR-303 available in your class path (e.g. Hibernate Validator).

Implement an instance of ApplicationContextListener<ContextStartedEvent> to receive the event when the application context is started and ready. Also, allow the bean to receive an instance of LocalValidatorFactoryBean:

public class GenericApplicationValidator implements ApplicationListener<ContextStartedEvent> {

  private ValidatorFactoryBean validatorFactoryBean;

  public void onApplicationEvent(ContextStartedEvent e) {
    // Refer to next step
  }

  public void setValidatorFactoryBean(ValidatorFactoryBean vfb) {
    this.validatorFactoryBean = vfb;
  }
}

In the method onApplicationEvent(ContextStartedEvent e):

  1. Fetch the instance of application context.
  2. Through the application context, find all the beans you need to validate.
  3. You have access to validatorFactoryBean.getValidator()
  4. Iterate over all the beans, use the validator and validate the bean.

Remember that I have not had an experience on doing this. But it looks to me it can be one way to get close to achieve what you need.

Upvotes: 1

Related Questions