Package org.ow2.easybeans.transaction.interceptors

Source Code of org.ow2.easybeans.transaction.interceptors.ListenerSessionSynchronizationInterceptor

/**
* EasyBeans
* Copyright (C) 2006 Bull S.A.S.
* Contact: easybeans@ow2.org
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
* USA
*
* --------------------------------------------------------------------------
* $Id: ListenerSessionSynchronizationInterceptor.java 5369 2010-02-24 14:58:19Z benoitf $
* --------------------------------------------------------------------------
*/

package org.ow2.easybeans.transaction.interceptors;

import java.rmi.RemoteException;
import java.util.Map;
import java.util.WeakHashMap;

import javax.ejb.EJBException;
import javax.ejb.SessionSynchronization;
import javax.ejb.TransactionRolledbackLocalException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;

import org.ow2.easybeans.api.EasyBeansInvocationContext;
import org.ow2.easybeans.api.OperationState;
import org.ow2.easybeans.transaction.SessionSynchronizationListener;
import org.ow2.util.log.Log;
import org.ow2.util.log.LogFactory;

/**
* This interceptor will add on the current transaction an object which will
* listen the transaction synchronization and call methods on a bean.
* @author Florent Benoit
*/
public class ListenerSessionSynchronizationInterceptor extends AbsTransactionInterceptor {

    /**
     * Logger.
     */
    private Log logger = LogFactory.getLog(ListenerSessionSynchronizationInterceptor.class);

    /**
     * Listener which will receive event of the transaction manager.
     */
    private Map<Object, SessionSynchronizationListener> listeners = new WeakHashMap<Object, SessionSynchronizationListener>();

    /**
     * Adds a listener object receiving calls from the transaction manager.
     * @param invocationContext context with useful attributes on the current
     *        invocation
     * @return result of the next invocation (to chain interceptors).
     * @throws Exception if interceptor fails
     * @see <a href="http://www.jcp.org/en/jsr/detail?id=220">EJB 3.0
     *      specification ?12.6.2.2</a>
     */
    @Override
    public Object intercept(final EasyBeansInvocationContext invocationContext) throws Exception {
        this.logger.debug("Calling ListenerSessionSynchronizationInterceptor interceptor");
        if (getTransactionManager().getTransaction() != null) {
            addSynchronization(invocationContext);
        } else {
            this.logger.warn("No transaction but the bean is implementing session synchonization interface.");
        }
        return invocationContext.proceed();
    }

    /**
     * Add a synchronization listener to the transaction manager in order to be
     * notified and send actions on the bean. It should be done only once until
     * transaction is completed.
     * @param invocationContext the context on the current invocation.
     */
    private void addSynchronization(final EasyBeansInvocationContext invocationContext) {
        Object o = invocationContext.getTarget();
        if (!(o instanceof SessionSynchronization)) {
            throw new IllegalArgumentException("This interceptor should not have been added on this "
                    + "bean which doesn't implement SessionSynchronization interface.");
        }
        SessionSynchronization bean = (SessionSynchronization) o;

        /**
         * 4.3.11 Interceptors for Session Beans.<br>
         * For stateful session beans that implement the SessionSynchronization
         * interface, afterBegin occurs before any AroundInvoke method
         * invocation, and beforeCompletion after all AroundInvoke invocations
         * are finished.<br>
         * The beforeCompletion method is called by the transaction manager
         * prior to the start of the two-phase transaction commit process. This
         * call is executed with the transaction context of the transaction that
         * is being committed.
         */

        // TODO: THE COMPLETED information should be retrieved on the bean
        // context, not on the session listener.
        SessionSynchronizationListener sessionSynchronizationListener = this.listeners.get(bean);
        if (sessionSynchronizationListener == null) {
            sessionSynchronizationListener =  new SessionSynchronizationListener(bean, invocationContext.getFactory());
            this.listeners.put(bean, sessionSynchronizationListener);
        }

        // add only once until
        if (sessionSynchronizationListener.isReady()) {

            try {
                getTransactionManager().getTransaction().registerSynchronization(sessionSynchronizationListener);
            } catch (IllegalStateException e) {
                throw new EJBException("Cannot register the synchronization", e);
            } catch (RollbackException e) {
                throw new TransactionRolledbackLocalException("Session rolled back");
            } catch (SystemException e) {
                throw new EJBException("Cannot register the synchronization", e);
            }

            // Change state
            OperationState oldState = invocationContext.getFactory().getOperationState();
            invocationContext.getFactory().getOperationStateThreadLocal().set(OperationState.AFTER_BEGIN);

            // Call method
            try {
                bean.afterBegin();
            } catch (EJBException e) {
                throw e;
            } catch (RemoteException e) {
                throw new EJBException("Cannot call afterBegin method", e);
            } finally {
                invocationContext.getFactory().getOperationStateThreadLocal().set(oldState);
            }
            sessionSynchronizationListener.inTX();
        }

    }
}
TOP

Related Classes of org.ow2.easybeans.transaction.interceptors.ListenerSessionSynchronizationInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.