[hibernate-issues] [Hibernate-JIRA] Created: (HV-138) JPAValidateListener checks @NotNull fields that are filled after the @PrePersist call

Julien Kronegg (JIRA) noreply at atlassian.com
Mon Apr 6 08:54:39 EDT 2009


JPAValidateListener checks @NotNull fields that are filled after the @PrePersist call
-------------------------------------------------------------------------------------

                 Key: HV-138
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HV-138
             Project: Hibernate Validator
          Issue Type: Bug
    Affects Versions: 3.1.0.GA
         Environment: Hibernate 3.3.1.GA, Hibernate annotations 3.4.0.GA, Hibernate entity manager 3.4.0.GA, POJO annotated entities, DB2
            Reporter: Julien Kronegg


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).

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        



More information about the hibernate-issues mailing list