mirror of https://github.com/apache/openjpa.git
OPENJPA-506. svn merge -c 617334 ../branches/1.0.x; svn merge -c 617363 ../branches/1.0.x, plus modifications for serialization.
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@617525 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
64d0ea8166
commit
a747db9443
|
@ -41,6 +41,12 @@ public class LifecycleEvent
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -76,6 +82,12 @@ public class LifecycleEvent
|
|||
*/
|
||||
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.
|
||||
*/
|
||||
|
@ -121,12 +133,26 @@ public class LifecycleEvent
|
|||
*/
|
||||
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 @@ public class LifecycleEvent
|
|||
AFTER_CLEAR,
|
||||
BEFORE_DELETE,
|
||||
AFTER_DELETE,
|
||||
AFTER_DELETE_PERFORMED,
|
||||
BEFORE_DIRTY,
|
||||
AFTER_DIRTY,
|
||||
BEFORE_DIRTY_FLUSHED,
|
||||
|
@ -143,6 +170,8 @@ public class LifecycleEvent
|
|||
BEFORE_ATTACH,
|
||||
AFTER_ATTACH,
|
||||
AFTER_REFRESH,
|
||||
BEFORE_UPDATE,
|
||||
AFTER_UPDATE_PERFORMED,
|
||||
};
|
||||
|
||||
private final int _type;
|
||||
|
|
|
@ -29,6 +29,9 @@ import java.util.Map;
|
|||
|
||||
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;
|
||||
import org.apache.openjpa.util.InvalidStateException;
|
||||
|
||||
/**
|
||||
* Manager that can be used to track and notify listeners on lifecycle events.
|
||||
|
@ -49,6 +52,9 @@ public class LifecycleEventManager
|
|||
|
||||
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();
|
||||
|
@ -133,7 +139,9 @@ public class LifecycleEventManager
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -141,7 +149,8 @@ public class LifecycleEventManager
|
|||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -167,6 +176,14 @@ public class LifecycleEventManager
|
|||
|| hasHandlers(source, meta, LifecycleEvent.AFTER_STORE);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
@ -471,6 +488,10 @@ public class LifecycleEventManager
|
|||
((AttachListener) listener).afterAttach(ev);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidStateException(
|
||||
_loc.get("unknown-lifecycle-event",
|
||||
Integer.toString(type)));
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
|
|
|
@ -969,6 +969,11 @@ public class StateManagerImpl
|
|||
|
||||
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);
|
||||
|
||||
|
@ -989,6 +994,15 @@ public class StateManagerImpl
|
|||
// 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);
|
||||
|
@ -2786,6 +2800,11 @@ public class StateManagerImpl
|
|||
|
||||
if (isPersistent()) {
|
||||
fireLifecycleEvent(LifecycleEvent.BEFORE_STORE);
|
||||
// BEFORE_PERSIST is handled during Broker.persist and Broker.attach
|
||||
if (isDeleted())
|
||||
fireLifecycleEvent(LifecycleEvent.BEFORE_DELETE);
|
||||
else if (!(isNew() && !isFlushed()))
|
||||
fireLifecycleEvent(LifecycleEvent.BEFORE_UPDATE);
|
||||
_flags |= FLAG_PRE_FLUSHED;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.apache.openjpa.util.ApplicationIds;
|
|||
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 @@ class VersionAttachStrategy
|
|||
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
|
||||
|
|
|
@ -168,9 +168,9 @@ public class ImplHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
|
|
@ -96,4 +96,6 @@ bean-constructor: Could not instantiate class {0}. Make sure it has an \
|
|||
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.
|
||||
BrokerFactoryListener. This exception will be ignored.
|
||||
unknown-lifecycle-event: An unknown lifecycle event was encountered. Please \
|
||||
report this to dev@openjpa.apache.org. Event type: {0}.
|
|
@ -24,27 +24,52 @@ import javax.persistence.PostLoad;
|
|||
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 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 setThrowOnPreUpdate(boolean b) {
|
||||
throwOnPreUpdate = b;
|
||||
public void setThrowOnPreRemove(boolean b) {
|
||||
throwOnPreRemove = b;
|
||||
}
|
||||
|
||||
public void setThrowOnPostRemove(boolean b) {
|
||||
throwOnPostRemove = b;
|
||||
}
|
||||
|
||||
public void setStringField(String s) {
|
||||
|
@ -57,18 +82,50 @@ public class ExceptionsFromCallbacksEntity {
|
|||
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 {
|
||||
}
|
||||
|
|
|
@ -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 @@ import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
|||
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 class TestExceptionsFromCallbacks
|
|||
}
|
||||
}
|
||||
|
||||
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 class TestExceptionsFromCallbacks
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ public class TestExceptionsFromCallbacks
|
|||
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 @@ public class TestExceptionsFromCallbacks
|
|||
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
|
||||
|
@ -129,4 +436,107 @@ public class TestExceptionsFromCallbacks
|
|||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public abstract class PersistenceTestCase
|
|||
/**
|
||||
* The {@link TestResult} instance for the current test run.
|
||||
*/
|
||||
private TestResult testResult;
|
||||
protected TestResult testResult;
|
||||
|
||||
/**
|
||||
* Create an entity manager factory. Put {@link #CLEAR_TABLES} in
|
||||
|
|
|
@ -58,6 +58,11 @@ public abstract class SingleEMFTestCase
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -47,15 +47,15 @@ class MetaDataParsers {
|
|||
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 };
|
||||
|
|
Loading…
Reference in New Issue