@Autowired bean null in ConstraintValidator when calling Sessionfactory.getCurrentSession.merge

I just implemented Bean Validation with Hibernate.

If I call the validator explicitly, it works as expected, and my @Autowired DAO Bean, which connects to the database, is entered as expected.

Earlier, I discovered that I needed to add instructions below before working on it would work. I used @Autowired beans extensively, but the following instruction was necessary to control the validator using Spring and Bean introduced in ConstraintValidator.

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

However, when the validator is called automatically during SessionFactory.getCurrentSession.merge, the Bean is null.

The fact that it works, if I call the validator directly with javax.Validation.validate, makes me think that I configured Spring correctly.

I read the number for messages in which people were unable to get the DAO Bean @Autowired, but in my case this happens, except when called during a merge.

The output below shows that the validator is called directly first, and then called as a result of the merge operation.

 07.12.2011 01:58:13 INFO [http-8080-1] (FileTypeAndClassValidator:isValid) - Validating ... 07.12.2011 01:58:13 INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=className, returnValue=com.twoh.dto.PurchaseOrder 07.12.2011 01:58:13 INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=fileTypeId, returnValue=4 07.12.2011 01:58:13 INFO [http-8080-1] (QueryUtil:createHQLQuery) - select ft.id from FileType ft where ft.id = :fileTypeId and ft.fileClassName = :fileClassName 07.12.2011 01:58:13 INFO [http-8080-1] (BaseDAO:merge) - Entity: com.twoh.dto.PurchaseOrder: 1036. 07.12.2011 01:58:13 INFO [http-8080-1] (FileTypeAndClassValidator:isValid) - Validating ... 07.12.2011 01:58:13 INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=className, returnValue=com.twoh.dto.PurchaseOrder 07.12.2011 01:58:13 INFO [http-8080-1] (ConstraintValidatorHelper:getPropertyValue) - propertyName=fileTypeId, returnValue=4 07.12.2011 01:58:13 INFO [http-8080-1] (FileTypeAndClassValidator:isValid) - java.lang.NullPointerException 

The following is the code for ConstraintValidator:

 package com.twoh.dto.ConstraintValidation; import javax.validation.ConstraintValidator; import javax.validation.ConstraintValidatorContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import com.twoh.dao.IQueryUtil; @Component public class FileTypeAndClassValidator implements ConstraintValidator<FileTypeAndClass, Object> { private Log logger = LogFactory.getLog(this.getClass()); private String fileClassProperty; private String fileTypeProperty; @Autowired private IQueryUtil queryUtil; public void initialize(FileTypeAndClass constraintAnnotation) { this.fileClassProperty = constraintAnnotation.fileClassProperty(); this.fileTypeProperty = constraintAnnotation.fileTypeProperty(); } public boolean isValid(Object object, ConstraintValidatorContext constraintValidatorContext) { boolean result = true; logger.info("Validating ..."); if (object == null) { result = false; } else { try { String fileClassName = ConstraintValidatorHelper.getPropertyValue(String.class, fileClassProperty, object); Integer fileTypeId = ConstraintValidatorHelper.getPropertyValue(Integer.class, fileTypeProperty, object); result = queryUtil.createHQLQuery(( "select ft.id" + " from FileType ft" + " where ft.id = :fileTypeId" + " and ft.fileClassName = :fileClassName" )) .setParameter("fileTypeId", fileTypeId) .setParameter("fileClassName", fileClassName) .iterate().hasNext(); } catch (Exception e) { logger.info(e); } } return result; } } 
+1
source share
2 answers

Well, after about 18 hours, Google finally came across a site that both described problems that had a solution. Recipe: Using event-based validation in Hibernate using custom JSR-303 validators and Spring auto-firmware

In my current project, we wanted to create a custom validator that checks to see if an existing email address already exists in the database before saving any instance of our contact object using Hibernate. This validator needed to enter a DAO to check for an email address in the database. To our surprise, we thought the wind would be more like a storm. Spring injection didn’t work at all when our bean was tested in the context of the Hibernates event-based check (in our case, the pre-insert event).

In the end, my Spring configuration ended up as follows:

 ... <bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean" /> <bean id="beanValidationEventListener" class="org.hibernate.cfg.beanvalidation.BeanValidationEventListener"> <constructor-arg ref="validator"/> <constructor-arg ref="hibernateProperties"/> </bean> ... <util:properties id="hibernateProperties" location="classpath:hibernate.properties"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="myDataSource" /> <property name="packagesToScan" value="com.twoh" /> <property name="hibernateProperties" ref="hibernateProperties"/> <property name="eventListeners"> <map> <entry key="pre-insert" value-ref="beanValidationEventListener" /> <entry key="pre-update" value-ref="beanValidationEventListener" /> </map> </property> </bean> 
+6
source

You can use the following method provided by the Spring framework since version 2.5.1

 SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); 

it is much cleaner since you do not need to set any listener / property in your application.

The code will look like this:

 public class ValidUniqueUserEmailValidator implements ConstraintValidator<ValidUniqueUserEmail, Object>, Serializable { private static final long serialVersionUID = 1L; @Autowired private UserDAO userDAO; @Override public void initialize(ValidUniqueUserEmail constraintAnnotation) { SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this); } @Override public boolean isValid(Object value, ConstraintValidatorContext context) { boolean isValid = true; if (value instanceof String) { String email = value.toString(); if (email == null || email.equals("")) { isValid = false; }else{ User user = new User(); user.setEmail(email); isValid = (userDAO.countByEmail(user) > 0); } } return isValid; } } 

Hope it helps you guys

+4
source

All Articles