001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins;
023:
024: import java.lang.reflect.Method;
025: import java.rmi.RemoteException;
026:
027: import org.jboss.ejb.Container;
028: import org.jboss.ejb.StatefulSessionContainer;
029: import org.jboss.ejb.StatefulSessionEnterpriseContext;
030: import org.jboss.ejb.EnterpriseContext;
031: import org.jboss.invocation.Invocation;
032:
033: /**
034: * This interceptor synchronizes a HA SFSB instance with its underlying persistent manager.
035: *
036: * @author <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
037: * @version $Revision: 57188 $
038: *
039: * <p><b>Revisions:</b>
040: * <p><b>2002/07/28: <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a></b>
041: * <ol>
042: * <li>Added isModified check before replication (TaskId 57031)
043: * </ol>
044: */
045: public class StatefulHASessionSynchronisationInterceptor extends
046: AbstractInterceptor {
047: protected StatefulSessionContainer container;
048:
049: // optional isModified method used to avoid unecessary state replication
050: //
051: protected Method isModified = null;
052:
053: public void start() throws Exception {
054: // Lookup the isModified method if it exists
055: //
056: try {
057: isModified = this .container.getBeanClass().getMethod(
058: "isModified", new Class[0]);
059: if (!isModified.getReturnType().equals(Boolean.TYPE)) {
060: isModified = null; // Has to have "boolean" as return type!
061: log
062: .warn("Found isModified method, but return type is not boolean; ignoring");
063: } else {
064: log.debug("Using isModified method: " + isModified);
065: }
066: } catch (NoSuchMethodException ignored) {
067: }
068: }
069:
070: public Object invokeHome(Invocation mi) throws Exception {
071: EnterpriseContext ctx = (EnterpriseContext) mi
072: .getEnterpriseContext();
073:
074: try {
075: // Invoke through interceptors
076: return getNext().invokeHome(mi);
077: } finally {
078: if ((ctx != null) && (ctx.getId() != null))
079: // Still a valid instance and instance not removed
080: //
081: {
082: // Everything went ok (at least no J2EE problem) and the instance will most probably be called
083: // many more times. Consequently, we need to synchronize the state of our bean instance with
084: // our persistant store (which will forward this to its HASessionState implementation) for clustering
085: // behaviour. This is only necessary for "create" calls (which is the case because ctx.getId() != null)
086: //
087: synchronizeState(ctx);
088: }
089: }
090: }
091:
092: public Object invoke(Invocation mi) throws Exception {
093: EnterpriseContext ctx = (EnterpriseContext) mi
094: .getEnterpriseContext();
095:
096: try {
097: // Invoke through interceptors
098: return getNext().invoke(mi);
099: } catch (RemoteException e) {
100: ctx = null;
101: throw e;
102: } catch (RuntimeException e) {
103: ctx = null;
104: throw e;
105: } catch (Error e) {
106: ctx = null;
107: throw e;
108: } finally {
109: if ((ctx != null) && (ctx.getId() != null))
110: // Still a valid instance and instance not removed
111: //
112: {
113: // Everything went ok (at least no J2EE problem) and the instance will most probably be called
114: // many more times. Consequently, we need to synchronize the state of our bean instance with
115: // our persistant store (which will forward this to its HASessionState implementation) for clustering
116: // behaviour.
117: //
118:
119: if (isModified == null) {
120: synchronizeState(ctx);
121: } else {
122: Boolean modified = (Boolean) isModified.invoke(ctx
123: .getInstance(), new Object[0]);
124: if (modified.booleanValue())
125: synchronizeState(ctx);
126: }
127: }
128: }
129: }
130:
131: protected void synchronizeState(EnterpriseContext ctx)
132: throws Exception {
133: ((HAPersistentManager) container.getPersistenceManager())
134: .synchroSession((StatefulSessionEnterpriseContext) ctx);
135: }
136:
137: /**
138: * This callback is set by the container so that the plugin may access it
139: *
140: * @param container The container using this plugin.
141: */
142: public void setContainer(Container container) {
143: this .container = (StatefulSessionContainer) container;
144: }
145:
146: public Container getContainer() {
147: return container;
148: }
149:
150: }
|