Search in sources :

Example 1 with StatefulSessionComponentInstance

use of org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance in project wildfly by wildfly.

the class StatefulSessionSynchronizationInterceptor method processInvocation.

@Override
public Object processInvocation(final InterceptorContext context) throws Exception {
    final StatefulSessionComponent component = getComponent(context, StatefulSessionComponent.class);
    final StatefulSessionComponentInstance instance = getComponentInstance(context);
    final OwnableReentrantLock lock = instance.getLock();
    final Object threadLock = instance.getThreadLock();
    final AtomicInteger invocationSyncState = instance.getInvocationSynchState();
    final TransactionSynchronizationRegistry transactionSynchronizationRegistry = component.getTransactionSynchronizationRegistry();
    final Object lockOwner = getLockOwner(transactionSynchronizationRegistry);
    final AccessTimeoutDetails timeout = component.getAccessTimeout(context.getMethod());
    boolean toDiscard = false;
    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(), lockOwner);
    if (!acquired) {
        throw EjbLogger.ROOT_LOGGER.failToObtainLock(component.getComponentName(), timeout.getValue(), timeout.getTimeUnit());
    }
    synchronized (threadLock) {
        //invocation in progress
        invocationSyncState.set(SYNC_STATE_INVOCATION_IN_PROGRESS);
        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 {
            //so enrolling in an existing transaction is not correct
            if (containerManagedTransactions) {
                if (!instance.isSynchronizationRegistered()) {
                    // get the key to current transaction associated with this thread
                    currentTransactionKey = transactionSynchronizationRegistry.getTransactionKey();
                    final int status = transactionSynchronizationRegistry.getTransactionStatus();
                    // if the thread is currently associated with a tx, then register a tx synchronization
                    if (currentTransactionKey != null && status != Status.STATUS_COMMITTED && status != Status.STATUS_ROLLEDBACK) {
                        // register a tx synchronization for this SFSB instance
                        final Synchronization statefulSessionSync = new StatefulSessionSynchronization(instance);
                        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);
                        }
                        // invoke the afterBegin callback on the SFSB
                        instance.afterBegin();
                        instance.setSynchronizationRegistered(true);
                        context.putPrivateData(StatefulTransactionMarker.class, StatefulTransactionMarker.of(true));
                    }
                } else {
                    context.putPrivateData(StatefulTransactionMarker.class, StatefulTransactionMarker.of(false));
                }
            }
            // proceed with the invocation
            try {
                return context.proceed();
            } catch (Exception e) {
                if (component.shouldDiscard(e, context.getMethod())) {
                    toDiscard = true;
                }
                throw e;
            }
        } finally {
            // taken care off by a tx synchronization callbacks.
            if (!wasTxSyncRegistered && !instance.isSynchronizationRegistered()) {
                releaseInstance(instance);
            } else if (!wasTxSyncRegistered) {
                //if we don't release the lock here then it will be acquired multiple times
                //and only released once
                releaseLock(instance);
                //we also call the cache release to decrease the usage count
                if (!instance.isDiscarded()) {
                    instance.getComponent().getCache().release(instance);
                }
            }
            for (; ; ) {
                int state = invocationSyncState.get();
                if (state == SYNC_STATE_INVOCATION_IN_PROGRESS && invocationSyncState.compareAndSet(SYNC_STATE_INVOCATION_IN_PROGRESS, SYNC_STATE_NO_INVOCATION)) {
                    break;
                } else if (state == SYNC_STATE_AFTER_COMPLETE_DELAYED_COMMITTED || state == SYNC_STATE_AFTER_COMPLETE_DELAYED_NO_COMMIT) {
                    try {
                        //invoke the after completion method, other after completion syncs may have already run
                        handleAfterCompletion(state == SYNC_STATE_AFTER_COMPLETE_DELAYED_COMMITTED, instance, toDiscard);
                    } finally {
                        invocationSyncState.set(SYNC_STATE_NO_INVOCATION);
                    }
                } else {
                    EjbLogger.ROOT_LOGGER.unexpectedInvocationState(state);
                    break;
                }
            }
        }
    }
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) TransactionSynchronizationRegistry(javax.transaction.TransactionSynchronizationRegistry) OwnableReentrantLock(org.jboss.as.ejb3.tx.OwnableReentrantLock) AccessTimeoutDetails(org.jboss.as.ejb3.concurrency.AccessTimeoutDetails) Synchronization(javax.transaction.Synchronization) EJBException(javax.ejb.EJBException)

Example 2 with StatefulSessionComponentInstance

use of org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance in project wildfly by wildfly.

the class StatefulRemoveInterceptor method processInvocation.

@Override
public Object processInvocation(InterceptorContext context) throws Exception {
    final Component component = context.getPrivateData(Component.class);
    //if a session bean is participating in a transaction, it
    //is an error for a client to invoke the remove method
    //on the session object's home or component interface.
    final ComponentView view = context.getPrivateData(ComponentView.class);
    if (view != null) {
        Ejb2xViewType viewType = view.getPrivateData(Ejb2xViewType.class);
        if (viewType != null) {
            //this means it is an EJB 2.x view
            //which is not allowed to remove while enrolled in a TX
            final StatefulTransactionMarker marker = context.getPrivateData(StatefulTransactionMarker.class);
            if (marker != null && !marker.isFirstInvocation()) {
                throw EjbLogger.ROOT_LOGGER.cannotRemoveWhileParticipatingInTransaction();
            }
        }
    }
    // just log a WARN and throw back the original exception
    if (component instanceof StatefulSessionComponent == false) {
        throw EjbLogger.ROOT_LOGGER.unexpectedComponent(component, StatefulSessionComponent.class);
    }
    final StatefulSessionComponent statefulComponent = (StatefulSessionComponent) component;
    Object invocationResult = null;
    try {
        // proceed
        invocationResult = context.proceed();
    } catch (Exception e) {
        // then just throw back the exception and don't remove the session instance.
        if (this.isApplicationException(statefulComponent, e.getClass(), context.getMethod()) && this.retainIfException) {
            throw e;
        }
        // otherwise, just remove it and throw back the original exception
        final StatefulSessionComponentInstance statefulComponentInstance = (StatefulSessionComponentInstance) context.getPrivateData(ComponentInstance.class);
        final SessionID sessionId = statefulComponentInstance.getId();
        statefulComponent.removeSession(sessionId);
        throw e;
    }
    final StatefulSessionComponentInstance statefulComponentInstance = (StatefulSessionComponentInstance) context.getPrivateData(ComponentInstance.class);
    final SessionID sessionId = statefulComponentInstance.getId();
    // just remove the session because of a call to @Remove method
    statefulComponent.removeSession(sessionId);
    // return the invocation result
    return invocationResult;
}
Also used : ComponentView(org.jboss.as.ee.component.ComponentView) ComponentInstance(org.jboss.as.ee.component.ComponentInstance) Ejb2xViewType(org.jboss.as.ejb3.component.Ejb2xViewType) EJBComponent(org.jboss.as.ejb3.component.EJBComponent) Component(org.jboss.as.ee.component.Component) SessionID(org.jboss.ejb.client.SessionID)

Example 3 with StatefulSessionComponentInstance

use of org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance in project wildfly by wildfly.

the class StatefulBMTInterceptor method handleInvocation.

@Override
protected Object handleInvocation(final InterceptorContext invocation) throws Exception {
    final StatefulSessionComponentInstance instance = (StatefulSessionComponentInstance) invocation.getPrivateData(ComponentInstance.class);
    TransactionManager tm = getComponent().getTransactionManager();
    assert tm.getTransaction() == null : "can't handle BMT transaction, there is a transaction active";
    // Is the instance already associated with a transaction?
    Transaction tx = instance.getTransaction();
    if (tx != null) {
        // then resume that transaction.
        instance.setTransaction(null);
        tm.resume(tx);
    }
    try {
        return invocation.proceed();
    } catch (Throwable e) {
        throw this.handleException(invocation, e);
    } finally {
        checkBadStateful();
        // Is the instance finished with the transaction?
        Transaction newTx = tm.getTransaction();
        //always set it, even if null
        instance.setTransaction(newTx);
        if (newTx != null) {
            // remember the association
            // and suspend it.
            tm.suspend();
        }
    }
}
Also used : Transaction(javax.transaction.Transaction) StatefulSessionComponentInstance(org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance) TransactionManager(javax.transaction.TransactionManager) ComponentInstance(org.jboss.as.ee.component.ComponentInstance) StatefulSessionComponentInstance(org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance)

Aggregations

ComponentInstance (org.jboss.as.ee.component.ComponentInstance)2 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)1 EJBException (javax.ejb.EJBException)1 Synchronization (javax.transaction.Synchronization)1 Transaction (javax.transaction.Transaction)1 TransactionManager (javax.transaction.TransactionManager)1 TransactionSynchronizationRegistry (javax.transaction.TransactionSynchronizationRegistry)1 Component (org.jboss.as.ee.component.Component)1 ComponentView (org.jboss.as.ee.component.ComponentView)1 EJBComponent (org.jboss.as.ejb3.component.EJBComponent)1 Ejb2xViewType (org.jboss.as.ejb3.component.Ejb2xViewType)1 StatefulSessionComponentInstance (org.jboss.as.ejb3.component.stateful.StatefulSessionComponentInstance)1 AccessTimeoutDetails (org.jboss.as.ejb3.concurrency.AccessTimeoutDetails)1 OwnableReentrantLock (org.jboss.as.ejb3.tx.OwnableReentrantLock)1 SessionID (org.jboss.ejb.client.SessionID)1