@Override
public Object processInvocation(final InterceptorContext context) throws Exception {
final StatefulSessionComponent component = getComponent(context, StatefulSessionComponent.class);
final StatefulSessionComponentInstance instance = getComponentInstance(context);
final TransactionSynchronizationRegistry transactionSynchronizationRegistry = component.getTransactionSynchronizationRegistry();
final Object lockOwner = getLockOwner(transactionSynchronizationRegistry);
lock.pushOwner(lockOwner);
try {
final AccessTimeoutDetails timeout = component.getAccessTimeout(context.getMethod());
if (ROOT_LOGGER.isTraceEnabled()) {
ROOT_LOGGER.trace("Trying to acquire lock: " + lock + " for stateful component instance: " + instance + " during invocation: " + context);
}
// we obtain a lock in this synchronization interceptor because the lock needs to be tied to the synchronization
// so that it can released on the tx synchronization callbacks
boolean acquired = lock.tryLock(timeout.getValue(), timeout.getTimeUnit());
if (!acquired) {
throw MESSAGES.failToObtainLock(context, timeout.getValue(), timeout.getTimeUnit());
}
synchronized (threadLock) {
if (ROOT_LOGGER.isTraceEnabled()) {
ROOT_LOGGER.trace("Acquired lock: " + lock + " for stateful component instance: " + instance + " during invocation: " + context);
}
Object currentTransactionKey = null;
boolean wasTxSyncRegistered = false;
try {
//we never register a sync for bean managed transactions
//the inner BMT interceptor is going to setup the correct transaction anyway
//so enrolling in an existing transaction is not correct
if(containerManagedTransactions) {
if (!synchronizationRegistered) {
// get the key to current transaction associated with this thread
currentTransactionKey = transactionSynchronizationRegistry.getTransactionKey();
final int status = transactionSynchronizationRegistry.getTransactionStatus();
// if this SFSB instance is already associated with a different transaction, then it's an error
// if the thread is currently associated with a tx, then register a tx synchronization
if (currentTransactionKey != null && status != Status.STATUS_COMMITTED) {
// register a tx synchronization for this SFSB instance
final Synchronization statefulSessionSync = new StatefulSessionSynchronization(instance, lockOwner);
transactionSynchronizationRegistry.registerInterposedSynchronization(statefulSessionSync);
wasTxSyncRegistered = true;
if (ROOT_LOGGER.isTraceEnabled()) {
ROOT_LOGGER.trace("Registered tx synchronization: " + statefulSessionSync + " for tx: " + currentTransactionKey +
" associated with stateful component instance: " + instance);
}