Author: pcl
Date: Thu Jan 31 18:41:00 2008
New Revision: 617334
URL: http://svn.apache.org/viewvc?rev=617334&view=rev
Log:
OPENJPA-506
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEvent.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
openjpa/branches/1.0.x/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/ExceptionsFromCallbacksEntity.java
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/TestExceptionsFromCallbacks.java
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SingleEMFTestCase.java
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataParsers.java
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEvent.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEvent.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEvent.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEvent.java
Thu Jan 31 18:41:00 2008
@@ -42,6 +42,12 @@
public static final int AFTER_PERSIST = 1;
/**
+ * Event type when an instance is made persistent, after the record has
+ * been written to the store
+ */
+ public static final int AFTER_PERSIST_PERFORMED = 18;
+
+ /**
* Event type when an instance is loaded.
*/
public static final int AFTER_LOAD = 2;
@@ -77,6 +83,12 @@
public static final int AFTER_DELETE = 8;
/**
+ * Event type when an instance is deleted, after the record has been
+ * deleted from the store.
+ */
+ public static final int AFTER_DELETE_PERFORMED = 19;
+
+ /**
* Event type when an instance is dirtied for the first time.
*/
public static final int BEFORE_DIRTY = 9;
@@ -122,11 +134,25 @@
public static final int AFTER_REFRESH = 17;
/**
+ * Event type when an instance is modified. This is not invoked for
+ * PNEW records, but is invoked for PNEWFLUSHED.
+ */
+ public static final int BEFORE_UPDATE = 20;
+
+ /**
+ * Event type when an instance is modified, after the change has been
+ * sent to the store. This is not invoked for PNEW records, but is
+ * invoked for PNEWFLUSHED records.
+ */
+ public static final int AFTER_UPDATE_PERFORMED = 21;
+
+ /**
* Convenience array of all event types.
*/
public static final int[] ALL_EVENTS = new int[]{
BEFORE_PERSIST,
AFTER_PERSIST,
+ AFTER_PERSIST_PERFORMED,
AFTER_LOAD,
BEFORE_STORE,
AFTER_STORE,
@@ -134,6 +160,7 @@
AFTER_CLEAR,
BEFORE_DELETE,
AFTER_DELETE,
+ AFTER_DELETE_PERFORMED,
BEFORE_DIRTY,
AFTER_DIRTY,
BEFORE_DIRTY_FLUSHED,
@@ -143,6 +170,8 @@
BEFORE_ATTACH,
AFTER_ATTACH,
AFTER_REFRESH,
+ BEFORE_UPDATE,
+ AFTER_UPDATE_PERFORMED,
};
private final int _type;
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java
Thu Jan 31 18:41:00 2008
@@ -28,6 +28,8 @@
import org.apache.openjpa.meta.ClassMetaData;
import org.apache.openjpa.meta.MetaDataDefaults;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
/**
* Manager that can be used to track and notify listeners on lifecycle events.
@@ -48,6 +50,9 @@
private static final Exception[] EMPTY_EXCEPTIONS = new Exception[0];
+ private static final Localizer _loc = Localizer.forPackage(
+ LifecycleEventManager.class);
+
private Map _classListeners = null; // class -> listener list
private ListenerList _listeners = null;
private List _addListeners = new LinkedList();
@@ -56,6 +61,11 @@
private boolean _firing = false;
private boolean _fail = false;
private boolean _failFast = false;
+ private final Log _log;
+
+ public LifecycleEventManager(Log log) {
+ _log = log;
+ }
/**
* Whether to fail after first exception when firing events to listeners.
@@ -132,7 +142,9 @@
*/
public boolean hasPersistListeners(Object source, ClassMetaData meta) {
return hasHandlers(source, meta, LifecycleEvent.BEFORE_PERSIST)
- || hasHandlers(source, meta, LifecycleEvent.AFTER_PERSIST);
+ || hasHandlers(source, meta, LifecycleEvent.AFTER_PERSIST)
+ || hasHandlers(source, meta,
+ LifecycleEvent.AFTER_PERSIST_PERFORMED);
}
/**
@@ -140,7 +152,8 @@
*/
public boolean hasDeleteListeners(Object source, ClassMetaData meta) {
return hasHandlers(source, meta, LifecycleEvent.BEFORE_DELETE)
- || hasHandlers(source, meta, LifecycleEvent.AFTER_DELETE);
+ || hasHandlers(source, meta, LifecycleEvent.AFTER_DELETE)
+ || hasHandlers(source, meta,
LifecycleEvent.AFTER_DELETE_PERFORMED);
}
/**
@@ -169,6 +182,14 @@
/**
* Return whether there are listeners or callbacks for the given source.
*/
+ public boolean hasUpdateListeners(Object source, ClassMetaData meta) {
+ return hasHandlers(source, meta, LifecycleEvent.BEFORE_UPDATE)
+ || hasHandlers(source, meta,
LifecycleEvent.AFTER_UPDATE_PERFORMED);
+ }
+
+ /**
+ * Return whether there are listeners or callbacks for the given source.
+ */
public boolean hasDirtyListeners(Object source, ClassMetaData meta) {
return hasHandlers(source, meta, LifecycleEvent.BEFORE_DIRTY)
|| hasHandlers(source, meta, LifecycleEvent.AFTER_DIRTY);
@@ -469,6 +490,11 @@
else
((AttachListener) listener).afterAttach(ev);
}
+ break;
+ default:
+ if (_log.isWarnEnabled())
+ _log.warn(_loc.get("unknown-lifecycle-event",
+ Integer.toString(type)));
break;
}
}
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java
Thu Jan 31 18:41:00 2008
@@ -264,7 +264,8 @@
else
_runtime = new LocalManagedRuntime(this);
- _lifeEventManager = new LifecycleEventManager();
+ _lifeEventManager = new LifecycleEventManager(
+ _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME));
_transEventManager = new TransactionEventManager();
int cmode = _conf.getMetaDataRepositoryInstance().
getMetaDataFactory().getDefaults().getCallbackMode();
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
Thu Jan 31 18:41:00 2008
@@ -952,6 +952,11 @@
if (reason != BrokerImpl.FLUSH_ROLLBACK
&& reason != BrokerImpl.FLUSH_LOGICAL) {
+ // analyze previous state for later
+ boolean wasNew = isNew();
+ boolean wasFlushed = isFlushed();
+ boolean wasDeleted = isDeleted();
+
// all dirty fields were flushed
_flush.or(_dirty);
@@ -972,6 +977,15 @@
// if this object was stored with preFlush, do post-store callback
if ((_flags & FLAG_PRE_FLUSHED) > 0)
fireLifecycleEvent(LifecycleEvent.AFTER_STORE);
+
+ // do post-update as needed
+ if (wasNew && !wasFlushed)
+ fireLifecycleEvent(LifecycleEvent.AFTER_PERSIST_PERFORMED);
+ else if (wasDeleted)
+ fireLifecycleEvent(LifecycleEvent.AFTER_DELETE_PERFORMED);
+ else
+ // updates and new-flushed with changes
+ fireLifecycleEvent(LifecycleEvent.AFTER_UPDATE_PERFORMED);
} else if (reason == BrokerImpl.FLUSH_ROLLBACK) {
// revert to last loaded version and original oid
assignVersionField(_loadVersion);
@@ -2761,6 +2775,11 @@
if (isPersistent()) {
fireLifecycleEvent(LifecycleEvent.BEFORE_STORE);
+ // BEFORE_PERSIST is handled during Broker.persist and
Broker.attach
+ if (isDeleted())
+ fireLifecycleEvent(LifecycleEvent.BEFORE_DELETE);
+ else
+ fireLifecycleEvent(LifecycleEvent.BEFORE_UPDATE);
_flags |= FLAG_PRE_FLUSHED;
}
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java
Thu Jan 31 18:41:00 2008
@@ -33,6 +33,7 @@
import org.apache.openjpa.util.ObjectNotFoundException;
import org.apache.openjpa.util.OptimisticException;
import org.apache.openjpa.util.ImplHelper;
+import org.apache.openjpa.event.LifecycleEvent;
/**
* Handles attaching instances using version and primary key fields.
@@ -133,8 +134,13 @@
return into;
}
- // invoke any preAttach on the detached instance
- manager.fireBeforeAttach(toAttach, meta);
+ if (isNew) {
+ broker.fireLifecycleEvent(toAttach, null, meta,
+ LifecycleEvent.BEFORE_PERSIST);
+ } else {
+ // invoke any preAttach on the detached instance
+ manager.fireBeforeAttach(toAttach, meta);
+ }
// assign the detached pc the same state manager as the object we're
// copying into during the attach process
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java
Thu Jan 31 18:41:00 2008
@@ -168,9 +168,9 @@
}
}
- /**
- * Returns the fields of the state that require an update.
- *
+ /**
+ * Returns the fields of the state that require an update.
+ *
* @param sm the state to check
* @return the BitSet of fields that need update, or null if none
*/
Modified:
openjpa/branches/1.0.x/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties
(original)
+++
openjpa/branches/1.0.x/openjpa-kernel/src/main/resources/org/apache/openjpa/event/localizer.properties
Thu Jan 31 18:41:00 2008
@@ -96,4 +96,6 @@
method-notfound: Method "{1}" with arguments of type: {2} \
not found in class "{0}".
broker-factory-listener-exception: Exception thrown while calling a \
- BrokerFactoryListener. This exception will be ignored.
\ No newline at end of file
+ BrokerFactoryListener. This exception will be ignored.
+unknown-lifecycle-event: An unknown lifecycle event was encountered. Please \
+ report this to [EMAIL PROTECTED] Event type: {0}.
\ No newline at end of file
Modified:
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/ExceptionsFromCallbacksEntity.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/ExceptionsFromCallbacksEntity.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/ExceptionsFromCallbacksEntity.java
(original)
+++
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/ExceptionsFromCallbacksEntity.java
Thu Jan 31 18:41:00 2008
@@ -24,29 +24,54 @@
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Version;
-
+import javax.persistence.PreRemove;
+import javax.persistence.PostRemove;
+import javax.persistence.PostUpdate;
+import javax.persistence.PostPersist;
+import javax.persistence.GeneratedValue;
+import javax.persistence.Transient;
@Entity
public class ExceptionsFromCallbacksEntity {
- @Id private long id;
+ @Id @GeneratedValue private long id;
@Version private int version;
- private boolean throwOnPrePersist;
- private boolean throwOnPreUpdate;
+ @Transient private boolean throwOnPrePersist;
+ @Transient private boolean throwOnPostPersist;
+ @Transient private boolean throwOnPreUpdate;
+ @Transient private boolean throwOnPostUpdate;
private boolean throwOnPostLoad;
+ @Transient private boolean throwOnPreRemove;
+ @Transient private boolean throwOnPostRemove;
private String stringField;
-
+
public void setThrowOnPrePersist(boolean b) {
throwOnPrePersist = b;
}
- public void setThrowOnPostLoad(boolean b) {
- throwOnPostLoad = b;
+ public void setThrowOnPostPersist(boolean b) {
+ throwOnPostPersist = b;
}
public void setThrowOnPreUpdate(boolean b) {
throwOnPreUpdate = b;
}
+ public void setThrowOnPostUpdate(boolean b) {
+ throwOnPostUpdate = b;
+ }
+
+ public void setThrowOnPostLoad(boolean b) {
+ throwOnPostLoad = b;
+ }
+
+ public void setThrowOnPreRemove(boolean b) {
+ throwOnPreRemove = b;
+ }
+
+ public void setThrowOnPostRemove(boolean b) {
+ throwOnPostRemove = b;
+ }
+
public void setStringField(String s) {
stringField = s;
}
@@ -57,18 +82,50 @@
throw new CallbackTestException();
}
+ @PostPersist
+ public void postPersist() {
+ if (throwOnPostPersist)
+ throw new CallbackTestException();
+ }
+
+ @PostLoad
+ public void postLoad() {
+ if (throwOnPostLoad && isInvokedFromTestMethod())
+ throw new CallbackTestException();
+ }
+
+ private boolean isInvokedFromTestMethod() {
+ return TestExceptionsFromCallbacks.testRunning;
+ }
+
@PreUpdate
public void preUpdate() {
if (throwOnPreUpdate)
throw new CallbackTestException();
}
- @PostLoad
- public void postLoad() {
- if (throwOnPostLoad)
+ @PostUpdate
+ public void postUpdate() {
+ if (throwOnPostUpdate)
throw new CallbackTestException();
}
-
+
+ @PreRemove
+ public void preRemove() {
+ if (throwOnPreRemove && isInvokedFromTestMethod())
+ throw new CallbackTestException();
+ }
+
+ @PostRemove
+ public void postRemove() {
+ if (throwOnPostRemove && isInvokedFromTestMethod())
+ throw new CallbackTestException();
+ }
+
+ public Object getId() {
+ return id;
+ }
+
public class CallbackTestException
extends RuntimeException {
}
Modified:
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/TestExceptionsFromCallbacks.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/TestExceptionsFromCallbacks.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/TestExceptionsFromCallbacks.java
(original)
+++
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/callbacks/TestExceptionsFromCallbacks.java
Thu Jan 31 18:41:00 2008
@@ -18,18 +18,15 @@
*/
package org.apache.openjpa.persistence.callbacks;
-import java.util.HashMap;
-import java.util.Map;
-
+import java.util.Set;
+import java.util.HashSet;
import javax.persistence.EntityManager;
-import javax.persistence.Persistence;
import javax.persistence.RollbackException;
-import junit.framework.TestCase;
-import org.apache.openjpa.persistence.OpenJPAEntityManagerFactory;
import org.apache.openjpa.persistence.OpenJPAPersistence;
import
org.apache.openjpa.persistence.callbacks.ExceptionsFromCallbacksEntity.CallbackTestException;
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+import org.apache.openjpa.enhance.PersistenceCapable;
/**
* Tests against JPA section 3.5's description of callback exception handling.
@@ -37,8 +34,35 @@
public class TestExceptionsFromCallbacks
extends SingleEMFTestCase {
+ public static boolean testRunning = false;
+
+ @Override
public void setUp() {
- setUp(ExceptionsFromCallbacksEntity.class);
+ Set needEnhancement = new HashSet();
+ needEnhancement.add(
+ "testPostUpdateExceptionDuringFlushWithNewInstance");
+ needEnhancement.add(
+ "testPreUpdateExceptionDuringFlushWithExistingFlushedInstance");
+ needEnhancement.add(
+ "testPreUpdateExceptionDuringCommitWithExistingFlushedInstance");
+ needEnhancement.add(
+ "testPostUpdateExceptionDuringFlushWithExistingFlushedInstance");
+ needEnhancement.add(
+ "testPostUpdateExceptionDuringCommitWithExistingFlushedInstance");
+ if (!PersistenceCapable.class.isAssignableFrom(
+ ExceptionsFromCallbacksEntity.class)
+ && needEnhancement.contains(getName()))
+ // actually, we really only need redef
+ fail("this test method does not work without enhancement");
+
+ setUp(ExceptionsFromCallbacksEntity.class, CLEAR_TABLES,
"openjpa.Log", "SQL=TRACE");
+ testRunning = true;
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ testRunning = false;
+ super.tearDown();
}
public void testPrePersistException() {
@@ -60,13 +84,41 @@
}
}
- public void testPreUpdateExceptionDuringFlush() {
+ public void testPrePersistExceptionOnMerge() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
- o.setThrowOnPreUpdate(true);
+ o.setThrowOnPrePersist(true);
+ try {
+ em.merge(o);
+ fail("merge should have failed");
+ } catch (CallbackTestException cte) {
+ // transaction should be still active, but marked for rollback
+ assertTrue(em.getTransaction().isActive());
+ assertTrue(em.getTransaction().getRollbackOnly());
+ } finally {
+ if (em.getTransaction().isActive())
+ em.getTransaction().rollback();
+ em.close();
+ }
+ }
+
+ public void testPostPersistExceptionDuringFlush() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ o.setThrowOnPostPersist(true);
em.persist(o);
+ mutateAndFlush(em, o);
+ }
+
+ private void mutateAndFlush(EntityManager em,
+ ExceptionsFromCallbacksEntity o) {
o.setStringField("foo");
+ flush(em);
+ }
+
+ private void flush(EntityManager em) {
try {
em.flush();
fail("flush should have failed");
@@ -81,20 +133,29 @@
}
}
- public void testPreUpdateExceptionDuringCommit() {
+ public void testPostPersistExceptionDuringCommit() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
- o.setThrowOnPreUpdate(true);
+ o.setThrowOnPostPersist(true);
em.persist(o);
+ mutateAndCommit(em, o);
+ }
+
+ private void mutateAndCommit(EntityManager em,
+ ExceptionsFromCallbacksEntity o) {
o.setStringField("foo");
+ commit(em);
+ }
+
+ private void commit(EntityManager em) {
try {
em.getTransaction().commit();
fail("commit should have failed");
} catch (RollbackException re) {
assertEquals(CallbackTestException.class,
re.getCause().getClass());
-
+
// transaction should be rolled back at this point
assertFalse(em.getTransaction().isActive());
} finally {
@@ -103,7 +164,253 @@
em.close();
}
}
-
+
+ public void testPrePersistExceptionDuringFlushWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPrePersist(true);
+ // should pass; pre-persist should not be triggered
+ o.setStringField("foo");
+ em.flush();
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPrePersistExceptionDuringCommitWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPrePersist(true);
+ // should pass; pre-persist should not be triggered
+ o.setStringField("foo");
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPostPersistExceptionDuringFlushWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPostPersist(true);
+ // should pass; post-persist should not be triggered
+ o.setStringField("foo");
+ em.flush();
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPostPersistExceptionDuringCommitWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPostPersist(true);
+ // should pass; post-persist should not be triggered
+ o.setStringField("foo");
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPreUpdateExceptionWithNewInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ o.setThrowOnPreUpdate(true);
+ em.persist(o);
+ o.setStringField("foo");
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPostUpdateExceptionDuringFlushWithNewInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ o.setThrowOnPostUpdate(true);
+ em.persist(o);
+ o.setStringField("foo");
+ em.flush();
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPostUpdateExceptionDuringCommitWithNewInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ o.setThrowOnPostUpdate(true);
+ em.persist(o);
+ o.setStringField("foo");
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPreUpdateExceptionDuringFlushWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPreUpdate(true);
+ mutateAndFlush(em, o);
+ }
+
+ public void testPreUpdateExceptionDuringCommitWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPreUpdate(true);
+ mutateAndCommit(em, o);
+ }
+
+ public void testPostUpdateExceptionDuringFlushWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPostUpdate(true);
+ mutateAndFlush(em, o);
+ }
+
+ public void testPostUpdateExceptionDuringCommitWithNewFlushedInstance() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPostUpdate(true);
+ mutateAndCommit(em, o);
+ }
+
+ public void testPreUpdateExceptionDuringFlushWithExistingInstance() {
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setThrowOnPreUpdate(true);
+ mutateAndFlush(em, o);
+ }
+
+ private Object insert(String s) {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ o.setStringField(s);
+ em.persist(o);
+ em.getTransaction().commit();
+ em.close();
+ return o.getId();
+ }
+
+ public void testPreUpdateExceptionDuringCommitWithExistingInstance() {
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setThrowOnPreUpdate(true);
+ mutateAndCommit(em, o);
+ }
+
+ public void testPostUpdateExceptionDuringFlushWithExistingInstance() {
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setThrowOnPostUpdate(true);
+ mutateAndFlush(em, o);
+ }
+
+ public void testPostUpdateExceptionDuringCommitWithExistingInstance() {
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setThrowOnPostUpdate(true);
+ mutateAndCommit(em, o);
+ }
+
+ public void testPreUpdateExceptionDuringFlushWithExistingFlushedInstance()
{
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setStringField("foo");
+ em.flush();
+ o.setThrowOnPreUpdate(true);
+ // there's no additional flush work; should not re-invoke the callback
+ em.flush();
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void
testPreUpdateExceptionDuringCommitWithExistingFlushedInstance(){
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setStringField("foo");
+ em.flush();
+ o.setThrowOnPreUpdate(true);
+ // there's no additional flush work; should not re-invoke the callback
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void
testPostUpdateExceptionDuringFlushWithExistingFlushedInstance(){
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setStringField("foo");
+ em.flush();
+ o.setThrowOnPostUpdate(true);
+ // no mutations; should not trigger a PostUpdate
+ em.flush();
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void
testPostUpdateExceptionDuringCommitWithExistingFlushedInstance()
+ {
+ Object oid = insert("new instance");
+
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o =
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
+ o.setStringField("foo");
+ em.flush();
+ // no mutations; should not trigger a PostUpdate
+ o.setThrowOnPostUpdate(true);
+ em.getTransaction().commit();
+ em.close();
+ }
+
public void testPostLoadException() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
@@ -117,7 +424,7 @@
em = emf.createEntityManager();
em.getTransaction().begin();
try {
- o = em.find(ExceptionsFromCallbacksEntity.class, oid);
+ em.find(ExceptionsFromCallbacksEntity.class, oid);
fail("find should have failed");
} catch (CallbackTestException cte) {
// transaction should be active but marked for rollback
@@ -128,5 +435,108 @@
em.getTransaction().rollback();
em.close();
}
+ }
+
+ public void testPreDeleteException() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPreRemove(true);
+ try {
+ em.remove(o);
+ } catch (CallbackTestException cte) {
+ // transaction should be active but marked for rollback
+ assertTrue(em.getTransaction().isActive());
+ assertTrue(em.getTransaction().getRollbackOnly());
+ } finally {
+ if (em.getTransaction().isActive())
+ em.getTransaction().rollback();
+ em.close();
+ }
+ }
+
+ public void testPostDeleteExceptionDuringFlush() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPostRemove(true);
+ try {
+ em.remove(o);
+ } catch (CallbackTestException e) {
+ em.getTransaction().rollback();
+ em.close();
+ fail("PostRemove is being called too soon (before SQL is issued)");
+ }
+ flush(em);
+ }
+
+ public void testPostDeleteExceptionDuringCommit() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ o.setThrowOnPostRemove(true);
+ try {
+ em.remove(o);
+ } catch (CallbackTestException e) {
+ em.getTransaction().rollback();
+ em.close();
+ fail("PostRemove is being called too soon (before SQL is issued)");
+ }
+ commit(em);
+ }
+
+ public void testPreDeleteExceptionDoubleDelete() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ // this should pass
+ em.remove(o);
+ em.flush();
+ o.setThrowOnPreRemove(true);
+ // this shoud also pass; no work to do for delete
+ em.remove(o);
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPostDeleteExceptionDuringFlushDoubleDelete() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ // this should pass
+ em.remove(o);
+ em.flush();
+ o.setThrowOnPostRemove(true);
+ // this shoud also pass; no work to do for delete
+ em.remove(o);
+ em.flush();
+ em.getTransaction().commit();
+ em.close();
+ }
+
+ public void testPostDeleteExceptionDuringCommitDoubleDelete() {
+ EntityManager em = emf.createEntityManager();
+ em.getTransaction().begin();
+ ExceptionsFromCallbacksEntity o = new ExceptionsFromCallbacksEntity();
+ em.persist(o);
+ em.flush();
+ // this should pass
+ em.remove(o);
+ em.flush();
+ o.setThrowOnPostRemove(true);
+ // this shoud also pass; no work to do for delete
+ em.remove(o);
+ em.getTransaction().commit();
+ em.close();
}
}
Modified:
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java
(original)
+++
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/PersistenceTestCase.java
Thu Jan 31 18:41:00 2008
@@ -29,6 +29,7 @@
import javax.persistence.Persistence;
import junit.framework.TestCase;
+import junit.framework.TestResult;
import org.apache.openjpa.kernel.AbstractBrokerFactory;
import org.apache.openjpa.kernel.Broker;
import org.apache.openjpa.meta.ClassMetaData;
@@ -48,6 +49,11 @@
protected static final Object CLEAR_TABLES = new Object();
/**
+ * The [EMAIL PROTECTED] TestResult} instance for the current test run.
+ */
+ protected TestResult testResult;
+
+ /**
* Create an entity manager factory. Put [EMAIL PROTECTED] #CLEAR_TABLES}
in
* this list to tell the test framework to delete all table contents
* before running the tests.
@@ -88,8 +94,22 @@
createEntityManagerFactory("test", map);
}
+ @Override
+ public void run(TestResult testResult) {
+ this.testResult = testResult;
+ super.run(testResult);
+ }
+
+ @Override
public void tearDown() throws Exception {
- super.tearDown();
+ try {
+ super.tearDown();
+ } catch (Exception e) {
+ // if a test failed, swallow any exceptions that happen
+ // during tear-down, as these just mask the original problem.
+ if (testResult.wasSuccessful())
+ throw e;
+ }
}
/**
Modified:
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SingleEMFTestCase.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SingleEMFTestCase.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SingleEMFTestCase.java
(original)
+++
openjpa/branches/1.0.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SingleEMFTestCase.java
Thu Jan 31 18:41:00 2008
@@ -58,6 +58,11 @@
try {
clear(emf);
+ } catch (Exception e) {
+ // if a test failed, swallow any exceptions that happen
+ // during tear-down, as these just mask the original problem.
+ if (testResult.wasSuccessful())
+ throw e;
} finally {
closeEMF(emf);
}
Modified:
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataParsers.java
URL:
http://svn.apache.org/viewvc/openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataParsers.java?rev=617334&r1=617333&r2=617334&view=diff
==============================================================================
---
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataParsers.java
(original)
+++
openjpa/branches/1.0.x/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/MetaDataParsers.java
Thu Jan 31 18:41:00 2008
@@ -47,15 +47,15 @@
case PRE_PERSIST:
return new int[]{ LifecycleEvent.BEFORE_PERSIST };
case POST_PERSIST:
- return new int[]{ LifecycleEvent.AFTER_PERSIST };
+ return new int[]{ LifecycleEvent.AFTER_PERSIST_PERFORMED };
case PRE_REMOVE:
return new int[]{ LifecycleEvent.BEFORE_DELETE };
case POST_REMOVE:
- return new int[]{ LifecycleEvent.AFTER_DELETE };
+ return new int[]{ LifecycleEvent.AFTER_DELETE_PERFORMED };
case PRE_UPDATE:
- return new int[]{ LifecycleEvent.BEFORE_STORE };
+ return new int[]{ LifecycleEvent.BEFORE_UPDATE };
case POST_UPDATE:
- return new int[]{ LifecycleEvent.AFTER_STORE };
+ return new int[]{ LifecycleEvent.AFTER_UPDATE_PERFORMED };
case POST_LOAD:
return new int[]{ LifecycleEvent.AFTER_LOAD,
LifecycleEvent.AFTER_REFRESH };