Handle exceptions from transaction listeners appropriately. Allow user to

override default CallbackMode for both lifecycle and transaction listeners.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@452981 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2006-10-04 19:12:34 +00:00
parent 88acae75c1
commit 8785be46e7
8 changed files with 236 additions and 82 deletions

View File

@ -52,6 +52,21 @@ public class LifecycleEventManager
private List _exceps = new LinkedList(); private List _exceps = new LinkedList();
private boolean _firing = false; private boolean _firing = false;
private boolean _fail = 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 * Register a lifecycle listener for the given classes. If the classes
@ -207,22 +222,19 @@ public class LifecycleEventManager
ClassMetaData meta, int type) { ClassMetaData meta, int type) {
if (meta.getLifecycleMetaData().getIgnoreSystemListeners()) if (meta.getLifecycleMetaData().getIgnoreSystemListeners())
return false; return false;
boolean failFast = (meta.getRepository().getMetaDataFactory(). if (fireEvent(null, source, null, type, _listeners, true, null)
getDefaults().getCallbackMode() & CALLBACK_FAIL_FAST) != 0; == Boolean.TRUE)
if (fireEvent(null, source, null, type, _listeners, true, failFast,
null) == Boolean.TRUE)
return true; return true;
ListenerList system = meta.getRepository().getSystemListeners(); ListenerList system = meta.getRepository().getSystemListeners();
if (!system.isEmpty() && fireEvent(null, source, null, type, system, if (!system.isEmpty() && fireEvent(null, source, null, type, system,
true, failFast, null) == Boolean.TRUE) true, null) == Boolean.TRUE)
return true; return true;
if (_classListeners != null) { if (_classListeners != null) {
Class c = source == null ? meta.getDescribedType() : Class c = source == null ? meta.getDescribedType() :
source.getClass(); source.getClass();
do { do {
if (fireEvent(null, source, null, type, (ListenerList) if (fireEvent(null, source, null, type, (ListenerList)
_classListeners.get(c), true, failFast, null) _classListeners.get(c), true, null) == Boolean.TRUE)
== Boolean.TRUE)
return true; return true;
c = c.getSuperclass(); c = c.getSuperclass();
} while (c != null && c != Object.class); } while (c != null && c != Object.class);
@ -250,21 +262,18 @@ public class LifecycleEventManager
getDefaults(); getDefaults();
boolean callbacks = def.getCallbacksBeforeListeners(type); boolean callbacks = def.getCallbacksBeforeListeners(type);
boolean failFast = (def.getCallbackMode() & CALLBACK_FAIL_FAST) != 0;
if (callbacks) if (callbacks)
makeCallbacks(source, related, meta, type, failFast, exceptions); makeCallbacks(source, related, meta, type, exceptions);
LifecycleEvent ev = (LifecycleEvent) fireEvent(null, source, related, LifecycleEvent ev = (LifecycleEvent) fireEvent(null, source, related,
type, _listeners, false, failFast, exceptions); type, _listeners, false, exceptions);
if (_classListeners != null) { if (_classListeners != null) {
Class c = source == null ? meta.getDescribedType() : Class c = source == null ? meta.getDescribedType() :
source.getClass(); source.getClass();
do { do {
ev = (LifecycleEvent) fireEvent(ev, source, related, type, ev = (LifecycleEvent) fireEvent(ev, source, related, type,
(ListenerList) _classListeners.get(c), false, failFast, (ListenerList) _classListeners.get(c), false, exceptions);
exceptions);
c = c.getSuperclass(); c = c.getSuperclass();
} while (c != null && c != Object.class); } while (c != null && c != Object.class);
} }
@ -272,12 +281,11 @@ public class LifecycleEventManager
// make system listeners // make system listeners
if (!meta.getLifecycleMetaData().getIgnoreSystemListeners()) { if (!meta.getLifecycleMetaData().getIgnoreSystemListeners()) {
ListenerList system = meta.getRepository().getSystemListeners(); ListenerList system = meta.getRepository().getSystemListeners();
fireEvent(ev, source, related, type, system, false, failFast, fireEvent(ev, source, related, type, system, false, exceptions);
exceptions);
} }
if (!callbacks) if (!callbacks)
makeCallbacks(source, related, meta, type, failFast, exceptions); makeCallbacks(source, related, meta, type, exceptions);
// create return array before clearing exceptions // create return array before clearing exceptions
Exception[] ret; Exception[] ret;
@ -309,7 +317,7 @@ public class LifecycleEventManager
* Make callbacks, recording any exceptions in the given collection. * Make callbacks, recording any exceptions in the given collection.
*/ */
private void makeCallbacks(Object source, Object related, private void makeCallbacks(Object source, Object related,
ClassMetaData meta, int type, boolean failFast, Collection exceptions) { ClassMetaData meta, int type, Collection exceptions) {
// make lifecycle callbacks // make lifecycle callbacks
LifecycleCallbacks[] callbacks = meta.getLifecycleMetaData(). LifecycleCallbacks[] callbacks = meta.getLifecycleMetaData().
getCallbacks(type); getCallbacks(type);
@ -318,7 +326,7 @@ public class LifecycleEventManager
callbacks[i].makeCallback(source, related, type); callbacks[i].makeCallback(source, related, type);
} catch (Exception e) { } catch (Exception e) {
exceptions.add(e); exceptions.add(e);
if (failFast) if (_failFast)
_fail = true; _fail = true;
} }
} }
@ -329,8 +337,7 @@ public class LifecycleEventManager
* listeners. The event may have already been constructed. * listeners. The event may have already been constructed.
*/ */
private Object fireEvent(LifecycleEvent ev, Object source, Object rel, private Object fireEvent(LifecycleEvent ev, Object source, Object rel,
int type, ListenerList listeners, boolean mock, boolean failFast, int type, ListenerList listeners, boolean mock, List exceptions) {
List exceptions) {
if (listeners == null || !listeners.hasListeners(type)) if (listeners == null || !listeners.hasListeners(type))
return null; return null;
@ -471,7 +478,7 @@ public class LifecycleEventManager
} }
catch (Exception e) { catch (Exception e) {
exceptions.add(e); exceptions.add(e);
if (failFast) if (_failFast)
_fail = true; _fail = true;
} }
} }

