/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This 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 (at your option) any later version.
*
* This software 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 software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.ejb.plugins;
import java.lang.reflect.Method;
import java.rmi.RemoteException;
import org.jboss.ejb.Container;
import org.jboss.ejb.StatefulSessionContainer;
import org.jboss.ejb.StatefulSessionEnterpriseContext;
import org.jboss.ejb.EnterpriseContext;
import org.jboss.invocation.Invocation;
/**
* This interceptor synchronizes a HA SFSB instance with its underlying persistent manager.
*
* @author <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
* @version $Revision: 81001 $
*
* <p><b>Revisions:</b>
* <p><b>2002/07/28: <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a></b>
* <ol>
* <li>Added isModified check before replication (TaskId 57031)
* </ol>
*/
public class StatefulHASessionSynchronisationInterceptor
extends AbstractInterceptor
{
protected StatefulSessionContainer container;
// optional isModified method used to avoid unecessary state replication
//
protected Method isModified = null;
public void start () throws Exception
{
// Lookup the isModified method if it exists
//
try
{
isModified = this.container.getBeanClass().getMethod("isModified", new Class[0]);
if (!isModified.getReturnType().equals(Boolean.TYPE)) {
isModified = null; // Has to have "boolean" as return type!
log.warn("Found isModified method, but return type is not boolean; ignoring");
}
else
{
log.debug("Using isModified method: " + isModified);
}
}
catch (NoSuchMethodException ignored) {}
}
public Object invokeHome (Invocation mi)
throws Exception
{
EnterpriseContext ctx = (EnterpriseContext)mi.getEnterpriseContext ();
try
{
// Invoke through interceptors
return getNext ().invokeHome (mi);
}
finally
{
if ( (ctx != null) && (ctx.getId () != null) )
// Still a valid instance and instance not removed
//
{
// Everything went ok (at least no J2EE problem) and the instance will most probably be called
// many more times. Consequently, we need to synchronize the state of our bean instance with
// our persistant store (which will forward this to its HASessionState implementation) for clustering
// behaviour. This is only necessary for "create" calls (which is the case because ctx.getId() != null)
//
synchronizeState (ctx);
}
}
}
public Object invoke (Invocation mi)
throws Exception
{
EnterpriseContext ctx = (EnterpriseContext)mi.getEnterpriseContext ();
try
{
// Invoke through interceptors
return getNext ().invoke (mi);
}
catch (RemoteException e)
{
ctx = null;
throw e;
}
catch (RuntimeException e)
{
ctx = null;
throw e;
}
catch (Error e)
{
ctx = null;
throw e;
}
finally
{
if ( (ctx != null) && (ctx.getId () != null) )
// Still a valid instance and instance not removed
//
{
// Everything went ok (at least no J2EE problem) and the instance will most probably be called
// many more times. Consequently, we need to synchronize the state of our bean instance with
// our persistant store (which will forward this to its HASessionState implementation) for clustering
// behaviour.
//
if(isModified == null)
{
synchronizeState (ctx);
}
else
{
Boolean modified = (Boolean) isModified.invoke (ctx.getInstance (), new Object[0]);
if (modified.booleanValue ())
synchronizeState (ctx);
}
}
}
}
protected void synchronizeState (EnterpriseContext ctx) throws Exception
{
((HAPersistentManager)container.getPersistenceManager ()).synchroSession ((StatefulSessionEnterpriseContext)ctx);
}
/**
* This callback is set by the container so that the plugin may access it
*
* @param container The container using this plugin.
*/
public void setContainer (Container container)
{
this.container = (StatefulSessionContainer)container;
}
public Container getContainer ()
{
return container;
}
}