org.hibernate.validator.InvalidStateException: validation failed for : my.package.A

Hibernate JIRA | Julien Kronegg | 8 years ago
tip
Your exception is missing from the Samebug knowledge base.
Here are the best solutions we found on the Internet.
Click on the to mark the helpful solution and get rewards for you help.
  1. 0

    According to Hibernate validation documentation ( http://www.hibernate.org/hib_docs/validator/reference/en/html_single/#validator-checkconstraints-orm-jpaevent ) we can annotate an entity with @EntityListeners({JPAValidateListener.class}) to validate the fields using the @PrePersist / @PreUpdate JPA events handlers. I tryied with the following entity: @Entity @Table(...) @EntityListeners({JPAValidateListener.class}) public class A { private int id; private String text; @Id @Column(...) @NotNull @GeneratedValue(...) @GenericGenerator(...) public int getId() { return id; } public void setId(int id) { this.id=id; } ... } Problem is that the @PrePersist event is raised before some fields are automatically filled (e.g. @Id annotated). So the JPAValidateListener raises an exception saying that the identifier cannot be null. The exception root cause detail is (InvalidState: id cannot be null) and the stacktrace is: org.hibernate.validator.InvalidStateException: validation failed for : my.package.A at org.hibernate.validator.ClassValidator.assertValid(ClassValidator.java:666) at org.hibernate.validator.event.JPAValidateListener.onChange(JPAValidateListener.java:62) ...// some reflection StacktraceElement at org.hibernate.ejb.event.ListenerCallback.invoke(ListenerCallback.java:31) at org.hibernate.ejb.event.EntityCallbackHandler.callback(EntityCallbackHandler.java:80) at org.hibernate.ejb.event.EntityCallbackHandler.preCreate(EntityCallbackHandler.java:49) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:48) at org.hibernate.event.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:154) at org.hibernate.event.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:110) at org.hibernate.event.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:645) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:619) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:623) ... The EJB3PersistEventListener.saveWithGeneratedId() method looks like: protected Serializable saveWithGeneratedId(...) { callbackHandler.preCreate(entity); // raises the @PrePersist JPA event return super.saveWithGeneratedId(...); // sets the identifier } Thus, the JPAValidateListener validates the whole Entity and does not take the entity lifecycle into account. The JPAValidateListener should check all fields except the ones which are known to be modified/setled after the call to the validator. This may also be the case for other generated fields such as the ones annotated with @Version (I did not check that).

    Hibernate JIRA | 8 years ago | Julien Kronegg
    org.hibernate.validator.InvalidStateException: validation failed for : my.package.A
  2. 0

    According to Hibernate validation documentation ( http://www.hibernate.org/hib_docs/validator/reference/en/html_single/#validator-checkconstraints-orm-jpaevent ) we can annotate an entity with @EntityListeners({JPAValidateListener.class}) to validate the fields using the @PrePersist / @PreUpdate JPA events handlers. I tryied with the following entity: @Entity @Table(...) @EntityListeners({JPAValidateListener.class}) public class A { private int id; private String text; @Id @Column(...) @NotNull @GeneratedValue(...) @GenericGenerator(...) public int getId() { return id; } public void setId(int id) { this.id=id; } ... } Problem is that the @PrePersist event is raised before some fields are automatically filled (e.g. @Id annotated). So the JPAValidateListener raises an exception saying that the identifier cannot be null. The exception root cause detail is (InvalidState: id cannot be null) and the stacktrace is: org.hibernate.validator.InvalidStateException: validation failed for : my.package.A at org.hibernate.validator.ClassValidator.assertValid(ClassValidator.java:666) at org.hibernate.validator.event.JPAValidateListener.onChange(JPAValidateListener.java:62) ...// some reflection StacktraceElement at org.hibernate.ejb.event.ListenerCallback.invoke(ListenerCallback.java:31) at org.hibernate.ejb.event.EntityCallbackHandler.callback(EntityCallbackHandler.java:80) at org.hibernate.ejb.event.EntityCallbackHandler.preCreate(EntityCallbackHandler.java:49) at org.hibernate.ejb.event.EJB3PersistEventListener.saveWithGeneratedId(EJB3PersistEventListener.java:48) at org.hibernate.event.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:154) at org.hibernate.event.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:110) at org.hibernate.event.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:61) at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:645) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:619) at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:623) ... The EJB3PersistEventListener.saveWithGeneratedId() method looks like: protected Serializable saveWithGeneratedId(...) { callbackHandler.preCreate(entity); // raises the @PrePersist JPA event return super.saveWithGeneratedId(...); // sets the identifier } Thus, the JPAValidateListener validates the whole Entity and does not take the entity lifecycle into account. The JPAValidateListener should check all fields except the ones which are known to be modified/setled after the call to the validator. This may also be the case for other generated fields such as the ones annotated with @Version (I did not check that).

    Hibernate JIRA | 8 years ago | Julien Kronegg
    org.hibernate.validator.InvalidStateException: validation failed for : my.package.A

    Root Cause Analysis

    1. org.hibernate.validator.InvalidStateException

      validation failed for : my.package.A

      at org.hibernate.validator.ClassValidator.assertValid()
    2. Hibernate Validator Engine
      ClassValidator.assertValid
      1. org.hibernate.validator.ClassValidator.assertValid(ClassValidator.java:666)
      1 frame
    3. org.hibernate.validator
      JPAValidateListener.onChange
      1. org.hibernate.validator.event.JPAValidateListener.onChange(JPAValidateListener.java:62)
      1 frame