5

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

10
  • Are you using Spring Framework, right? Add it to the tags, please. Commented Dec 9, 2015 at 21:36
  • Looks like sessionFactory is null and it wasn't auto wired. Commented Dec 9, 2015 at 21:42
  • I don't know if it's null because the exception comes before my logger.. But, if sessionFactory is null, it means that is null also when trying to validate a correct value, right? But i'm not getting the exception in that case... PS i added the tag, thanks Commented Dec 9, 2015 at 21:49
  • added a correct log, sessionFactory is not null... Commented Dec 9, 2015 at 21:57
  • please debug your code and check where the nullpointer exception occurs. Commented Dec 10, 2015 at 9:40

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

Comments

0

By this line:

it.besmart.validator.UniqueConstraintValidator.getSession(UniqueConstraintValidator.java:27)

it is saying that getSession() throws a NPE. I guess getSession(), if is the line 27, does not find sessionFactory. @Autowired is not working here.

And, I actually doubt the decision of mixing the validator with business logic; the validator should return true when the incoming value is good, and false if is bad; nothing more. You should not make it @Transactional and saving things into DB. No, code smell against SRP.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.