View File

@ -21,6 +21,7 @@ import javax.resource.cci.LocalTransaction;
import javax.transaction.Synchronization; import javax.transaction.Synchronization;
import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.event.CallbackModes;
import org.apache.openjpa.event.LifecycleEventManager; import org.apache.openjpa.event.LifecycleEventManager;
import org.apache.openjpa.lib.util.Closeable; import org.apache.openjpa.lib.util.Closeable;
import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.meta.ClassMetaData;
@ -40,7 +41,7 @@ public interface Broker
extends Synchronization, Connection, LocalTransaction, extends Synchronization, Connection, LocalTransaction,
javax.resource.spi.LocalTransaction, Closeable, StoreContext, javax.resource.spi.LocalTransaction, Closeable, StoreContext,
ConnectionRetainModes, DetachState, LockLevels, ConnectionRetainModes, DetachState, LockLevels,
RestoreState, AutoClear, AutoDetach { RestoreState, AutoClear, AutoDetach, CallbackModes {
/** /**
* Set the broker's behavior for implicit actions such as flushing, * Set the broker's behavior for implicit actions such as flushing,
@ -240,6 +241,18 @@ public interface Broker
*/ */
public void removeTransactionListener(Object listener); 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 * Register a listener for lifecycle-related events on the specified
* classes. If the classes are null, all events will be propagated to * classes. If the classes are null, all events will be propagated to
@ -261,6 +274,16 @@ public interface Broker
*/ */
public LifecycleEventManager getLifecycleEventManager(); 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. * Begin a transaction.
*/ */

View File

@ -212,7 +212,6 @@ public class BrokerImpl
private int _autoDetach = 0; private int _autoDetach = 0;
private int _detachState = DETACH_LOADED; private int _detachState = DETACH_LOADED;
private boolean _detachedNew = true; private boolean _detachedNew = true;
private int _callbackMode = CallbackModes.CALLBACK_IGNORE;
private boolean _orderDirty = false; private boolean _orderDirty = false;
// status // status
@ -221,7 +220,9 @@ public class BrokerImpl
// event managers // event managers
private TransactionEventManager _transEventManager = null; private TransactionEventManager _transEventManager = null;
private int _transCallbackMode = 0;
private LifecycleEventManager _lifeEventManager = null; private LifecycleEventManager _lifeEventManager = null;
private int _lifeCallbackMode = 0;
/** /**
* Set the persistence manager's authentication. This is the first * Set the persistence manager's authentication. This is the first
@ -251,13 +252,10 @@ public class BrokerImpl
DelegatingStoreManager sm, boolean managed, int connMode) { DelegatingStoreManager sm, boolean managed, int connMode) {
_conf = factory.getConfiguration(); _conf = factory.getConfiguration();
_compat = _conf.getCompatibilityInstance(); _compat = _conf.getCompatibilityInstance();
_factory = factory; _factory = factory;
_log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); _log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME);
_cache = new ManagedCache(newManagedObjectCache()); _cache = new ManagedCache(newManagedObjectCache());
_lifeEventManager = new LifecycleEventManager(); _operating = MapBackedSet.decorate(new IdentityMap());
_callbackMode = _conf.getMetaDataRepositoryInstance().
getMetaDataFactory(). getDefaults().getCallbackMode();
_connRetainMode = connMode; _connRetainMode = connMode;
_managed = managed; _managed = managed;
if (managed) if (managed)
@ -265,9 +263,15 @@ public class BrokerImpl
else else
_runtime = new LocalManagedRuntime(this); _runtime = new LocalManagedRuntime(this);
_lifeEventManager = new LifecycleEventManager();
_transEventManager = new TransactionEventManager();
int cmode = _conf.getMetaDataRepositoryInstance().
getMetaDataFactory().getDefaults().getCallbackMode();
setLifecycleListenerCallbackMode(cmode);
setTransactionListenerCallbackMode(cmode);
// setup default options // setup default options
_factory.configureBroker(this); _factory.configureBroker(this);
_operating = MapBackedSet.decorate(new IdentityMap());
// make sure to do this after configuring broker so that store manager // make sure to do this after configuring broker so that store manager
// can look to broker configuration; we set both store and lock managers // 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. * 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, boolean fireLifecycleEvent(Object src, Object related, ClassMetaData meta,
int eventType) { int eventType) {
if (_lifeEventManager == null) // uninitialized if (_lifeEventManager == null)
return false; return false;
handleCallbackExceptions(_lifeEventManager.fireEvent(src, related,
Exception[] exceps = _lifeEventManager.fireEvent(src, related, meta, meta, eventType), _lifeCallbackMode);
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;
return true; 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) { public void addTransactionListener(Object tl) {
beginOperation(false); beginOperation(false);
try { try {
if (_transEventManager == null)
_transEventManager = new TransactionEventManager();
_transEventManager.addListener(tl); _transEventManager.addListener(tl);
if (tl instanceof RemoteCommitEventManager) if (tl instanceof RemoteCommitEventManager)
_flags |= FLAG_REMOTE_LISTENER; _flags |= FLAG_REMOTE_LISTENER;
@ -678,8 +694,7 @@ public class BrokerImpl
public void removeTransactionListener(Object tl) { public void removeTransactionListener(Object tl) {
beginOperation(false); beginOperation(false);
try { try {
if (_transEventManager != null if (_transEventManager.removeListener(tl)
&& _transEventManager.removeListener(tl)
&& (tl instanceof RemoteCommitEventManager)) && (tl instanceof RemoteCommitEventManager))
_flags &= ~FLAG_REMOTE_LISTENER; _flags &= ~FLAG_REMOTE_LISTENER;
} finally { } 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 // Lookups
/////////// ///////////
@ -1151,9 +1191,8 @@ public class BrokerImpl
} }
_lm.beginTransaction(); _lm.beginTransaction();
if (_transEventManager != null if (_transEventManager.hasBeginListeners())
&& _transEventManager.hasBeginListeners()) fireTransactionEvent(new TransactionEvent(this,
_transEventManager.fireEvent(new TransactionEvent(this,
TransactionEvent.AFTER_BEGIN, null, null, null, null)); TransactionEvent.AFTER_BEGIN, null, null, null, null));
} catch (OpenJPAException ke) { } catch (OpenJPAException ke) {
// if we already started the transaction, don't let it commit // if we already started the transaction, don't let it commit
@ -1755,9 +1794,8 @@ public class BrokerImpl
_flags &= ~FLAG_FLUSHED; _flags &= ~FLAG_FLUSHED;
_flags &= ~FLAG_TRANS_ENDING; _flags &= ~FLAG_TRANS_ENDING;
if (_transEventManager != null if (_transEventManager.hasEndListeners()) {
&& _transEventManager.hasEndListeners()) { fireTransactionEvent(new TransactionEvent(this,
_transEventManager.fireEvent(new TransactionEvent(this,
status == Status.STATUS_COMMITTED status == Status.STATUS_COMMITTED
? TransactionEvent.AFTER_COMMIT_COMPLETE ? TransactionEvent.AFTER_COMMIT_COMPLETE
: TransactionEvent.AFTER_ROLLBACK_COMPLETE, : TransactionEvent.AFTER_ROLLBACK_COMPLETE,
@ -1804,8 +1842,7 @@ public class BrokerImpl
// special case the remote commit listener used by the datacache cause // special case the remote commit listener used by the datacache cause
// we know it doesn't require the commit event when nothing changes // we know it doesn't require the commit event when nothing changes
boolean flush = (_flags & FLAG_FLUSH_REQUIRED) != 0; boolean flush = (_flags & FLAG_FLUSH_REQUIRED) != 0;
boolean listeners = _transEventManager != null boolean listeners = (_transEventManager.hasFlushListeners()
&& (_transEventManager.hasFlushListeners()
|| _transEventManager.hasEndListeners()) || _transEventManager.hasEndListeners())
&& ((_flags & FLAG_REMOTE_LISTENER) == 0 && ((_flags & FLAG_REMOTE_LISTENER) == 0
|| _transEventManager.getListeners().size() > 1); || _transEventManager.getListeners().size() > 1);
@ -1840,26 +1877,25 @@ public class BrokerImpl
if ((_flags & FLAG_STORE_ACTIVE) == 0) if ((_flags & FLAG_STORE_ACTIVE) == 0)
beginStoreManagerTransaction(false); beginStoreManagerTransaction(false);
if (_transEventManager != null if ((_transEventManager.hasFlushListeners()
&& (_transEventManager.hasFlushListeners()
|| _transEventManager.hasEndListeners()) || _transEventManager.hasEndListeners())
&& (flush || reason == FLUSH_COMMIT)) { && (flush || reason == FLUSH_COMMIT)) {
// fire events // fire events
mobjs = new ManagedObjectCollection(transactional); mobjs = new ManagedObjectCollection(transactional);
if (reason == FLUSH_COMMIT if (reason == FLUSH_COMMIT
&& _transEventManager.hasEndListeners()) { && _transEventManager.hasEndListeners()) {
_transEventManager.fireEvent(new TransactionEvent fireTransactionEvent(new TransactionEvent(this,
(this, TransactionEvent.BEFORE_COMMIT, mobjs, TransactionEvent.BEFORE_COMMIT, mobjs,
_persistedClss, _updatedClss, _deletedClss)); _persistedClss, _updatedClss, _deletedClss));
flushAdditions(transactional, reason); flushAdditions(transactional, reason);
flush = (_flags & FLAG_FLUSH_REQUIRED) != 0; flush = (_flags & FLAG_FLUSH_REQUIRED) != 0;
} }
if (flush && _transEventManager.hasFlushListeners()) { if (flush && _transEventManager.hasFlushListeners()) {
_transEventManager.fireEvent(new TransactionEvent fireTransactionEvent(new TransactionEvent(this,
(this, TransactionEvent.BEFORE_FLUSH, mobjs, TransactionEvent.BEFORE_FLUSH, mobjs,
_persistedClss, _updatedClss, _deletedClss)); _persistedClss, _updatedClss, _deletedClss));
flushAdditions(transactional, reason); flushAdditions(transactional, reason);
} }
} }
@ -1922,9 +1958,8 @@ public class BrokerImpl
throwNestedExceptions(exceps, true); throwNestedExceptions(exceps, true);
if (flush && reason != FLUSH_ROLLBACK && reason != FLUSH_LOGICAL if (flush && reason != FLUSH_ROLLBACK && reason != FLUSH_LOGICAL
&& _transEventManager != null
&& _transEventManager.hasFlushListeners()) { && _transEventManager.hasFlushListeners()) {
_transEventManager.fireEvent(new TransactionEvent(this, fireTransactionEvent(new TransactionEvent(this,
TransactionEvent.AFTER_FLUSH, mobjs, _persistedClss, TransactionEvent.AFTER_FLUSH, mobjs, _persistedClss,
_updatedClss, _deletedClss)); _updatedClss, _deletedClss));
} }
@ -2064,13 +2099,12 @@ public class BrokerImpl
// fire after rollback/commit event // fire after rollback/commit event
Collection mobjs = null; Collection mobjs = null;
if (_transEventManager != null && _transEventManager.hasEndListeners()) if (_transEventManager.hasEndListeners()) {
{
mobjs = new ManagedObjectCollection(transStates); mobjs = new ManagedObjectCollection(transStates);
int eventType = (rollback) ? TransactionEvent.AFTER_ROLLBACK int eventType = (rollback) ? TransactionEvent.AFTER_ROLLBACK
: TransactionEvent.AFTER_COMMIT; : TransactionEvent.AFTER_COMMIT;
_transEventManager.fireEvent(new TransactionEvent(this, eventType, fireTransactionEvent(new TransactionEvent(this, eventType, mobjs,
mobjs, _persistedClss, _updatedClss, _deletedClss)); _persistedClss, _updatedClss, _deletedClss));
} }
// null transactional caches now so that all the removeFromTransaction // null transactional caches now so that all the removeFromTransaction
@ -2130,10 +2164,9 @@ public class BrokerImpl
_savepointCache = null; _savepointCache = null;
// fire after state change event // fire after state change event
if (_transEventManager != null && _transEventManager.hasEndListeners()) if (_transEventManager.hasEndListeners())
_transEventManager.fireEvent(new TransactionEvent(this, fireTransactionEvent(new TransactionEvent(this, TransactionEvent.
TransactionEvent.AFTER_STATE_TRANSITIONS, mobjs, null, null, AFTER_STATE_TRANSITIONS, mobjs, null, null, null));
null));
// now clear trans cache; keep cleared version rather than // now clear trans cache; keep cleared version rather than
// null to avoid having to re-create the set later; more efficient // null to avoid having to re-create the set later; more efficient

View File

@ -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) { public void addLifecycleListener(Object listener, Class[] classes) {
try { try {
_broker.addLifecycleListener(listener, classes); _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() { public LifecycleEventManager getLifecycleEventManager() {
try { try {
return _broker.getLifecycleEventManager(); return _broker.getLifecycleEventManager();

View File

@ -320,7 +320,8 @@ savepoint-init: This savepoint has already been initialized.
savepoint-flush-not-supported: The configured SavepointManager does not \ savepoint-flush-not-supported: The configured SavepointManager does not \
support incremental flushing when a savepoint has been set. You must \ support incremental flushing when a savepoint has been set. You must \
release your savepoints before flushing. 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 \ bad-agg-listener-hint: Query hint value "{0}" ({1}) cannot be converted into \
an aggregate listener. an aggregate listener.
bad-filter-listener-hint: Query hint value "{0}" ({1}) cannot be converted \ bad-filter-listener-hint: Query hint value "{0}" ({1}) cannot be converted \

View File

@ -37,6 +37,7 @@ public abstract class AbstractConcurrentEventManager implements EventManager {
private static Exception[] EMPTY_EXCEPTIONS = new Exception[0]; private static Exception[] EMPTY_EXCEPTIONS = new Exception[0];
private final Collection _listeners; private final Collection _listeners;
private boolean _failFast = false;
/** /**
* Default constructor. * Default constructor.
@ -45,6 +46,20 @@ public abstract class AbstractConcurrentEventManager implements EventManager {
_listeners = newListenerCollection(); _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. * Register an event listener.
*/ */
@ -93,6 +108,8 @@ public abstract class AbstractConcurrentEventManager implements EventManager {
try { try {
fireEvent(event, itr.next()); fireEvent(event, itr.next());
} catch (Exception e) { } catch (Exception e) {
if (_failFast)
return new Exception[] { e };
if (exceptions == null) if (exceptions == null)
exceptions = new LinkedList(); exceptions = new LinkedList();
exceptions.add(e); exceptions.add(e);

View File

@ -283,6 +283,14 @@ public class EntityManagerImpl
_broker.removeTransactionListener(listener); _broker.removeTransactionListener(listener);
} }
public int getTransactionListenerCallbackMode() {
return _broker.getTransactionListenerCallbackMode();
}
public void setTransactionListenerCallbackMode(int mode) {
_broker.setTransactionListenerCallbackMode(mode);
}
public void addLifecycleListener(Object listener, Class... classes) { public void addLifecycleListener(Object listener, Class... classes) {
_broker.addLifecycleListener(listener, classes); _broker.addLifecycleListener(listener, classes);
} }
@ -291,6 +299,14 @@ public class EntityManagerImpl
_broker.removeLifecycleListener(listener); _broker.removeLifecycleListener(listener);
} }
public int getLifecycleListenerCallbackMode() {
return _broker.getLifecycleListenerCallbackMode();
}
public void setLifecycleListenerCallbackMode(int mode) {
_broker.setLifecycleListenerCallbackMode(mode);
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T> T getReference(Class<T> cls, Object oid) { public <T> T getReference(Class<T> cls, Object oid) {
oid = _broker.newObjectId(cls, oid); oid = _broker.newObjectId(cls, oid);

View File

@ -23,6 +23,7 @@ import javax.persistence.Query;
import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.conf.OpenJPAConfiguration;
import org.apache.openjpa.ee.ManagedRuntime; import org.apache.openjpa.ee.ManagedRuntime;
import org.apache.openjpa.event.CallbackModes;
import org.apache.openjpa.kernel.AutoClear; import org.apache.openjpa.kernel.AutoClear;
import org.apache.openjpa.kernel.AutoDetach; import org.apache.openjpa.kernel.AutoDetach;
import org.apache.openjpa.kernel.ConnectionRetainModes; import org.apache.openjpa.kernel.ConnectionRetainModes;
@ -41,7 +42,7 @@ public interface OpenJPAEntityManager
extends EntityManager, EntityTransaction, javax.resource.cci.Connection, extends EntityManager, EntityTransaction, javax.resource.cci.Connection,
javax.resource.cci.LocalTransaction, javax.resource.spi.LocalTransaction, javax.resource.cci.LocalTransaction, javax.resource.spi.LocalTransaction,
Closeable, ConnectionRetainModes, DetachState, RestoreState, AutoDetach, Closeable, ConnectionRetainModes, DetachState, RestoreState, AutoDetach,
AutoClear { AutoClear, CallbackModes {
/** /**
* Return the factory that produced this entity manager. * Return the factory that produced this entity manager.
@ -300,6 +301,18 @@ public interface OpenJPAEntityManager
*/ */
public void removeTransactionListener(Object listener); 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 * Register a listener for lifecycle-related events on the specified
* classes. If the classes are null, all events will be propagated to * classes. If the classes are null, all events will be propagated to
@ -312,6 +325,18 @@ public interface OpenJPAEntityManager
*/ */
public void removeLifecycleListener(Object listener); 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 // Lookups
/////////// ///////////