[
http://opensource.atlassian.com/projects/hibernate/browse/HV-138?page=com...
]
Julien Kronegg commented on HV-138:
-----------------------------------
The same problem occurs when using an OpenJPA persistence provider version 1.2.1. In this
case, 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.apache.openjpa.event.BeanLifecycleCallbacks.makeCallback(BeanLifecycleCallbacks.java:85)
at
org.apache.openjpa.event.LifecycleEventManager.makeCallbacks(LifecycleEventManager.java:340)
at
org.apache.openjpa.event.LifecycleEventManager.fireEvent(LifecycleEventManager.java:302)
at org.apache.openjpa.kernel.fireLifecycleEvent(BrokerImpl.java:688)
at org.apache.openjpa.kernel.persist(BrokerImpl.java:2428)
... // cutted down some OpenJPA StacktraceElements
at
org.apache.openjpa.persistence.EntityManagerImpl.persist(EntityManagerImpl.java:645)
The BrokerImpl.persist (around line 2428) is:
fireLifecycleEvent(..., LifecycleEvent.BEFORE_PERSIST); // raises the @PrePersist JPA
event
if (id==null) {
... // sets the identifier
}
Consequently, the issue is the same for both Hibernate and OpenJPA persistence providers.
AFAIK, the JPA specification does not give guidelines on when must be @PrePersist event
raised. Thus, both providers implementation may be considered as correct, which confirms
that the issue should be in the Hibernate Validator.
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
Original Estimate: 2 days
Remaining Estimate: 2 days
According to Hibernate validation documentation (
http://www.hibernate.org/hib_docs/validator/reference/en/html_single/#val...
) 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....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira