persistence@glassfish.java.net

Re: PrePersist method not being called

From: Jon Miller <jemiller_at_uchicago.edu>
Date: Mon, 8 Jan 2007 12:00:51 -0600

Thanks Tom. Yeah, I have all the classes listed there now. It still isn't
working though. I just tried a simpler test with the PrePersist method in
the top level class and it worked. I'll have to look into it further...

Thanks for the info on weaving. I recently read about that. So far I just
been doing without it. I figure once I get further along I may need to
enable it if performance is an issue. One thing that I'm wondering about the
agent is: is it possible to somehow enable the agent programatically in the
program itself, or, does it have to be passed as a command-line argument?
I'm using TopLink with Tomcat and not using an EJB application server. I
like the idea of being able to deploy the web app self-contained without
having to make changes to the web server configuration such as passing
command-line arguments to the JVM.

Jon

----- Original Message -----
From: "Tom Ware" <tom.ware_at_oracle.com>
To: <persistence_at_glassfish.dev.java.net>
Sent: Monday, January 08, 2007 8:28 AM
Subject: Re: PrePersist method not being called


> Hi Jon,
>
> Are you still seeing the problem now that you have listed AuditObject in
> your persistence.xml?
>
> In Java SE, the JPA specification says that portable applications must
> list the classes that will be used in the persistence.xml either with
> <class> element, by referring to them in a file referenced by a
> <mapping-file> element, or by placing them in a file referenced by a
> <jar-file> element. As a result, in Java SE depending on how your
> persistence.xml looks, we may not automatically discover your classes.
>
> In some Java SE Environments TopLink Essentials will be able to
> auto-discover if you use the <exclude-unlisted-classes> element in your
> persistence.xml and set it to false.
>
> FYI: You have asked a couple of questions about the javaagent, so I'll
> give you an idea what the purpose of the agent is. In TopLink Essentials,
> we use the javaagent to dynamically weave classes that have OneToOne or
> ManyToOne mappings with FetchType LAZY. The weaving allows us to actually
> retrieve the elements referenced by those mappings in a LAZY manner. For
> those that do not wish to use the agent (or cannot use it), there is also
> the option of using a preprocessing step for this weaving. If you are
> interested in that step, take a look at the section of the following
> document entitled, "Static Weaving Using the StaticWeave Class on the
> Command Line":
>
> http://www.oracle.com/technology/products/ias/toplink/jpa/resources/toplink-jpa-extensions.html#LazyLoading
>
> -Tom
>
> Jon Miller wrote:
>
>>I thought I found what might have been the problem on my side. I wasn't
>>listing AuditObject in my persistence.xml. Initially, I was thinking that
>>you only would have to list the subclasses that you are using directly and
>>that it would automatically add in the superclasses for you. I found out
>>that this doesn't appear to be the case though (at least in standalone
>>mode). Another thing worth mentioning is that the AuditObject class is in
>>a different jar file. I'm not sure if that would make a difference or not.
>>There's only one persistence.xml, but, the classes are split between two
>>jar files.
>>
>>Jon
>>
>>----- Original Message -----
>>From: "Jon Miller" <jemiller_at_uchicago.edu>
>>To: <persistence_at_glassfish.dev.java.net>
>>Sent: Friday, January 05, 2007 6:13 PM
>>Subject: Re: PrePersist method not being called
>>
>>
>>
>>>OK, I tested it and it works with Hibernate, but, I receive the following
>>>error with TopLink. The prePersist method is supposed to be called which
>>>sets the lastWriteTime field. This isn't happening, so, it's causing an
>>>exception since that field is NOT NULL.
>>>
>>> [junit] Caused by: Exception [TOPLINK-4002] (Oracle TopLink
>>> Essentials - 9.1 (Build b30)): oracle.toplink.essentials
>>>.exceptions.DatabaseException
>>> [junit] Internal Exception: java.sql.SQLException:
>>> [SKATE\SQLEXPRESS]Cannot insert the value NULL into column 'LastW
>>>riteTime', table 'Schedules.dbo.Person'; column does not allow nulls.
>>>INSERT fails.Error Code: 515
>>> [junit] Call:INSERT INTO Person (Department, CreationUserName,
>>> FirstName, LastName, LastWriteTime, Name, LastWriteUs
>>>erName, MiddleName, TelephoneNumber, Title, CreationTime, Curriculum,
>>>Address, UserName, EmailAddress, Organization, Cla
>>>ss) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
>>> [junit] bind => [null, null, Jonathan, Miller, null, Jonathan Eric
>>> Miller, null, Eric, null, null, null, null, n
>>>ull, jemiller, null, null, Schedules.Persistence.Entity.User]
>>>
>>>Jon
>>>
>>>----- Original Message -----
>>>From: "Jon Miller" <jemiller_at_uchicago.edu>
>>>To: <persistence_at_glassfish.dev.java.net>
>>>Sent: Friday, January 05, 2007 5:47 PM
>>>Subject: Re: PrePersist method not being called
>>>
>>>
>>>
>>>>OK, I tested it with V2 build 30. It still isn't getting called. I'm not
>>>>using the agent at present. Would that matter? I'm wondering if the
>>>>problem is that the PrePersist method is in a MappedSuperclass? I think
>>>>that's a valid thing to do though. I think the Javadocs mention it if I
>>>>remember correctly. I'm going to test it again with Hibernate, just to
>>>>make sure I'm not doing something else wrong and that it does indeed
>>>>work with Hibernate and not TopLink.
>>>>
>>>>Jon
>>>>
>>>>----- Original Message -----
>>>>From: "Tom Ware" <tom.ware_at_oracle.com>
>>>>To: <persistence_at_glassfish.dev.java.net>
>>>>Sent: Thursday, January 04, 2007 2:10 PM
>>>>Subject: Re: PrePersist method not being called
>>>>
>>>>
>>>>
>>>>>Hi Jon,
>>>>>
>>>>> Do you see the same behavior on the latest builds of TopLink
>>>>> essentials (e.g. V2 build 30)? There have been quite a lot of changes
>>>>> since the end of August (060830).
>>>>>
>>>>> You can get the latest version at:
>>>>>
>>>>>https://glassfish.dev.java.net/downloads/persistence/JavaPersistence.html
>>>>>
>>>>>-Tom
>>>>>
>>>>>Jon Miller wrote:
>>>>>
>>>>>
>>>>>>Hi all,
>>>>>>
>>>>>>I'm using the version of Toplink Essentials that comes with NetBeans
>>>>>>5.5. I have a class which defines a PrePersist method
>>>>>>(AuditObject.prePersist()) which sets some values in an object (namely
>>>>>>a timestamp which is a NOT NULL value). I'm finding that this method
>>>>>>isn't being called when I attempt to persist an Item object (subclass
>>>>>>of AuditObject). It works fine if I use Hibernate's implementation of
>>>>>>JPA. Does anyone know what I might be doing wrong or if this is a
>>>>>>known issue? So far I haven't been using the javaagent. However, I
>>>>>>just tried it with the agent to see if that might be the problem, but,
>>>>>>it didn't make a difference. The following is the exception that I'm
>>>>>>receiving.
>>>>>>
>>>>>>Exception [TOPLINK-4002] (Oracle TopLink Essentials - 2006.8 (Build
>>>>>>060830)): oracle.toplink.essentials.exceptions.DatabaseException
>>>>>>Internal Exception: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot
>>>>>>insert the value NULL into column 'LastWriteTime', table
>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>fails.Error Code: 515
>>>>>>Call:INSERT INTO Item (Name, CreationUserName, Description,
>>>>>>LastWriteUserName, LastWriteTime, CreationTime) VALUES (?, ?, ?, ?, ?,
>>>>>>?)
>>>>>> bind => [testSaveItem Wed Jan 03 14:43:08 CST 2007, null,
>>>>>> Description, null, null, null]
>>>>>>Query:InsertObjectQuery([id = null, name = "testSaveItem Wed Jan 03
>>>>>>14:43:08 CST 2007", description = "Description"])
>>>>>>javax.persistence.RollbackException: Exception [TOPLINK-4002] (Oracle
>>>>>>TopLink Essentials - 2006.8 (Build 060830)):
>>>>>>oracle.toplink.essentials.exceptions.DatabaseException
>>>>>>Internal Exception: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot
>>>>>>insert the value NULL into column 'LastWriteTime', table
>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>fails.Error Code: 515
>>>>>>Call:INSERT INTO Item (Name, CreationUserName, Description,
>>>>>>LastWriteUserName, LastWriteTime, CreationTime) VALUES (?, ?, ?, ?, ?,
>>>>>>?)
>>>>>> bind => [testSaveItem Wed Jan 03 14:43:08 CST 2007, null,
>>>>>> Description, null, null, null]
>>>>>>Query:InsertObjectQuery([id = null, name = "testSaveItem Wed Jan 03
>>>>>>14:43:08 CST 2007", description = "Description"])
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:109)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.ejb.cmp3.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:45)
>>>>>> at
>>>>>> edu.uchicago.at.reservations.ReservationsService.saveItem(ReservationsService.java:254)
>>>>>> at
>>>>>> edu.uchicago.at.reservations.ReservationsServiceTest.testSaveGetAndRemoveItem(ReservationsServiceTest.java:44)
>>>>>>Caused by: Exception [TOPLINK-4002] (Oracle TopLink Essentials -
>>>>>>2006.8 (Build 060830)):
>>>>>>oracle.toplink.essentials.exceptions.DatabaseException
>>>>>>Internal Exception: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot
>>>>>>insert the value NULL into column 'LastWriteTime', table
>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT
>>>>>>fails.Error Code: 515
>>>>>>Call:INSERT INTO Item (Name, CreationUserName, Description,
>>>>>>LastWriteUserName, LastWriteTime, CreationTime) VALUES (?, ?, ?, ?, ?,
>>>>>>?)
>>>>>> bind => [testSaveItem Wed Jan 03 14:43:08 CST 2007, null,
>>>>>> Description, null, null, null]
>>>>>>Query:InsertObjectQuery([id = null, name = "testSaveItem Wed Jan 03
>>>>>>14:43:08 CST 2007", description = "Description"])
>>>>>> at
>>>>>> oracle.toplink.essentials.exceptions.DatabaseException.sqlException(DatabaseException.java:295)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:639)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:688)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:477)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:437)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.AbstractSession.executeCall(AbstractSession.java:675)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:213)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:199)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:331)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:176)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:190)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:457)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.InsertObjectQuery.executeCommit(InsertObjectQuery.java:74)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedWrite(DatabaseQueryMechanism.java:635)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.performUserDefinedInsert(DatabaseQueryMechanism.java:599)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.insertObjectForWriteWithChangeSet(DatabaseQueryMechanism.java:495)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.WriteObjectQuery.executeCommitWithChangeSet(WriteObjectQuery.java:130)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.queryframework.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:283)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:67)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:536)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:123)
>>>>>> at
>>>>>> oracle.toplink.essentials.queryframework.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:95)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2218)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:894)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:254)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:175)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:2638)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1030)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:357)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1112)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.ejb.cmp3.base.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:82)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:842)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.ejb.cmp3.transaction.base.EntityTransactionImpl.commit(EntityTransactionImpl.java:90)
>>>>>> ... 18 more
>>>>>>Caused by: java.sql.SQLException: [SKATE\SQLEXPRESS]Cannot insert the
>>>>>>value NULL into column 'LastWriteTime', table
>>>>>>'ReservationsDev.dbo.Item'; column does not allow nulls. INSERT fails.
>>>>>> at com.inet.tds.a.a(Unknown Source)
>>>>>> at com.inet.tds.c.new(Unknown Source)
>>>>>> at com.inet.tds.c.executeUpdate(Unknown Source)
>>>>>> at
>>>>>> oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:632)
>>>>>> ... 51 more
>>>>>>
>>>>>>// AuditObject.java
>>>>>>package edu.uchicago.at.common.persistence.entity;
>>>>>>
>>>>>>import java.io.Serializable;
>>>>>>import java.util.Date;
>>>>>>import java.util.logging.Logger;
>>>>>>import javax.persistence.Column;
>>>>>>import javax.persistence.MappedSuperclass;
>>>>>>import javax.persistence.PrePersist;
>>>>>>import javax.persistence.PreUpdate;
>>>>>>import javax.persistence.Temporal;
>>>>>>import javax.persistence.TemporalType;
>>>>>>
>>>>>>@MappedSuperclass
>>>>>>public abstract class AuditObject implements Serializable {
>>>>>> private Date creationTime;
>>>>>> private String creationUserName;
>>>>>> private Date lastWriteTime;
>>>>>> private String lastWriteUserName;
>>>>>> private static Logger logger = Logger.getLogger(
>>>>>> AuditObject.class.getName());
>>>>>>
>>>>>> @Column(name="CreationTime", nullable=false)
>>>>>> @Temporal(TemporalType.TIMESTAMP)
>>>>>> public Date getCreationTime() {
>>>>>> return creationTime;
>>>>>> }
>>>>>>
>>>>>> public void setCreationTime(Date creationTime) {
>>>>>> this.creationTime = creationTime;
>>>>>> }
>>>>>>
>>>>>> @Column(name="CreationUserName", columnDefinition="nvarchar(255)")
>>>>>> public String getCreationUserName() {
>>>>>> return creationUserName;
>>>>>> }
>>>>>>
>>>>>> public void setCreationUserName(String creationUserName) {
>>>>>> this.creationUserName = creationUserName;
>>>>>> }
>>>>>>
>>>>>> @Column(name="LastWriteTime", nullable=false)
>>>>>> @Temporal(TemporalType.TIMESTAMP)
>>>>>> public Date getLastWriteTime() {
>>>>>> return lastWriteTime;
>>>>>> }
>>>>>>
>>>>>> public void setLastWriteTime(Date lastWriteTime) {
>>>>>> this.lastWriteTime = lastWriteTime;
>>>>>> }
>>>>>>
>>>>>> @Column(name="LastWriteUserName", columnDefinition="nvarchar(255)")
>>>>>> public String getLastWriteUserName() {
>>>>>> return lastWriteUserName;
>>>>>> }
>>>>>>
>>>>>> public void setLastWriteUserName(String lastWriteUserName) {
>>>>>> this.lastWriteUserName = lastWriteUserName;
>>>>>> }
>>>>>>
>>>>>> @PrePersist
>>>>>> public void prePersist() {
>>>>>> Date d = new Date();
>>>>>> setCreationTime(d);
>>>>>> setLastWriteTime(d);
>>>>>> }
>>>>>>
>>>>>> @PreUpdate
>>>>>> public void preUpdate() {
>>>>>> Date d = new Date();
>>>>>> setLastWriteTime(d);
>>>>>> }
>>>>>>}
>>>>>>
>>>>>>// Item.java
>>>>>>package edu.uchicago.at.reservations.persistence.entity;
>>>>>>
>>>>>>import edu.uchicago.at.common.persistence.entity.AuditObject;
>>>>>>import java.util.ArrayList;
>>>>>>import java.util.Collection;
>>>>>>import javax.persistence.Column;
>>>>>>import javax.persistence.Entity;
>>>>>>import javax.persistence.GeneratedValue;
>>>>>>import javax.persistence.GenerationType;
>>>>>>import javax.persistence.Id;
>>>>>>import javax.persistence.JoinColumn;
>>>>>>import javax.persistence.JoinTable;
>>>>>>import javax.persistence.ManyToMany;
>>>>>>import javax.persistence.Table;
>>>>>>
>>>>>>@Entity
>>>>>>@Table(name="Item")
>>>>>>public class Item extends AuditObject {
>>>>>> private String description;
>>>>>> private Integer id;
>>>>>> private String name;
>>>>>> private Collection<Reservation> reservations = new
>>>>>> ArrayList<Reservation>();
>>>>>> private Collection<Item> subItems = new ArrayList<Item>();
>>>>>> private Collection<Item> superItems = new ArrayList<Item>();
>>>>>>
>>>>>> public Item() {
>>>>>> }
>>>>>>
>>>>>> public Item(String name) {
>>>>>> setName(name);
>>>>>> }
>>>>>>
>>>>>> public boolean contains(Item item) {
>>>>>> for(Item i : subItems) {
>>>>>> if (i.id == item.id) {
>>>>>> return true;
>>>>>> }
>>>>>> if (i.contains(item)) {
>>>>>> return true;
>>>>>> }
>>>>>> }
>>>>>> return false;
>>>>>> }
>>>>>>
>>>>>> @Column(name="Description", columnDefinition="nvarchar(max)")
>>>>>> public String getDescription() {
>>>>>> return description;
>>>>>> }
>>>>>>
>>>>>> public void setDescription(String description) {
>>>>>> this.description = description;
>>>>>> }
>>>>>>
>>>>>> @Id
>>>>>> @GeneratedValue(strategy = GenerationType.IDENTITY)
>>>>>> @Column(name="Id")
>>>>>> public Integer getId() {
>>>>>> return id;
>>>>>> }
>>>>>>
>>>>>> public void setId(Integer id) {
>>>>>> this.id = id;
>>>>>> }
>>>>>>
>>>>>> @Column(name="Name", columnDefinition="nvarchar(255)")
>>>>>> public String getName() {
>>>>>> return name;
>>>>>> }
>>>>>>
>>>>>> public void setName(String name) {
>>>>>> this.name = name;
>>>>>> }
>>>>>>
>>>>>> @ManyToMany(mappedBy="items")
>>>>>> public Collection<Reservation> getReservations() {
>>>>>> return reservations;
>>>>>> }
>>>>>>
>>>>>> public void setReservations(Collection<Reservation> reservations) {
>>>>>> this.reservations = reservations;
>>>>>> }
>>>>>>
>>>>>> @ManyToMany
>>>>>> @JoinTable(name="ItemItem",
>>>>>> joinColumns={_at_JoinColumn(name="ItemId")},
>>>>>> inverseJoinColumns={_at_JoinColumn(name="SubItemId")})
>>>>>> public Collection<Item> getSubItems() {
>>>>>> return subItems;
>>>>>> }
>>>>>>
>>>>>> public void setSubItems(Collection<Item> subItems) {
>>>>>> this.subItems = subItems;
>>>>>> }
>>>>>>
>>>>>> @ManyToMany(mappedBy="subItems")
>>>>>> public Collection<Item> getSuperItems() {
>>>>>> return superItems;
>>>>>> }
>>>>>>
>>>>>> public void setSuperItems(Collection<Item> superItems) {
>>>>>> this.superItems = superItems;
>>>>>> }
>>>>>>
>>>>>> public String toString() {
>>>>>> StringBuilder sb = new StringBuilder();
>>>>>> sb.append("[");
>>>>>> sb.append(String.format("id = %d", id));
>>>>>> sb.append(String.format(", name = \"%s\"", name));
>>>>>> sb.append(String.format(", description = \"%s\"",
>>>>>> description));
>>>>>> sb.append("]");
>>>>>> return sb.toString();
>>>>>> }
>>>>>>}
>>>>>>
>>>>>>Jon
>>>>>>
>>>>>>
>