mirror of https://github.com/apache/openjpa.git
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:
parent
88acae75c1
commit
8785be46e7
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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> T getReference(Class<T> cls, Object oid) {
|
||||
oid = _broker.newObjectId(cls, oid);
|
||||
|
|
|
@ -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
|
||||
///////////
|
||||
|
|
Loading…
Reference in New Issue