001: /**
002: * EasyBeans
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: easybeans@ow2.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: ListenerSessionSynchronizationInterceptor.java 1970 2007-10-16 11:49:25Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.transaction.interceptors;
025:
026: import java.rmi.RemoteException;
027: import java.util.Map;
028: import java.util.WeakHashMap;
029:
030: import javax.ejb.EJBException;
031: import javax.ejb.SessionSynchronization;
032: import javax.ejb.TransactionRolledbackLocalException;
033: import javax.transaction.RollbackException;
034: import javax.transaction.SystemException;
035:
036: import org.ow2.easybeans.api.EasyBeansInvocationContext;
037: import org.ow2.easybeans.transaction.SessionSynchronizationListener;
038: import org.ow2.util.log.Log;
039: import org.ow2.util.log.LogFactory;
040:
041: /**
042: * This interceptor will add on the current transaction an object which will
043: * listen the transaction synchronization and call methods on a bean.
044: * @author Florent Benoit
045: */
046: public class ListenerSessionSynchronizationInterceptor extends
047: AbsTransactionInterceptor {
048:
049: /**
050: * Logger.
051: */
052: private Log logger = LogFactory
053: .getLog(ListenerSessionSynchronizationInterceptor.class);
054:
055: /**
056: * Listener which will receive event of the transaction manager.
057: */
058: private Map<Object, SessionSynchronizationListener> listeners = new WeakHashMap<Object, SessionSynchronizationListener>();
059:
060: /**
061: * Adds a listener object receiving calls from the transaction manager.
062: * @param invocationContext context with useful attributes on the current
063: * invocation
064: * @return result of the next invocation (to chain interceptors).
065: * @throws Exception if interceptor fails
066: * @see <a href="http://www.jcp.org/en/jsr/detail?id=220">EJB 3.0
067: * specification ?12.6.2.2</a>
068: */
069: @Override
070: public Object intercept(
071: final EasyBeansInvocationContext invocationContext)
072: throws Exception {
073: logger
074: .debug("Calling ListenerSessionSynchronizationInterceptor interceptor");
075: if (getTransactionManager().getTransaction() != null) {
076: addSynchronization(invocationContext);
077: } else {
078: logger
079: .warn("No transaction but the bean is implementing session synchonization interface.");
080: }
081: return invocationContext.proceed();
082: }
083:
084: /**
085: * Add a synchronization listener to the transaction manager in order to be
086: * notified and send actions on the bean. It should be done only once until
087: * transaction is completed.
088: * @param invocationContext the context on the current invocation.
089: */
090: private void addSynchronization(
091: final EasyBeansInvocationContext invocationContext) {
092: Object o = invocationContext.getTarget();
093: if (!(o instanceof SessionSynchronization)) {
094: throw new IllegalArgumentException(
095: "This interceptor should not have been added on this "
096: + "bean which doesn't implement SessionSynchronization interface.");
097: }
098: SessionSynchronization bean = (SessionSynchronization) o;
099:
100: /**
101: * 4.3.11 Interceptors for Session Beans.<br>
102: * For stateful session beans that implement the SessionSynchronization
103: * interface, afterBegin occurs before any AroundInvoke method
104: * invocation, and beforeCompletion after all AroundInvoke invocations
105: * are finished.<br>
106: * The beforeCompletion method is called by the transaction manager
107: * prior to the start of the two-phase transaction commit process. This
108: * call is executed with the transaction context of the transaction that
109: * is being committed.
110: */
111:
112: // TODO: THE COMPLETED information should be retrieved on the bean
113: // context, not on the session listener.
114: SessionSynchronizationListener sessionSynchronizationListener = listeners
115: .get(bean);
116: if (sessionSynchronizationListener == null) {
117: sessionSynchronizationListener = new SessionSynchronizationListener(
118: bean);
119: listeners.put(bean, sessionSynchronizationListener);
120: }
121:
122: // add only once until
123: if (sessionSynchronizationListener.isReady()) {
124:
125: try {
126: getTransactionManager().getTransaction()
127: .registerSynchronization(
128: sessionSynchronizationListener);
129: } catch (IllegalStateException e) {
130: throw new EJBException(
131: "Cannot register the synchronization", e);
132: } catch (RollbackException e) {
133: throw new TransactionRolledbackLocalException(
134: "Session rolled back");
135: } catch (SystemException e) {
136: throw new EJBException(
137: "Cannot register the synchronization", e);
138: }
139:
140: // now call the after begin method on the synchronized bean
141: try {
142: bean.afterBegin();
143: } catch (EJBException e) {
144: throw e;
145: } catch (RemoteException e) {
146: throw new EJBException("Cannot call afterBefin method",
147: e);
148: }
149: sessionSynchronizationListener.inTX();
150: }
151:
152: }
153: }
|