I'have been fighting with this for days, I've read all the discussions here but with no solution...
I have a custom constraint..
Unique.java
@Target({FIELD, METHOD})
@Retention(RUNTIME)
@Constraint(validatedBy = UniqueConstraintValidator.class)
public @interface Unique {
String message() default "{src.main.resources}";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
String property() default "id";
Class<?> entity();
}
This is used by UniqueConstraintValidator.java
@Transactional
public class UniqueConstraintValidator implements ConstraintValidator<Unique, Serializable> {
private static final Logger logger = Logger.getLogger(UniqueConstraintValidator.class);
Session session;
@Autowired
private SessionFactory sessionFactory;
protected Session getSession(){
return sessionFactory.getCurrentSession();
}
private Class<?> entityClass;
private String uniqueField;
public void initialize(Unique unique) {
entityClass = unique.entity();
uniqueField = unique.property();
}
@SuppressWarnings("rawtypes")
public boolean isValid(Serializable property, ConstraintValidatorContext cvContext) {
String query = String.format("from %s where %s = :field ", entityClass.getName(), uniqueField);
List list = getSession().createQuery(query).setParameter("field", property).list();
return list != null && list.size() == 0;
}
}
Now, my model has this annotation where I need to validate the uniqueness of the field
@NotNull
@Unique(entity = Luce.class, property="numeroLuce")
@Column(name="numero_luce")
public int getNumeroLuce() {
return numeroLuce;
}
public void setNumeroLuce(int numeroLuce) {
this.numeroLuce = numeroLuce;
}
Now, i know the custom annotation won't work while updating an existing object, but now i need to understand how it works. Let's assume we want to add a new object.
When I try to save an already existing value, I got a correct validation error but if I want to save a valid object i got a java.lang.NullPointerException
EDITED this is the full stacktrace
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is javax.validation.ValidationException: HV000028: Unexpected exception during isValid call.
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
javax.validation.ValidationException: HV000028: Unexpected exception during isValid call.
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:286)
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:133)
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:91)
org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:83)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:547)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:487)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:451)
org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:403)
org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:206)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:137)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:95)
org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:214)
org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:92)
org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:490)
org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:195)
org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:179)
org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:214)
org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
it.besmart.dao.AbstractDao.persist(AbstractDao.java:37)
it.besmart.dao.LuceDaoImpl.saveLuci(LuceDaoImpl.java:33)
it.besmart.service.LuceServiceImpl.saveLuci(LuceServiceImpl.java:33)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:497)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
com.sun.proxy.$Proxy48.saveLuci(Unknown Source)
it.besmart.controller.LuceController.saveLight(LuceController.java:87)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:497)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
root cause
java.lang.NullPointerException
it.besmart.validator.UniqueConstraintValidator.getSession(UniqueConstraintValidator.java:27)
it.besmart.validator.UniqueConstraintValidator.isValid(UniqueConstraintValidator.java:44)
it.besmart.validator.UniqueConstraintValidator.isValid(UniqueConstraintValidator.java:18)
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:283)
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:133)
org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateConstraints(ConstraintTree.java:91)
org.hibernate.validator.internal.metadata.core.MetaConstraint.validateConstraint(MetaConstraint.java:83)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraint(ValidatorImpl.java:547)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForDefaultGroup(ValidatorImpl.java:487)
org.hibernate.validator.internal.engine.ValidatorImpl.validateConstraintsForCurrentGroup(ValidatorImpl.java:451)
org.hibernate.validator.internal.engine.ValidatorImpl.validateInContext(ValidatorImpl.java:403)
org.hibernate.validator.internal.engine.ValidatorImpl.validate(ValidatorImpl.java:206)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:137)
org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:95)
org.hibernate.action.internal.EntityIdentityInsertAction.preInsert(EntityIdentityInsertAction.java:214)
org.hibernate.action.internal.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:92)
org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:490)
org.hibernate.engine.spi.ActionQueue.addResolvedEntityInsertAction(ActionQueue.java:195)
org.hibernate.engine.spi.ActionQueue.addInsertAction(ActionQueue.java:179)
org.hibernate.engine.spi.ActionQueue.addAction(ActionQueue.java:214)
org.hibernate.event.internal.AbstractSaveEventListener.addInsertAction(AbstractSaveEventListener.java:324)
org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:194)
org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:125)
org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:206)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:149)
org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75)
org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784)
org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789)
it.besmart.dao.AbstractDao.persist(AbstractDao.java:37)
it.besmart.dao.LuceDaoImpl.saveLuci(LuceDaoImpl.java:33)
it.besmart.service.LuceServiceImpl.saveLuci(LuceServiceImpl.java:33)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:497)
org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:302)
org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:208)
com.sun.proxy.$Proxy48.saveLuci(Unknown Source)
it.besmart.controller.LuceController.saveLight(LuceController.java:87)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:497)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
I really cannot understand what I'm doing wrong, i know i'm a java noob, but everything looks to me correct.
I added a log in UniqueConstraintValidator to check if sessionFactory is null, but i'm getting
Session is org.hibernate.internal.SessionFactoryImpl@53911200
so, it's not null...
Thanks in advance
In this comment You will find answer.
JSR303 custom validators being called twice
First you validate object by spring when is create by form, and second time by hibernate before persistence (it's default behavior). As I understood hibernate make validation outside Spring context so Autowired doesn't work. That is why you get NullPointerException.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With