diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java index b7e76831b..b8c826871 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/event/LifecycleEventManager.java @@ -52,6 +52,21 @@ public class LifecycleEventManager private List _exceps = new LinkedList(); private boolean _firing = false; private boolean _fail = false; + private boolean _failFast = false; + + /** + * Whether to fail after first exception when firing events to listeners. + */ + public boolean isFailFast() { + return _failFast; + } + + /** + * Whether to fail after first exception when firing events to listeners. + */ + public void setFailFast(boolean failFast) { + _failFast = failFast; + } /** * Register a lifecycle listener for the given classes. If the classes @@ -207,22 +222,19 @@ public class LifecycleEventManager ClassMetaData meta, int type) { if (meta.getLifecycleMetaData().getIgnoreSystemListeners()) return false; - boolean failFast = (meta.getRepository().getMetaDataFactory(). - getDefaults().getCallbackMode() & CALLBACK_FAIL_FAST) != 0; - if (fireEvent(null, source, null, type, _listeners, true, failFast, - null) == Boolean.TRUE) + if (fireEvent(null, source, null, type, _listeners, true, null) + == Boolean.TRUE) return true; ListenerList system = meta.getRepository().getSystemListeners(); if (!system.isEmpty() && fireEvent(null, source, null, type, system, - true, failFast, null) == Boolean.TRUE) + true, null) == Boolean.TRUE) return true; if (_classListeners != null) { Class c = source == null ? meta.getDescribedType() : source.getClass(); do { if (fireEvent(null, source, null, type, (ListenerList) - _classListeners.get(c), true, failFast, null) - == Boolean.TRUE) + _classListeners.get(c), true, null) == Boolean.TRUE) return true; c = c.getSuperclass(); } while (c != null && c != Object.class); @@ -250,21 +262,18 @@ public class LifecycleEventManager getDefaults(); boolean callbacks = def.getCallbacksBeforeListeners(type); - boolean failFast = (def.getCallbackMode() & CALLBACK_FAIL_FAST) != 0; - if (callbacks) - makeCallbacks(source, related, meta, type, failFast, exceptions); + makeCallbacks(source, related, meta, type, exceptions); LifecycleEvent ev = (LifecycleEvent) fireEvent(null, source, related, - type, _listeners, false, failFast, exceptions); + type, _listeners, false, exceptions); if (_classListeners != null) { Class c = source == null ? meta.getDescribedType() : source.getClass(); do { ev = (LifecycleEvent) fireEvent(ev, source, related, type, - (ListenerList) _classListeners.get(c), false, failFast, - exceptions); + (ListenerList) _classListeners.get(c), false, exceptions); c = c.getSuperclass(); } while (c != null && c != Object.class); } @@ -272,12 +281,11 @@ public class LifecycleEventManager // make system listeners if (!meta.getLifecycleMetaData().getIgnoreSystemListeners()) { ListenerList system = meta.getRepository().getSystemListeners(); - fireEvent(ev, source, related, type, system, false, failFast, - exceptions); + fireEvent(ev, source, related, type, system, false, exceptions); } if (!callbacks) - makeCallbacks(source, related, meta, type, failFast, exceptions); + makeCallbacks(source, related, meta, type, exceptions); // create return array before clearing exceptions Exception[] ret; @@ -309,7 +317,7 @@ public class LifecycleEventManager * Make callbacks, recording any exceptions in the given collection. */ private void makeCallbacks(Object source, Object related, - ClassMetaData meta, int type, boolean failFast, Collection exceptions) { + ClassMetaData meta, int type, Collection exceptions) { // make lifecycle callbacks LifecycleCallbacks[] callbacks = meta.getLifecycleMetaData(). getCallbacks(type); @@ -318,7 +326,7 @@ public class LifecycleEventManager callbacks[i].makeCallback(source, related, type); } catch (Exception e) { exceptions.add(e); - if (failFast) + if (_failFast) _fail = true; } } @@ -329,8 +337,7 @@ public class LifecycleEventManager * listeners. The event may have already been constructed. */ private Object fireEvent(LifecycleEvent ev, Object source, Object rel, - int type, ListenerList listeners, boolean mock, boolean failFast, - List exceptions) { + int type, ListenerList listeners, boolean mock, List exceptions) { if (listeners == null || !listeners.hasListeners(type)) return null; @@ -471,7 +478,7 @@ public class LifecycleEventManager } catch (Exception e) { exceptions.add(e); - if (failFast) + if (_failFast) _fail = true; } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Broker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Broker.java index b5ba99f16..df787c92f 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Broker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/Broker.java @@ -21,6 +21,7 @@ import javax.resource.cci.LocalTransaction; import javax.transaction.Synchronization; import org.apache.openjpa.ee.ManagedRuntime; +import org.apache.openjpa.event.CallbackModes; import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.meta.ClassMetaData; @@ -40,7 +41,7 @@ public interface Broker extends Synchronization, Connection, LocalTransaction, javax.resource.spi.LocalTransaction, Closeable, StoreContext, ConnectionRetainModes, DetachState, LockLevels, - RestoreState, AutoClear, AutoDetach { + RestoreState, AutoClear, AutoDetach, CallbackModes { /** * Set the broker's behavior for implicit actions such as flushing, @@ -240,6 +241,18 @@ public interface Broker */ public void removeTransactionListener(Object listener); + /** + * The callback mode for handling exceptions from transaction event + * listeners. + */ + public int getTransactionListenerCallbackMode(); + + /** + * The callback mode for handling exceptions from transaction event + * listeners. + */ + public void setTransactionListenerCallbackMode(int mode); + /** * Register a listener for lifecycle-related events on the specified * classes. If the classes are null, all events will be propagated to @@ -261,6 +274,16 @@ public interface Broker */ public LifecycleEventManager getLifecycleEventManager(); + /** + * The callback mode for handling exceptions from lifecycle event listeners. + */ + public int getLifecycleListenerCallbackMode(); + + /** + * The callback mode for handling exceptions from lifecycle event listeners. + */ + public void setLifecycleListenerCallbackMode(int mode); + /** * Begin a transaction. */ diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java index 6a3322d51..aa97ae247 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java @@ -212,7 +212,6 @@ public class BrokerImpl private int _autoDetach = 0; private int _detachState = DETACH_LOADED; private boolean _detachedNew = true; - private int _callbackMode = CallbackModes.CALLBACK_IGNORE; private boolean _orderDirty = false; // status @@ -221,7 +220,9 @@ public class BrokerImpl // event managers private TransactionEventManager _transEventManager = null; + private int _transCallbackMode = 0; private LifecycleEventManager _lifeEventManager = null; + private int _lifeCallbackMode = 0; /** * Set the persistence manager's authentication. This is the first @@ -251,13 +252,10 @@ public class BrokerImpl DelegatingStoreManager sm, boolean managed, int connMode) { _conf = factory.getConfiguration(); _compat = _conf.getCompatibilityInstance(); - _factory = factory; _log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); _cache = new ManagedCache(newManagedObjectCache()); - _lifeEventManager = new LifecycleEventManager(); - _callbackMode = _conf.getMetaDataRepositoryInstance(). - getMetaDataFactory(). getDefaults().getCallbackMode(); + _operating = MapBackedSet.decorate(new IdentityMap()); _connRetainMode = connMode; _managed = managed; if (managed) @@ -265,9 +263,15 @@ public class BrokerImpl else _runtime = new LocalManagedRuntime(this); + _lifeEventManager = new LifecycleEventManager(); + _transEventManager = new TransactionEventManager(); + int cmode = _conf.getMetaDataRepositoryInstance(). + getMetaDataFactory().getDefaults().getCallbackMode(); + setLifecycleListenerCallbackMode(cmode); + setTransactionListenerCallbackMode(cmode); + // setup default options _factory.configureBroker(this); - _operating = MapBackedSet.decorate(new IdentityMap()); // make sure to do this after configuring broker so that store manager // can look to broker configuration; we set both store and lock managers @@ -624,6 +628,20 @@ public class BrokerImpl } } + public int getLifecycleListenerCallbackMode() { + return _lifeCallbackMode; + } + + public void setLifecycleListenerCallbackMode(int mode) { + beginOperation(false); + try { + _lifeCallbackMode = mode; + _lifeEventManager.setFailFast((mode & CALLBACK_FAIL_FAST) != 0); + } finally { + endOperation(); + } + } + /** * Give state managers access to the lifecycle event manager. */ @@ -632,41 +650,39 @@ public class BrokerImpl } /** - * Fire lifecycle events, handling any exceptions appropriately. + * Fire given lifecycle event, handling any exceptions appropriately. * - * @return whether events are being processed at this time. + * @return whether events are being processed at this time */ boolean fireLifecycleEvent(Object src, Object related, ClassMetaData meta, int eventType) { - if (_lifeEventManager == null) // uninitialized + if (_lifeEventManager == null) return false; - - Exception[] exceps = _lifeEventManager.fireEvent(src, related, meta, - eventType); - if (exceps.length == 0 - || (_callbackMode & CallbackModes.CALLBACK_IGNORE) != 0) - return true; - - OpenJPAException ke = new CallbackException - (_loc.get("callback-err", meta)). - setNestedThrowables(exceps).setFatal(true); - if ((_callbackMode & CallbackModes.CALLBACK_ROLLBACK) != 0 - && (_flags & FLAG_ACTIVE) != 0) - setRollbackOnlyInternal(); - if ((_callbackMode & CallbackModes.CALLBACK_LOG) != 0 - && _log.isWarnEnabled()) - _log.warn(ke); - if ((_callbackMode & CallbackModes.CALLBACK_RETHROW) != 0) - throw ke; + handleCallbackExceptions(_lifeEventManager.fireEvent(src, related, + meta, eventType), _lifeCallbackMode); return true; } + /** + * Take actions on callback exceptions depending on callback mode. + */ + private void handleCallbackExceptions(Exception[] exceps, int mode) { + if (exceps.length == 0 || (mode & CALLBACK_IGNORE) != 0) + return; + + OpenJPAException ke = new CallbackException(_loc.get("callback-err")). + setNestedThrowables(exceps).setFatal(true); + if ((mode & CALLBACK_ROLLBACK) != 0 && (_flags & FLAG_ACTIVE) != 0) + setRollbackOnlyInternal(); + if ((mode & CALLBACK_LOG) != 0 && _log.isWarnEnabled()) + _log.warn(ke); + if ((mode & CALLBACK_RETHROW) != 0) + throw ke; + } + public void addTransactionListener(Object tl) { beginOperation(false); try { - if (_transEventManager == null) - _transEventManager = new TransactionEventManager(); - _transEventManager.addListener(tl); if (tl instanceof RemoteCommitEventManager) _flags |= FLAG_REMOTE_LISTENER; @@ -678,8 +694,7 @@ public class BrokerImpl public void removeTransactionListener(Object tl) { beginOperation(false); try { - if (_transEventManager != null - && _transEventManager.removeListener(tl) + if (_transEventManager.removeListener(tl) && (tl instanceof RemoteCommitEventManager)) _flags &= ~FLAG_REMOTE_LISTENER; } finally { @@ -687,6 +702,31 @@ public class BrokerImpl } } + public int getTransactionListenerCallbackMode() { + return _transCallbackMode; + } + + public void setTransactionListenerCallbackMode(int mode) { + beginOperation(false); + try { + _transCallbackMode = mode; + _transEventManager.setFailFast((mode & CALLBACK_FAIL_FAST) != 0); + } finally { + endOperation(); + } + } + + /** + * Fire given transaction event, handling any exceptions appropriately. + * + * @return whether events are being processed at this time + */ + private void fireTransactionEvent(TransactionEvent trans) { + if (_transEventManager != null) + handleCallbackExceptions(_transEventManager.fireEvent(trans), + _transCallbackMode); + } + /////////// // Lookups /////////// @@ -1151,9 +1191,8 @@ public class BrokerImpl } _lm.beginTransaction(); - if (_transEventManager != null - && _transEventManager.hasBeginListeners()) - _transEventManager.fireEvent(new TransactionEvent(this, + if (_transEventManager.hasBeginListeners()) + fireTransactionEvent(new TransactionEvent(this, TransactionEvent.AFTER_BEGIN, null, null, null, null)); } catch (OpenJPAException ke) { // if we already started the transaction, don't let it commit @@ -1755,9 +1794,8 @@ public class BrokerImpl _flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_TRANS_ENDING; - if (_transEventManager != null - && _transEventManager.hasEndListeners()) { - _transEventManager.fireEvent(new TransactionEvent(this, + if (_transEventManager.hasEndListeners()) { + fireTransactionEvent(new TransactionEvent(this, status == Status.STATUS_COMMITTED ? TransactionEvent.AFTER_COMMIT_COMPLETE : TransactionEvent.AFTER_ROLLBACK_COMPLETE, @@ -1804,8 +1842,7 @@ public class BrokerImpl // special case the remote commit listener used by the datacache cause // we know it doesn't require the commit event when nothing changes boolean flush = (_flags & FLAG_FLUSH_REQUIRED) != 0; - boolean listeners = _transEventManager != null - && (_transEventManager.hasFlushListeners() + boolean listeners = (_transEventManager.hasFlushListeners() || _transEventManager.hasEndListeners()) && ((_flags & FLAG_REMOTE_LISTENER) == 0 || _transEventManager.getListeners().size() > 1); @@ -1840,26 +1877,25 @@ public class BrokerImpl if ((_flags & FLAG_STORE_ACTIVE) == 0) beginStoreManagerTransaction(false); - if (_transEventManager != null - && (_transEventManager.hasFlushListeners() + if ((_transEventManager.hasFlushListeners() || _transEventManager.hasEndListeners()) && (flush || reason == FLUSH_COMMIT)) { // fire events mobjs = new ManagedObjectCollection(transactional); if (reason == FLUSH_COMMIT && _transEventManager.hasEndListeners()) { - _transEventManager.fireEvent(new TransactionEvent - (this, TransactionEvent.BEFORE_COMMIT, mobjs, - _persistedClss, _updatedClss, _deletedClss)); + fireTransactionEvent(new TransactionEvent(this, + TransactionEvent.BEFORE_COMMIT, mobjs, + _persistedClss, _updatedClss, _deletedClss)); flushAdditions(transactional, reason); flush = (_flags & FLAG_FLUSH_REQUIRED) != 0; } if (flush && _transEventManager.hasFlushListeners()) { - _transEventManager.fireEvent(new TransactionEvent - (this, TransactionEvent.BEFORE_FLUSH, mobjs, - _persistedClss, _updatedClss, _deletedClss)); + fireTransactionEvent(new TransactionEvent(this, + TransactionEvent.BEFORE_FLUSH, mobjs, + _persistedClss, _updatedClss, _deletedClss)); flushAdditions(transactional, reason); } } @@ -1922,9 +1958,8 @@ public class BrokerImpl throwNestedExceptions(exceps, true); if (flush && reason != FLUSH_ROLLBACK && reason != FLUSH_LOGICAL - && _transEventManager != null && _transEventManager.hasFlushListeners()) { - _transEventManager.fireEvent(new TransactionEvent(this, + fireTransactionEvent(new TransactionEvent(this, TransactionEvent.AFTER_FLUSH, mobjs, _persistedClss, _updatedClss, _deletedClss)); } @@ -2064,13 +2099,12 @@ public class BrokerImpl // fire after rollback/commit event Collection mobjs = null; - if (_transEventManager != null && _transEventManager.hasEndListeners()) - { + if (_transEventManager.hasEndListeners()) { mobjs = new ManagedObjectCollection(transStates); int eventType = (rollback) ? TransactionEvent.AFTER_ROLLBACK : TransactionEvent.AFTER_COMMIT; - _transEventManager.fireEvent(new TransactionEvent(this, eventType, - mobjs, _persistedClss, _updatedClss, _deletedClss)); + fireTransactionEvent(new TransactionEvent(this, eventType, mobjs, + _persistedClss, _updatedClss, _deletedClss)); } // null transactional caches now so that all the removeFromTransaction @@ -2130,10 +2164,9 @@ public class BrokerImpl _savepointCache = null; // fire after state change event - if (_transEventManager != null && _transEventManager.hasEndListeners()) - _transEventManager.fireEvent(new TransactionEvent(this, - TransactionEvent.AFTER_STATE_TRANSITIONS, mobjs, null, null, - null)); + if (_transEventManager.hasEndListeners()) + fireTransactionEvent(new TransactionEvent(this, TransactionEvent. + AFTER_STATE_TRANSITIONS, mobjs, null, null, null)); // now clear trans cache; keep cleared version rather than // null to avoid having to re-create the set later; more efficient diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java index cb59ed5c0..d00731871 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java @@ -794,6 +794,22 @@ public class DelegatingBroker } } + public int getTransactionListenerCallbackMode() { + try { + return _broker.getTransactionListenerCallbackMode(); + } catch (RuntimeException re) { + throw translate(re); + } + } + + public void setTransactionListenerCallbackMode(int mode) { + try { + _broker.setTransactionListenerCallbackMode(mode); + } catch (RuntimeException re) { + throw translate(re); + } + } + public void addLifecycleListener(Object listener, Class[] classes) { try { _broker.addLifecycleListener(listener, classes); @@ -810,6 +826,22 @@ public class DelegatingBroker } } + public int getLifecycleListenerCallbackMode() { + try { + return _broker.getLifecycleListenerCallbackMode(); + } catch (RuntimeException re) { + throw translate(re); + } + } + + public void setLifecycleListenerCallbackMode(int mode) { + try { + _broker.setLifecycleListenerCallbackMode(mode); + } catch (RuntimeException re) { + throw translate(re); + } + } + public LifecycleEventManager getLifecycleEventManager() { try { return _broker.getLifecycleEventManager(); diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties index eedb15dc7..f6eee3f5e 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/kernel/localizer.properties @@ -320,7 +320,8 @@ savepoint-init: This savepoint has already been initialized. savepoint-flush-not-supported: The configured SavepointManager does not \ support incremental flushing when a savepoint has been set. You must \ release your savepoints before flushing. -callback-err: An error occured processing callbacks for instance of type "{0}". +callback-err: Errors occured processing listener callbacks. See the nested \ + exceptions for details. bad-agg-listener-hint: Query hint value "{0}" ({1}) cannot be converted into \ an aggregate listener. bad-filter-listener-hint: Query hint value "{0}" ({1}) cannot be converted \ diff --git a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/AbstractConcurrentEventManager.java b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/AbstractConcurrentEventManager.java index fa2f22f16..ca6d25abf 100644 --- a/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/AbstractConcurrentEventManager.java +++ b/openjpa-lib/src/main/java/org/apache/openjpa/lib/util/concurrent/AbstractConcurrentEventManager.java @@ -37,6 +37,7 @@ public abstract class AbstractConcurrentEventManager implements EventManager { private static Exception[] EMPTY_EXCEPTIONS = new Exception[0]; private final Collection _listeners; + private boolean _failFast = false; /** * Default constructor. @@ -45,6 +46,20 @@ public abstract class AbstractConcurrentEventManager implements EventManager { _listeners = newListenerCollection(); } + /** + * Whether to fail after the first exception thrown by any listener. + */ + public boolean isFailFast() { + return _failFast; + } + + /** + * Whether to fail after the first exception thrown by any listener. + */ + public void setFailFast(boolean failFast) { + _failFast = failFast; + } + /** * Register an event listener. */ @@ -93,6 +108,8 @@ public abstract class AbstractConcurrentEventManager implements EventManager { try { fireEvent(event, itr.next()); } catch (Exception e) { + if (_failFast) + return new Exception[] { e }; if (exceptions == null) exceptions = new LinkedList(); exceptions.add(e); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java index a6bbef2ad..ebff6a8e0 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java @@ -283,6 +283,14 @@ public class EntityManagerImpl _broker.removeTransactionListener(listener); } + public int getTransactionListenerCallbackMode() { + return _broker.getTransactionListenerCallbackMode(); + } + + public void setTransactionListenerCallbackMode(int mode) { + _broker.setTransactionListenerCallbackMode(mode); + } + public void addLifecycleListener(Object listener, Class... classes) { _broker.addLifecycleListener(listener, classes); } @@ -291,6 +299,14 @@ public class EntityManagerImpl _broker.removeLifecycleListener(listener); } + public int getLifecycleListenerCallbackMode() { + return _broker.getLifecycleListenerCallbackMode(); + } + + public void setLifecycleListenerCallbackMode(int mode) { + _broker.setLifecycleListenerCallbackMode(mode); + } + @SuppressWarnings("unchecked") public T getReference(Class cls, Object oid) { oid = _broker.newObjectId(cls, oid); diff --git a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java index 9a6a2e13d..2fec8f707 100644 --- a/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java +++ b/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/OpenJPAEntityManager.java @@ -23,6 +23,7 @@ import javax.persistence.Query; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.ee.ManagedRuntime; +import org.apache.openjpa.event.CallbackModes; import org.apache.openjpa.kernel.AutoClear; import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.ConnectionRetainModes; @@ -41,7 +42,7 @@ public interface OpenJPAEntityManager extends EntityManager, EntityTransaction, javax.resource.cci.Connection, javax.resource.cci.LocalTransaction, javax.resource.spi.LocalTransaction, Closeable, ConnectionRetainModes, DetachState, RestoreState, AutoDetach, - AutoClear { + AutoClear, CallbackModes { /** * Return the factory that produced this entity manager. @@ -300,6 +301,18 @@ public interface OpenJPAEntityManager */ public void removeTransactionListener(Object listener); + /** + * The {@link CallbackModes} flags for handling transaction listener + * exceptions. + */ + public int getTransactionListenerCallbackMode(); + + /** + * The {@link CallbackModes} flags for handling transaction listener + * exceptions. + */ + public void setTransactionListenerCallbackMode(int callbackMode); + /** * Register a listener for lifecycle-related events on the specified * classes. If the classes are null, all events will be propagated to @@ -312,6 +325,18 @@ public interface OpenJPAEntityManager */ public void removeLifecycleListener(Object listener); + /** + * The {@link CallbackModes} flags for handling lifecycle listener + * exceptions. + */ + public int getLifecycleListenerCallbackMode(); + + /** + * The {@link CallbackModes} flags for handling lifecycle listener + * exceptions. + */ + public void setLifecycleListenerCallbackMode(int callbackMode); + /////////// // Lookups ///////////