views:

437

answers:

2

Spring 3.0.2, Hibernate 3.5.0, Hibernate-Validator 4.0.2.GA

I am trying to inject Spring dependencies into a ConstraintValidator using:

@PersistenceContext
private EntityManager entityManager;

I have configured the application context with:

<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

Which, according to the Spring documentation, should allow “custom ConstraintValidators to benefit from dependency injection like any other Spring bean”

Within the debugger I can see Spring calling getBean to create the ConstraintValidator. Later when flush triggers the preInsert, a different ConstraintValidator is created and called. The problem is the EntityManager is null within this new ConstraintValidator. I’ve tried injecting other dependencies within the ConstraintValidator and these are always null.

Does anyone know if it is possible to inject dependencies into a ConstraintValidator?

A: 

It seems that in JPA2, the persistence provider's validation mechanism kicks in by default on pre-persist, pre-update, etc.

It uses its own mechanism for constructing validators, Spring doesn't get involved.

The only solution I can see at the moment is disabling the out-of-the-box JPA2 validation in persistence.xml:

<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
  <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <properties>
      <property name="hibernate.show_sql" value="true"/>
      <!-- other props -->
    </properties>
  <validation-mode>NONE</validation-mode>
</persistence-unit>

Then use Spring's LocalValidatiorFactoryBean as usual. You'll then have to call the validators manually as in the pre-JPA2 world.

UPDATE:

Just to make it complete, another solution would be to specify a constraint-validator-factory in META-INF/validation.xml.

It would be very nice if this could be Spring's SpringConstraintValidatorFactory but unfortunately, it requires an AutowireCapableBeanFactory to be passed into its constructor, but a class with no-arg constructor is expected here by JPA2.

Which leaves the option of creating own implementation of ConstraintValidatorFactory that pulls validators out of Spring, but I don't see any clean way of doing that.

Michal Bachman
A: 

There is also the option to pass the ValidatorFactory as property to the entity manager creation using the property javax.persistence.validation.factory. If there is a ValidatorFactory instance stored under this property, the entity manager uses this validator factory instead of creating a new one.

Hardy