[jboss-cvs] JBossAS SVN: r74347 - in branches/JBPAPP_4_2_0_GA_CP: ejb3 and 8 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jun 10 05:41:28 EDT 2008


Author: galder.zamarreno at jboss.com
Date: 2008-06-10 05:41:28 -0400 (Tue, 10 Jun 2008)
New Revision: 74347

Added:
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulHomeClusteredProxy.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessHomeClusteredProxy.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/resources/test/ejbthree1109/
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/resources/test/ejbthree1109/test-interceptors-aop.xml
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/LoadBalanceAssertInterceptor.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemote.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemoteHome.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSfsbEjb21Bean.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSlsbEjb21Bean.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/unit/
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/unit/ClusteredHomeBeanUnitTestCase.java
Modified:
   branches/JBPAPP_4_2_0_GA_CP/aspects/src/main/org/jboss/aspects/remoting/ClusterChooserInterceptor.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/build-test.xml
   branches/JBPAPP_4_2_0_GA_CP/ejb3/build.sh
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/AbstractPool.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusterProxyFactory.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusteredProxy.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulContainer.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusterProxyFactory.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusteredProxy.java
   branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessContainer.java
Log:
[JBPAPP-864] Clustered home proxies implemented for SFSB and SLSBs. Besides that, I've added some trace logging here and there and changed build.sh in ejb3/ project so that it takes in account any user defined ANT_OPTS settings (useful for report generation where more mem is needed). Also, copied the fix around the NPE in abstract pool when calling @Init method that takes multiple parameters.

Modified: branches/JBPAPP_4_2_0_GA_CP/aspects/src/main/org/jboss/aspects/remoting/ClusterChooserInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/aspects/src/main/org/jboss/aspects/remoting/ClusterChooserInterceptor.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/aspects/src/main/org/jboss/aspects/remoting/ClusterChooserInterceptor.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -23,22 +23,28 @@
 
 import org.jboss.aop.DispatcherConnectException;
 import org.jboss.aop.util.PayloadKey;
+import org.jboss.ha.framework.interfaces.FamilyClusterInfo;
 import org.jboss.ha.framework.interfaces.GenericClusteringException;
 import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
+import org.jboss.logging.Logger;
 import org.jboss.remoting.CannotConnectException;
 import org.jboss.remoting.InvokerLocator;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Pick an invocation target
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class ClusterChooserInterceptor implements org.jboss.aop.advice.Interceptor, ClusterConstants, java.io.Serializable
 {
    private static final long serialVersionUID = -8666382019058421135L;
+   
+   private static final Logger log = Logger.getLogger(ClusterChooserInterceptor.class);
 
    public static final ClusterChooserInterceptor singleton = new ClusterChooserInterceptor();
 
@@ -51,21 +57,28 @@
    throws Throwable
    {
       LoadBalancePolicy lb = (LoadBalancePolicy) invocation.getMetaData(CLUSTERED_REMOTING, LOADBALANCE_POLICY);
-      FamilyWrapper family = (FamilyWrapper) invocation.getMetaData(CLUSTERED_REMOTING, CLUSTER_FAMILY_WRAPPER);
+      FamilyWrapper wrapper = (FamilyWrapper) invocation.getMetaData(CLUSTERED_REMOTING, CLUSTER_FAMILY_WRAPPER);
+      FamilyClusterInfo familyInfo = wrapper.get(); 
 
+      if (log.isTraceEnabled())
+      {
+         log.trace("Client cluster view id: " + familyInfo.getCurrentViewId());
+         log.trace(printPossibleTargets(familyInfo));
+      }
+      
       // we give the opportunity, to any server interceptor, to know if this a
       // first invocation to a node or if it is a failovered call
       //
       int failoverCounter = 0;
-      String familyName = family.get().getFamilyName();
+      String familyName = familyInfo.getFamilyName();
       invocation.getMetaData().addMetaData(CLUSTERED_REMOTING, CLUSTER_FAMILY, familyName, PayloadKey.AS_IS);
-      InvokerLocator target = (InvokerLocator) lb.chooseTarget(family.get());
+      InvokerLocator target = (InvokerLocator) lb.chooseTarget(familyInfo);
       Throwable lastException = null;
       while (target != null)
       {
          invocation.getMetaData().addMetaData(CLUSTERED_REMOTING, FAILOVER_COUNTER, new Integer(failoverCounter), PayloadKey.AS_IS);
          invocation.getMetaData().addMetaData(InvokeRemoteInterceptor.REMOTING, InvokeRemoteInterceptor.INVOKER_LOCATOR, target, PayloadKey.AS_IS);
-         invocation.getMetaData().addMetaData(CLUSTERED_REMOTING, CLUSTER_VIEW_ID, new Long(family.get().getCurrentViewId()), PayloadKey.AS_IS);
+         invocation.getMetaData().addMetaData(CLUSTERED_REMOTING, CLUSTER_VIEW_ID, new Long(familyInfo.getCurrentViewId()), PayloadKey.AS_IS);
 
          boolean definitivlyRemoveNodeOnFailure = true;
          lastException = null;
@@ -79,7 +92,7 @@
             if (newReplicants != null)
             {
                long newViewId = ((Long) invocation.getResponseAttachment("viewId")).longValue();
-               family.get().updateClusterInfo(newReplicants, newViewId);
+               familyInfo.updateClusterInfo(newReplicants, newViewId);
             }
             return rsp;
          }
@@ -106,7 +119,7 @@
                // we don't want to remove the node from the list of failed
                // node UNLESS there is a risk to indefinitively loop
                //
-               if (family.get().getTargets().size() >= failoverCounter)
+               if (familyInfo.getTargets().size() >= failoverCounter)
                {
                   if (!gce.isDefinitive())
                      definitivlyRemoveNodeOnFailure = false;
@@ -135,7 +148,7 @@
                   // we don't want to remove the node from the list of failed
                   // node UNLESS there is a risk to indefinitively loop
                   //
-                  if (family.get().getTargets().size() >= failoverCounter)
+                  if (familyInfo.getTargets().size() >= failoverCounter)
                   {
                      if (!gce.isDefinitive())
                         definitivlyRemoveNodeOnFailure = false;
@@ -152,13 +165,13 @@
          }
 
          // If we reach here, this means that we must fail-over
-         family.get().removeDeadTarget(target);
+         familyInfo.removeDeadTarget(target);
          if (!definitivlyRemoveNodeOnFailure)
          {
-            family.get().resetView();
+            familyInfo.resetView();
          }
 
-         target = (InvokerLocator) lb.chooseTarget(family.get());
+         target = (InvokerLocator) lb.chooseTarget(familyInfo);
          if (target == null)
          {
             if (lastException != null)
@@ -175,4 +188,21 @@
       // if we get here this means list was exhausted
       throw new RuntimeException("Unreachable?: Service unavailable.");
    }
+   
+   private Object printPossibleTargets(FamilyClusterInfo familyInfo)
+   {
+      StringBuffer buffer = new StringBuffer();
+      if(familyInfo != null)
+      {
+         List possibleTargets = familyInfo.getTargets();
+         if(possibleTargets != null && possibleTargets.size() > 0)
+         {
+            for(int x = 0; x < possibleTargets.size(); x++)
+            {
+               buffer.append("\nPossible target " + (x + 1) + ": " + possibleTargets.get(x));
+            }
+         }
+      }
+      return buffer.toString();
+   }
 }

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/build-test.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/build-test.xml	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/build-test.xml	2008-06-10 09:41:28 UTC (rev 74347)
@@ -130,7 +130,8 @@
             <available file="server.log">
                <filepath>
                   <fileset dir="${ejb3.dist}/server/@{conf}/log/" includes="server.log">
-                     <contains text="[org.jboss.system.server.Server] Shutdown complete"/>
+                     <!-- Removed first part so that cases when thread information is logged can be caught -->
+                     <contains text="Shutdown complete"/>
                   </fileset>
                </filepath>
             </available>
@@ -2042,6 +2043,20 @@
       <build-simple-jar name="ejbthree1062"/>
    </target>
    
+   <target name="ejbthree1109"
+      description="Builds all jar files."
+      depends="compile-classes">
+
+      <mkdir dir="${build.lib}"/>
+
+      <jar jarfile="${build.lib}/ejbthree1109.jar">
+         <fileset dir="${build.classes}">
+            <include name="org/jboss/ejb3/test/ejbthree1109/*.class"/>
+         </fileset>
+         <zipfileset dir="${build.resources}/test/ejbthree1109" includes="*"/>
+      </jar>
+   </target>
+   
    <target name="ejbthree1239"
       description="Builds a simple jar files."
       depends="compile-classes">
@@ -3743,6 +3758,7 @@
       ejbthree987,
       ejbthree921,
       ejbthree959, ejbthree963, ejbthree994, ejbthree1023, ejbthree1025, ejbthree1062,
+      ejbthree1109,
       ejbthree1239,
       jbas4489, epcpropagation, jaccpropagation, 
       aspectdomain, ejbcontext, schema, mail, scopedclassloader, dependency, jaxws,
@@ -4480,7 +4496,7 @@
       <antcall target="tests-clustering-shutdown"/>
    </target>
 
-   <target name="clustered-one-test" depends="init, clusteredsession, clusteredentity, ejbthree921">
+   <target name="clustered-one-test" depends="init, clusteredsession, clusteredentity, ejbthree921, ejbthree1109">
 <!--
 -->
       <antcall target="tests-clustering-startup"/>
@@ -4722,6 +4738,12 @@
          <param name="test.extension" value="${buddy-replication-extension}"/> 
       </antcall>
 
+      <antcall target="test-with-jvmargs" inheritRefs="true">
+         <param name="test" value="ejbthree1109"/>
+         <param name="jvmargs" value=""/>
+         <param name="test.extension" value="${buddy-replication-extension}"/> 
+      </antcall>
+      
    </target>
 	
    <target name="statelesscreation-test">

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/build.sh
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/build.sh	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/build.sh	2008-06-10 09:41:28 UTC (rev 74347)
@@ -145,7 +145,7 @@
     fi
 
     # need to specify planet57/buildmagic protocol handler package
-    ANT_OPTS="-Djava.protocol.handler.pkgs=org.jboss.net.protocol"
+    ANT_OPTS="$ANT_OPTS -Djava.protocol.handler.pkgs=org.jboss.net.protocol"
 
     # setup some build properties
     ANT_OPTS="$ANT_OPTS -Dbuild.script=$0"

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/AbstractPool.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/AbstractPool.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/AbstractPool.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -32,6 +32,7 @@
  * Comment
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public abstract class AbstractPool implements Pool
@@ -163,7 +164,19 @@
          CacheConfig config = (CacheConfig) advisor.resolveAnnotation(CacheConfig.class);
          if (config != null)
          {
-            sfctx.setReplicationIsPassivation(config.replicationIsPassivation());
+            boolean replIsPass = true;
+            try
+            {
+               // TODO determine why this fails on 4.2 branch if no
+               // CacheConfig annotation is present
+               replIsPass = config.replicationIsPassivation();
+            }
+            catch (Exception e)
+            {
+               log.debug("create(): Cannot determine replicationIsPassivation setting; defaulting to true " + 
+                         e.getLocalizedMessage());
+            }
+            sfctx.setReplicationIsPassivation(replIsPass);
          }
          // this is for propagated extended PC's
          ctx = sfctx = sfctx.pushContainedIn();

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusterProxyFactory.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusterProxyFactory.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusterProxyFactory.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -23,8 +23,11 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import javax.ejb.EJBHome;
+import javax.ejb.RemoteHome;
 import javax.naming.NamingException;
 
 import org.jboss.annotation.ejb.Clustered;
@@ -35,15 +38,20 @@
 import org.jboss.aop.advice.AdviceStack;
 import org.jboss.aspects.remoting.FamilyWrapper;
 import org.jboss.aspects.remoting.Remoting;
+import org.jboss.ejb3.Container;
+import org.jboss.ejb3.EJBContainer;
 import org.jboss.ejb3.JBossProxy;
 import org.jboss.ejb3.ProxyFactory;
 import org.jboss.ejb3.ProxyFactoryHelper;
+import org.jboss.ejb3.SessionContainer;
 import org.jboss.ejb3.remoting.RemoteProxyFactory;
+import org.jboss.ejb3.stateless.StatelessClusterProxyFactory;
 import org.jboss.ha.framework.interfaces.ClusteringTargetsRepository;
 import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
 import org.jboss.ha.framework.interfaces.FirstAvailable;
 import org.jboss.ha.framework.interfaces.HAPartition;
 import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
+import org.jboss.ha.framework.interfaces.RoundRobin;
 import org.jboss.ha.framework.server.HATarget;
 import org.jboss.logging.Logger;
 import org.jboss.naming.Util;
@@ -55,7 +63,7 @@
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
  * @author Brian Stansberry
- *
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class StatefulClusterProxyFactory extends BaseStatefulProxyFactory 
@@ -70,8 +78,11 @@
    private DistributedReplicantManager drm;
    private HATarget hatarget;
    private String proxyFamilyName;
+   private String homeProxyFamilyName;
    private LoadBalancePolicy lbPolicy;
    private FamilyWrapper wrapper;
+   private FamilyWrapper homeWrapper;
+   private Object homeProxy;
 
    public void setRemoteBinding(RemoteBinding binding)
    {
@@ -80,12 +91,36 @@
 
    protected Class[] getInterfaces()
    {
-      Class[] remoteInterfaces = ProxyFactoryHelper.getRemoteInterfaces(getContainer());
-      Class[] interfaces = new Class[remoteInterfaces.length + 1];
-      System.arraycopy(remoteInterfaces, 0, interfaces, 0, remoteInterfaces.length);
-      interfaces[remoteInterfaces.length] = JBossProxy.class;
-      return interfaces;
+      StatefulContainer statefulContainer = (StatefulContainer) getContainer();
+      RemoteHome remoteHome = (RemoteHome) statefulContainer.resolveAnnotation(RemoteHome.class);
+
+      boolean bindTogether = false;
+
+      if (remoteHome != null && bindHomeAndBusinessTogether(statefulContainer))
+         bindTogether = true;
+
+      // Obtain all remote interfaces
+      List<Class<?>> remoteInterfaces = new ArrayList<Class<?>>();
+      remoteInterfaces.addAll(Arrays.asList(ProxyFactoryHelper.getRemoteInterfaces(statefulContainer)));
+
+      // Add JBossProxy
+      remoteInterfaces.add(JBossProxy.class);
+      remoteInterfaces.add(javax.ejb.EJBObject.class);
+      
+      // If binding along w/ home, add home
+      if (bindTogether)
+      {
+         remoteInterfaces.add(remoteHome.value());
+      }
+
+      // Return
+      return remoteInterfaces.toArray(new Class<?>[]{});
    }
+   
+   protected boolean bindHomeAndBusinessTogether(Container container)
+   {
+      return ProxyFactoryHelper.getHomeJndiName(container).equals(ProxyFactoryHelper.getRemoteJndiName(container));
+   }
 
    protected void initializeJndiName()
    {
@@ -98,12 +133,12 @@
       locator = new InvokerLocator(clientBindUrl);
       Clustered clustered = (Clustered) ((Advisor)getContainer()).resolveAnnotation(Clustered.class);
       if (clustered == null) throw new RuntimeException("Could not find @Clustered annotation.  Cannot deploy.");
-      String partitionName = ((StatefulContainer) getContainer()).getPartitionName();
-      proxyFamilyName = ((StatefulContainer) getContainer()).getDeploymentQualifiedName() + locator.getProtocol() + partitionName;
+      String partitionName = ((EJBContainer) getContainer()).getPartitionName();
+      proxyFamilyName = ((EJBContainer) getContainer()).getDeploymentQualifiedName() + locator.getProtocol() + partitionName;
       HAPartition partition = (HAPartition) getContainer().getInitialContext().lookup("/HAPartition/" + partitionName);
       hatarget = new HATarget(partition, proxyFamilyName, locator, HATarget.ENABLE_INVOCATIONS);
       ClusteringTargetsRepository.initTarget(proxyFamilyName, hatarget.getReplicants());
-      ((StatefulContainer) getContainer()).getClusterFamilies().put(proxyFamilyName, hatarget);
+      ((SessionContainer) getContainer()).getClusterFamilies().put(proxyFamilyName, hatarget);
       if (clustered.loadBalancePolicy() == null || clustered.loadBalancePolicy().equals(LoadBalancePolicy.class))
       {
          lbPolicy = new FirstAvailable();
@@ -134,10 +169,16 @@
       assert !Dispatcher.singleton.isRegistered(targetId) : targetId + " is already registered";
       Dispatcher.singleton.registerTarget(targetId, this);
 
+      createAndBindHomeProxy();
    }
 
    public Object createProxy()
    {
+      return createProxy(null);
+   }
+
+   public Object createProxy(Object id)
+   {
       try
       {
          Object containerId = getContainer().getObjectName().getCanonicalName();
@@ -147,9 +188,18 @@
             stackName = binding.interceptorStack();
          }
          AdviceStack stack = AspectManager.instance().getAdviceStack(stackName);
-         String partitionName = ((StatefulContainer) getContainer()).getPartitionName();
-         Object[] args = {new StatefulClusteredProxy(getContainer(), stack.createInterceptors((Advisor) getContainer(), null), 
-               wrapper, lbPolicy, partitionName)};
+         String partitionName = ((EJBContainer) getContainer()).getPartitionName();
+         Object[] args = null;
+         if (id != null)
+         {
+            args = new Object[]{new StatefulClusteredProxy(getContainer(), stack.createInterceptors((Advisor) getContainer(), null), 
+                  wrapper, lbPolicy, partitionName, id)};
+         }
+         else
+         {
+            args = new Object[]{new StatefulClusteredProxy(getContainer(), stack.createInterceptors((Advisor) getContainer(), null), 
+                  wrapper, lbPolicy, partitionName)};            
+         }
          
          return proxyConstructor.newInstance(args);
       }
@@ -170,19 +220,16 @@
          throw new RuntimeException(e.getTargetException());  //To change body of catch statement use Options | File Templates.
       }
    }
-
-   public Object createProxy(Object id)
-   {
-      throw new RuntimeException("NYI");
-   }
    
    public void stop() throws Exception
    {
       Dispatcher.singleton.unregisterTarget(getTargetId());
       hatarget.destroy();
       drm.unregisterListener(proxyFamilyName, this);
-      ((StatefulContainer) getContainer()).getClusterFamilies().remove(proxyFamilyName);
+      ((SessionContainer) getContainer()).getClusterFamilies().remove(proxyFamilyName);
+      ((SessionContainer) getContainer()).getClusterFamilies().remove(homeProxyFamilyName);
       Util.unbind(getContainer().getInitialContext(), jndiName + PROXY_FACTORY_NAME);
+      Util.unbind(getContainer().getInitialContext(), ProxyFactoryHelper.getHomeJndiName(getContainer()));
       super.stop();
    }
    
@@ -202,7 +249,7 @@
    protected String getTargetId()
    {
       assert jndiName != null : "jndiName is null";      
-      String partition = ((StatefulContainer) getContainer()).getPartitionName();
+      String partition = ((EJBContainer) getContainer()).getPartitionName();
       return jndiName + PROXY_FACTORY_NAME + "@" + partition;
    }
    
@@ -214,7 +261,18 @@
       {
          // Update the FamilyClusterInfo with the new targets
          ArrayList targets = new ArrayList(newReplicants);
-         wrapper.get().updateClusterInfo(targets, newReplicantsViewId); 
+         wrapper.get().updateClusterInfo(targets, newReplicantsViewId);
+         
+         if (homeProxy != null)
+         {
+            if (log.isTraceEnabled())
+            {
+               log.trace("Updating home proxy for " + getContainer().getEjbName() + " with new replicants " + newReplicants + ", view=" + newReplicantsViewId);
+            }
+
+            homeWrapper.get().updateClusterInfo(targets, newReplicantsViewId);
+            bindHomeProxy(homeProxy);
+         }
       }
       catch (Exception e)
       {
@@ -222,4 +280,67 @@
       }
    }
 
+   protected void createAndBindHomeProxy() throws Exception
+   {
+      EJBContainer container = (EJBContainer) getContainer();
+      RemoteHome remoteHome = (RemoteHome) container.resolveAnnotation(RemoteHome.class);
+      if (remoteHome != null && !bindHomeAndBusinessTogether(container))
+      {
+         Object homeProxy = createHomeProxy(remoteHome.value(), container);
+         bindHomeProxy(homeProxy);
+      }
+   }
+
+   public Object createHomeProxy(Class homeInterface, EJBContainer container)
+   {
+      String stackName = "ClusteredStatefulSessionClientInterceptors";
+      if (binding.interceptorStack() != null && !binding.interceptorStack().equals(""))
+      {
+         stackName = binding.interceptorStack();
+      }
+      
+      AdviceStack stack = AspectManager.instance().getAdviceStack(stackName);
+      String partitionName = container.getPartitionName();
+
+      homeProxyFamilyName = container.getDeploymentQualifiedName() + locator.getProtocol() + partitionName + StatelessClusterProxyFactory.HOME_FAMILY;
+      homeWrapper = new FamilyWrapper(homeProxyFamilyName, hatarget.getReplicants());      
+      ((SessionContainer) getContainer()).getClusterFamilies().put(homeProxyFamilyName, hatarget);
+      
+      if (log.isTraceEnabled())
+      {
+         log.trace("Creating home clustered proxy with family name " + homeProxyFamilyName + " and replicants " + hatarget.getReplicants());
+      }
+
+      /* Round Robin hardcoded for Home interface load balancing */
+      StatefulHomeClusteredProxy proxy = new StatefulHomeClusteredProxy(getContainer(), 
+            stack.createInterceptors((Advisor) getContainer(), null), homeWrapper, 
+            new RoundRobin(), partitionName);
+
+      Class[] interfaces = { homeInterface, EJBHome.class};
+      homeProxy = java.lang.reflect.Proxy.newProxyInstance(getContainer()
+            .getBeanClass().getClassLoader(), interfaces, proxy);
+      
+      return homeProxy;      
+   }
+   
+   protected void bindHomeProxy(Object proxy) throws NamingException
+   {
+      log.debug("Binding home proxy for " + getContainer().getEjbName() + " in JNDI at " + ProxyFactoryHelper.getHomeJndiName(getContainer()));
+      
+      try 
+      {
+         Util.rebind(getContainer().getInitialContext(), ProxyFactoryHelper.getHomeJndiName(getContainer()), proxy);
+      }
+      catch (NamingException e)
+      {
+         NamingException namingException = new NamingException(
+               "Could not bind stateful home proxy with ejb name "
+                     + getContainer().getEjbName()
+                     + " into JNDI under jndiName: "
+                     + getContainer().getInitialContext().getNameInNamespace()
+                     + "/" + ProxyFactoryHelper.getHomeJndiName(getContainer()));
+         namingException.setRootCause(e);
+         throw namingException;
+      }      
+   }
 }

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusteredProxy.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusteredProxy.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulClusteredProxy.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -47,6 +47,7 @@
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
  * @author Brian Stansberry
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class StatefulClusteredProxy extends org.jboss.ejb3.remoting.BaseRemoteProxy
@@ -67,6 +68,12 @@
       this.lbPolicy = lb;
       this.partitionName = partitionName;
    }
+   
+   public StatefulClusteredProxy(Container container, Interceptor[] interceptors, FamilyWrapper family, LoadBalancePolicy lb, String partitionName, Object id)
+   {
+      this(container, interceptors, family, lb, partitionName);
+      this.id = id;
+   }
 
    public StatefulClusteredProxy(AsynchProvider provider, String containerId, String containerGuid, Interceptor[] interceptors, FamilyWrapper family, LoadBalancePolicy lb, String partitionName)
    {
@@ -149,13 +156,13 @@
    {
       if (id != null)
       {
-         return containerId.toString() + ":" + id.toString();
+         return containerId.toString() + ":Clustered" + ":" + id.toString();
       }
       else
       {
          //If the proxy has not been used yet, create a temporary id 
          GUID guid = new GUID();
-         return containerId.toString() + ":" + guid.toString();
+         return containerId.toString() + ":Clustered" +  ":" + guid.toString();
       }
    }
 

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulContainer.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulContainer.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulContainer.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -43,6 +43,7 @@
 import org.jboss.annotation.ejb.RemoteBindings;
 import org.jboss.annotation.ejb.cache.Cache;
 import org.jboss.aop.AspectManager;
+import org.jboss.aop.Dispatcher;
 import org.jboss.aop.MethodInfo;
 import org.jboss.aop.joinpoint.Invocation;
 import org.jboss.aop.joinpoint.InvocationResponse;
@@ -67,6 +68,7 @@
  * Comment
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class StatefulContainer extends SessionContainer
@@ -657,6 +659,25 @@
          return factory.createProxy();
    }
    
+   public Object createClusteredProxy(Object id) throws Exception
+   {
+      RemoteBinding binding = null;
+      RemoteBindings bindings = (RemoteBindings) resolveAnnotation(RemoteBindings.class);
+      if (bindings != null)
+         binding = bindings.value()[0];
+      else
+         binding = (RemoteBinding) resolveAnnotation(RemoteBinding.class);
+      
+      String jndiName = ProxyFactoryHelper.getRemoteJndiName(this, binding);
+      String targetId = jndiName + BaseStatefulProxyFactory.PROXY_FACTORY_NAME + "@" + getPartitionName();
+      StatefulClusterProxyFactory factory = (StatefulClusterProxyFactory)Dispatcher.singleton.getRegistered(targetId);
+      
+      if (id != null)
+         return factory.createProxy(id);
+      else
+         return factory.createProxy();
+   }
+   
    public boolean isClustered()
    {
       return hasAnnotation(getBeanClass(), org.jboss.annotation.ejb.Clustered.class.getName());
@@ -682,7 +703,15 @@
                  info, statefulInvocation, initParameterTypes,
                  initParameterValues);
 
-         Object proxy = createRemoteProxy(newStatefulInvocation.getId());
+         Object proxy = null;
+         if (isClustered())
+         {
+            proxy = createClusteredProxy(newStatefulInvocation.getId());
+         }
+         else
+         {
+            proxy = createRemoteProxy(newStatefulInvocation.getId());
+         }
 
          InvocationResponse response = marshallResponse(statefulInvocation, proxy, newStatefulInvocation.getResponseContextInfo());
          if (newStatefulInvocation.getId() != null)

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulHomeClusteredProxy.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulHomeClusteredProxy.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateful/StatefulHomeClusteredProxy.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,125 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.ejb3.stateful;
+
+import java.lang.reflect.Method;
+import org.jboss.aop.Dispatcher;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.util.MethodHashing;
+import org.jboss.aop.util.PayloadKey;
+import org.jboss.aspects.remoting.ClusterConstants;
+import org.jboss.aspects.remoting.FamilyWrapper;
+import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
+import org.jboss.ejb3.Container;
+import org.jboss.ejb3.ProxyUtils;
+import org.jboss.ejb3.remoting.ClusteredIsLocalInterceptor;
+import org.jboss.ejb3.remoting.IsLocalInterceptor;
+import org.jboss.ejb3.session.BaseSessionRemoteProxy;
+import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
+
+/**
+ * InvocationHandler for a clustered home SFSB proxy.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class StatefulHomeClusteredProxy extends BaseSessionRemoteProxy
+{   
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 5682364426659525065L;
+   
+   protected FamilyWrapper family;
+   protected LoadBalancePolicy lbPolicy;
+   protected String partitionName;
+
+   public StatefulHomeClusteredProxy(Container container, Interceptor[] interceptors, FamilyWrapper family, LoadBalancePolicy lbPolicy, String partitionName)
+   {
+      super(container, interceptors);
+      this.family = family;
+      this.lbPolicy = lbPolicy;
+      this.partitionName = partitionName;
+   }
+
+   public StatefulHomeClusteredProxy(String containerId, String containerGuid, Interceptor[] interceptors, FamilyWrapper family, LoadBalancePolicy lbPolicy, String partitionName)
+   {
+      super(containerId, containerGuid, interceptors);
+      this.family = family;
+      this.lbPolicy = lbPolicy;
+      this.partitionName = partitionName;
+   }
+
+   public StatefulHomeClusteredProxy()
+   {
+   }
+
+   public Object invoke(Object proxy, Method method, Object[] args)
+           throws Throwable
+   {
+      long hash = MethodHashing.calculateHash(method);
+      Object ret = ProxyUtils.handleCallLocally(hash, proxy, this, method, args);
+      if (ret != null)
+      {
+         return ret;
+      }
+      
+      ret = handleEjb21CallLocally(method, args);
+      if (ret != null)
+      {
+         return ret;
+      }
+
+      StatefulRemoteInvocation sri = new StatefulRemoteInvocation(interceptors, hash, method, method, null, null);
+      sri.setArguments(args);
+      sri.setInstanceResolver(metadata);
+      sri.getMetaData().addMetaData(Dispatcher.DISPATCHER, Dispatcher.OID, containerId, PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(ClusterConstants.CLUSTERED_REMOTING, ClusterConstants.CLUSTER_FAMILY_WRAPPER, family, PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(ClusterConstants.CLUSTERED_REMOTING, ClusterConstants.LOADBALANCE_POLICY, lbPolicy, PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(InvokeRemoteInterceptor.REMOTING, InvokeRemoteInterceptor.SUBSYSTEM, "AOP", PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(ClusteredIsLocalInterceptor.PARTITION_NAME, ClusteredIsLocalInterceptor.PARTITION_NAME, partitionName, PayloadKey.TRANSIENT);
+      sri.getMetaData().addMetaData(IsLocalInterceptor.IS_LOCAL, IsLocalInterceptor.GUID, containerGuid, PayloadKey.AS_IS);
+      
+      return sri.invokeNext();
+   }
+
+   public String toString()
+   {
+      return containerId.toString() + ":Home:Clustered";
+   }
+
+   public Object getAsynchronousProxy(Object proxy)
+   {
+      throw new RuntimeException("NOT IMPLEMENTED");
+   }
+
+   private Object handleEjb21CallLocally(Method method, Object[] args)
+   {
+      if (method.equals(ProxyUtils.GET_HOME_HANDLE))
+      {
+         return homeHandle;
+      }
+      else if (method.equals(ProxyUtils.GET_EJB_METADATA))
+      {
+         return ejbMetaData;
+      }
+
+      return null;
+   }
+}

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusterProxyFactory.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusterProxyFactory.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusterProxyFactory.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -22,24 +22,33 @@
 package org.jboss.ejb3.stateless;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
+import javax.ejb.EJBHome;
+import javax.ejb.RemoteHome;
+import javax.naming.NamingException;
+
 import org.jboss.annotation.ejb.Clustered;
 import org.jboss.annotation.ejb.RemoteBinding;
 import org.jboss.aop.Advisor;
 import org.jboss.aop.AspectManager;
 import org.jboss.aop.advice.AdviceStack;
 import org.jboss.aspects.remoting.FamilyWrapper;
+import org.jboss.ejb3.EJBContainer;
 import org.jboss.ejb3.JBossProxy;
 import org.jboss.ejb3.ProxyFactoryHelper;
+import org.jboss.ejb3.SessionContainer;
 import org.jboss.ejb3.remoting.RemoteProxyFactory;
 import org.jboss.ha.framework.interfaces.ClusteringTargetsRepository;
 import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
 import org.jboss.ha.framework.interfaces.HAPartition;
 import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
 import org.jboss.ha.framework.interfaces.RandomRobin;
+import org.jboss.ha.framework.interfaces.RoundRobin;
 import org.jboss.ha.framework.server.HATarget;
 import org.jboss.logging.Logger;
+import org.jboss.naming.Util;
 import org.jboss.remoting.InvokerLocator;
 
 
@@ -47,21 +56,27 @@
  * Comment
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class StatelessClusterProxyFactory extends BaseStatelessProxyFactory  
    implements RemoteProxyFactory, DistributedReplicantManager.ReplicantListener
 {
    private static final Logger log = Logger.getLogger(StatelessClusterProxyFactory.class);
+   
+   public static final String HOME_FAMILY = "/Home";
 
    private RemoteBinding binding;
    private InvokerLocator locator;
    private DistributedReplicantManager drm;
    private HATarget hatarget;
    private String proxyFamilyName;
+   private String homeProxyFamilyName;
    private LoadBalancePolicy lbPolicy;
-   private FamilyWrapper wrapper;
-   private Object proxy;
+   private FamilyWrapper beanWrapper;
+   private FamilyWrapper homeWrapper;
+   private Object beanProxy;
+   private Object homeProxy;
 
    public void setRemoteBinding(RemoteBinding binding)
    {
@@ -70,12 +85,46 @@
 
    protected Class[] getInterfaces()
    {
-      Class[] remoteInterfaces = ProxyFactoryHelper.getRemoteInterfaces(getContainer());
-      Class[] interfaces = new Class[remoteInterfaces.length + 1];
-      System.arraycopy(remoteInterfaces, 0, interfaces, 0, remoteInterfaces.length);
-      interfaces[remoteInterfaces.length] = JBossProxy.class;
-      return interfaces;
+      StatelessContainer statelessContainer = (StatelessContainer) getContainer();
+      RemoteHome remoteHome = (RemoteHome) statelessContainer.resolveAnnotation(RemoteHome.class);
+
+      boolean bindTogether = false;
+
+      if (remoteHome != null && bindHomeAndBusinessTogether(statelessContainer))
+         bindTogether = true;
+
+      // Obtain all remote interfaces
+      List<Class<?>> remoteInterfaces = new ArrayList<Class<?>>();
+      remoteInterfaces.addAll(Arrays.asList(ProxyFactoryHelper.getRemoteInterfaces(statelessContainer)));
+
+      // Ensure remote interfaces defined
+      if (remoteInterfaces.size() > 0)
+      {
+         // Add JBossProxy
+         remoteInterfaces.add(JBossProxy.class);
+         remoteInterfaces.add(javax.ejb.EJBObject.class);
+
+         // If binding along w/ home, add home
+         if (bindTogether)
+         {
+            remoteInterfaces.add(remoteHome.value());
+         }
+      }
+      else
+      {
+         // No remote interfaces defined, log warning
+         log.warn("[EJBTHREE-933] NPE when deploying web service beans");
+      }
+
+      // Return
+      return remoteInterfaces.toArray(new Class<?>[]
+      {});
    }
+   
+   protected boolean bindHomeAndBusinessTogether(EJBContainer container)
+   {
+      return ProxyFactoryHelper.getHomeJndiName(container).equals(ProxyFactoryHelper.getRemoteJndiName(container));
+   }
 
    protected void initializeJndiName()
    {
@@ -88,12 +137,12 @@
       locator = new InvokerLocator(clientBindUrl);
       Clustered clustered = (Clustered) ((Advisor)getContainer()).resolveAnnotation(Clustered.class);
       if (clustered == null) throw new RuntimeException("Could not find @Clustered annotation.  Cannot deploy.");
-      String partitionName = ((StatelessContainer) getContainer()).getPartitionName();
-      proxyFamilyName = ((StatelessContainer) getContainer()).getDeploymentQualifiedName() + locator.getProtocol() + partitionName;
+      String partitionName = ((EJBContainer) getContainer()).getPartitionName();      
+      proxyFamilyName = ((EJBContainer) getContainer()).getDeploymentQualifiedName() + locator.getProtocol() + partitionName;
       HAPartition partition = (HAPartition) getContainer().getInitialContext().lookup("/HAPartition/" + partitionName);
       hatarget = new HATarget(partition, proxyFamilyName, locator, HATarget.ENABLE_INVOCATIONS);
       ClusteringTargetsRepository.initTarget(proxyFamilyName, hatarget.getReplicants());
-      ((StatelessContainer) getContainer()).getClusterFamilies().put(proxyFamilyName, hatarget);
+      ((SessionContainer) getContainer()).getClusterFamilies().put(proxyFamilyName, hatarget);
       if (clustered.loadBalancePolicy() == null || clustered.loadBalancePolicy().equals(LoadBalancePolicy.class))
       {
          lbPolicy = new RandomRobin();
@@ -102,62 +151,47 @@
       {
          lbPolicy = (LoadBalancePolicy) clustered.loadBalancePolicy().newInstance();
       }
-      wrapper = new FamilyWrapper(proxyFamilyName, hatarget.getReplicants());
+      beanWrapper = new FamilyWrapper(proxyFamilyName, hatarget.getReplicants());
       
       this.drm = partition.getDistributedReplicantManager();
       drm.registerListener(proxyFamilyName, this);
       
       super.start();
+      
+      createAndBindHomeProxy();
    }
 
    public void stop() throws Exception
    {
       super.stop();
-      proxy = null;
+      beanProxy = null;
+      homeProxy = null;
       hatarget.destroy();
       drm.unregisterListener(proxyFamilyName, this);
-      ((StatelessContainer) getContainer()).getClusterFamilies().remove(proxyFamilyName);
+      ((SessionContainer) getContainer()).getClusterFamilies().remove(proxyFamilyName);
+      ((SessionContainer) getContainer()).getClusterFamilies().remove(homeProxyFamilyName);
    }
 
    public Object createProxy()
    {
-//      try
+      Object containerId = getContainer().getObjectName().getCanonicalName();
+      String stackName = "ClusteredStatelessSessionClientInterceptors";
+      if (binding.interceptorStack() != null && !binding.interceptorStack().equals(""))
       {
-         Object containerId = getContainer().getObjectName().getCanonicalName();
-         String stackName = "ClusteredStatelessSessionClientInterceptors";
-         if (binding.interceptorStack() != null && !binding.interceptorStack().equals(""))
-         {
-            stackName = binding.interceptorStack();
-         }
-         AdviceStack stack = AspectManager.instance().getAdviceStack(stackName);
-         /*
-         Object[] args = {new StatelessClusteredProxy(containerId, stack.createInterceptors((Advisor) container, null), wrapper, lbPolicy)};
-         return proxyConstructor.newInstance(args);
-         */
-         String partitionName = ((StatelessContainer) getContainer()).getPartitionName();
-         
-         proxy = constructProxy(new StatelessClusteredProxy(getContainer(), stack.createInterceptors((Advisor) getContainer(), null), 
-               wrapper, lbPolicy, partitionName));
-         return proxy;
+         stackName = binding.interceptorStack();
       }
-      /*
-      catch (InstantiationException e)
+      AdviceStack stack = AspectManager.instance().getAdviceStack(stackName);
+      
+      if (log.isTraceEnabled())
       {
-         throw new RuntimeException(e);  //To change body of catch statement use Options | File Templates.
+         log.trace("Advice stack for " + stackName + " is " + stack);
       }
-      catch (IllegalAccessException e)
-      {
-         throw new RuntimeException(e);  //To change body of catch statement use Options | File Templates.
-      }
-      catch (IllegalArgumentException e)
-      {
-         throw new RuntimeException(e);  //To change body of catch statement use Options | File Templates.
-      }
-      catch (InvocationTargetException e)
-      {
-         throw new RuntimeException(e.getTargetException());  //To change body of catch statement use Options | File Templates.
-      }
-      */
+      
+      String partitionName = ((StatelessContainer) getContainer()).getPartitionName();
+      
+      beanProxy = constructProxy(new StatelessClusteredProxy(getContainer(), stack.createInterceptors((Advisor) getContainer(), null), 
+            beanWrapper, lbPolicy, partitionName));
+      return beanProxy;
    }
 
    protected StatelessHandleImpl getHandle()
@@ -178,15 +212,99 @@
       {
          // Update the FamilyClusterInfo with the new targets
          ArrayList targets = new ArrayList(newReplicants);
-         wrapper.get().updateClusterInfo(targets, newReplicantsViewId);
-         
+                  
          // Rebind the proxy as the old one has been serialized
-         if (proxy != null)
-            bindProxy(proxy);
+         if (beanProxy != null)
+         {
+            if (log.isTraceEnabled())
+            {
+               log.trace("Updating bean proxy for " + getContainer().getEjbName() + " with new replicants " + newReplicants + ", view=" + newReplicantsViewId);
+            }
+            
+            beanWrapper.get().updateClusterInfo(targets, newReplicantsViewId);
+            bindProxy(beanProxy);
+         }
+                     
+         // Rebind the proxy as the old one has been serialized
+         if (homeProxy != null)
+         {
+            if (log.isTraceEnabled())
+            {
+               log.trace("Updating home proxy for " + getContainer().getEjbName() + " with new replicants " + newReplicants + ", view=" + newReplicantsViewId);
+            }
+            
+            homeWrapper.get().updateClusterInfo(targets, newReplicantsViewId);
+            bindHomeProxy(homeProxy);
+         }
+            
       }
       catch (Exception e)
       {
          log.error(e);
       }
    }
+   
+   protected void createAndBindHomeProxy() throws Exception
+   {
+      EJBContainer container = (EJBContainer) getContainer();
+      RemoteHome remoteHome = (RemoteHome) container.resolveAnnotation(RemoteHome.class);
+      if (remoteHome != null && !bindHomeAndBusinessTogether(container))
+      {
+         Object homeProxy = createHomeProxy(remoteHome.value());
+         bindHomeProxy(homeProxy);
+      }
+   }
+   
+   public Object createHomeProxy(Class homeInterface)
+   {
+      String stackName = "ClusteredStatelessSessionClientInterceptors";
+      if (binding.interceptorStack() != null && !binding.interceptorStack().equals(""))
+      {
+         stackName = binding.interceptorStack();
+      }
+      
+      AdviceStack stack = AspectManager.instance().getAdviceStack(stackName);
+      String partitionName = ((StatelessContainer) getContainer()).getPartitionName();
+
+      homeProxyFamilyName = ((StatelessContainer) getContainer()).getDeploymentQualifiedName() + locator.getProtocol() + partitionName + HOME_FAMILY;
+      homeWrapper = new FamilyWrapper(homeProxyFamilyName, hatarget.getReplicants());      
+      ((SessionContainer) getContainer()).getClusterFamilies().put(homeProxyFamilyName, hatarget);
+      
+      if (log.isTraceEnabled())
+      {
+         log.trace("Creating home clustered proxy with family name " + homeProxyFamilyName + " and replicants " + hatarget.getReplicants());
+      }
+
+      /* Round Robin hardcoded for Home interface load balancing */
+      StatelessHomeClusteredProxy proxy = new StatelessHomeClusteredProxy(getContainer(), 
+            stack.createInterceptors((Advisor) getContainer(), null), homeWrapper, 
+            new RoundRobin(), partitionName);
+
+      Class[] interfaces = { homeInterface, EJBHome.class};
+      homeProxy = java.lang.reflect.Proxy.newProxyInstance(getContainer()
+            .getBeanClass().getClassLoader(), interfaces, proxy);
+      
+      return homeProxy;      
+   }
+   
+   protected void bindHomeProxy(Object proxy) throws NamingException
+   {
+      log.debug("Binding home proxy for " + getContainer().getEjbName() + " in JNDI at " + ProxyFactoryHelper.getHomeJndiName(getContainer()));
+      
+      try 
+      {
+         Util.rebind(getContainer().getInitialContext(), ProxyFactoryHelper.getHomeJndiName(getContainer()), proxy);
+      }
+      catch (NamingException e)
+      {
+         NamingException namingException = new NamingException(
+               "Could not bind stateless home proxy with ejb name "
+                     + getContainer().getEjbName()
+                     + " into JNDI under jndiName: "
+                     + getContainer().getInitialContext().getNameInNamespace()
+                     + "/" + ProxyFactoryHelper.getHomeJndiName(getContainer()));
+         namingException.setRootCause(e);
+         throw namingException;
+      }      
+   }
 }

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusteredProxy.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusteredProxy.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessClusteredProxy.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -48,6 +48,7 @@
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
  * @author Brian Stansberry
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class StatelessClusteredProxy extends BaseRemoteProxy
@@ -130,7 +131,7 @@
 
    public String toString()
    {
-      return containerId.toString();
+      return containerId.toString() + ":Clustered";
    }
 
 }

Modified: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessContainer.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessContainer.java	2008-06-10 09:38:05 UTC (rev 74346)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessContainer.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -54,6 +54,7 @@
 import org.jboss.ejb3.timerservice.TimedObjectInvoker;
 import org.jboss.ejb3.timerservice.TimerServiceFactory;
 import org.jboss.logging.Logger;
+import org.jboss.naming.Util;
 import org.jboss.proxy.ejb.handle.HomeHandleImpl;
 import org.jboss.proxy.ejb.handle.StatelessHandleImpl;
 
@@ -62,6 +63,7 @@
  * Comment
  *
  * @author <a href="mailto:bill at jboss.org">Bill Burke</a>
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
  * @version $Revision$
  */
 public class StatelessContainer extends SessionContainer implements TimedObjectInvoker
@@ -391,13 +393,42 @@
 
       return factory.createProxy();
    }
+   
+   public Object createdClustereProxy() throws Exception
+   {
+      /* Use the same hack as createRemoteProxy(). In other words, take 
+       * the first of the remote bindings. */
+      RemoteBinding binding = null;
+      RemoteBindings bindings = (RemoteBindings) resolveAnnotation(RemoteBindings.class);
+      binding = bindings != null ? bindings.value()[0] : (RemoteBinding) resolveAnnotation(RemoteBinding.class);
+      
+      /* Get the JNDI of the clustered remote proxy, look it up and 
+       * return it */
+      String jndiName = ProxyFactoryHelper.getRemoteJndiName(this, binding);
+      return Util.lookup(jndiName, Object.class);
+   }
 
    protected Object invokeHomeMethod(MethodInfo info, MethodInvocation invocation) throws Throwable
    {
       Method unadvisedMethod = info.getUnadvisedMethod();
       if (unadvisedMethod.getName().equals("create"))
       {
-         return createRemoteProxy(null);
+         Object proxy = null;
+         if (isClustered())
+         {
+            proxy = createdClustereProxy();
+         }
+         else
+         {
+            proxy = createRemoteProxy(null);
+         }
+         
+         if (log.isTraceEnabled())
+         {
+            log.trace("Remote home.create() method called and will return " + proxy);
+         }
+         
+         return proxy;
       }
       else // remove
       {
@@ -424,4 +455,10 @@
    {
       throw new RuntimeException("NYI");
    }
+   
+   @Override
+   public boolean isClustered()
+   {
+      return hasAnnotation(getBeanClass(), org.jboss.annotation.ejb.Clustered.class.getName());
+   }
 }

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessHomeClusteredProxy.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessHomeClusteredProxy.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/main/org/jboss/ejb3/stateless/StatelessHomeClusteredProxy.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,133 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2006, 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.ejb3.stateless;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import org.jboss.aop.Dispatcher;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.joinpoint.MethodInvocation;
+import org.jboss.aop.util.MethodHashing;
+import org.jboss.aop.util.PayloadKey;
+import org.jboss.aspects.asynch.AsynchMixin;
+import org.jboss.aspects.asynch.AsynchProvider;
+import org.jboss.aspects.remoting.ClusterConstants;
+import org.jboss.aspects.remoting.FamilyWrapper;
+import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
+import org.jboss.ejb3.Container;
+import org.jboss.ejb3.Ejb3Registry;
+import org.jboss.ejb3.JBossProxy;
+import org.jboss.ejb3.ProxyUtils;
+import org.jboss.ejb3.asynchronous.AsynchronousInterceptor;
+import org.jboss.ejb3.remoting.BaseRemoteProxy;
+import org.jboss.ejb3.remoting.ClusteredIsLocalInterceptor;
+import org.jboss.ejb3.remoting.IsLocalInterceptor;
+import org.jboss.ejb3.session.BaseSessionRemoteProxy;
+import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
+
+/**
+ * InvocationHandler for a clustered home SLSB proxy.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class StatelessHomeClusteredProxy extends BaseSessionRemoteProxy
+{   
+   /** The serialVersionUID */
+   private static final long serialVersionUID = 1485643483431262990L;
+   
+   protected FamilyWrapper family;
+   protected LoadBalancePolicy lbPolicy;
+   protected String partitionName;
+
+   public StatelessHomeClusteredProxy(Container container, Interceptor[] interceptors, FamilyWrapper family, LoadBalancePolicy lbPolicy, String partitionName)
+   {
+      super(container, interceptors);
+      this.family = family;
+      this.lbPolicy = lbPolicy;
+      this.partitionName = partitionName;
+   }
+
+   public StatelessHomeClusteredProxy(String containerId, String containerGuid, Interceptor[] interceptors, FamilyWrapper family, LoadBalancePolicy lbPolicy, String partitionName)
+   {
+      super(containerId, containerGuid, interceptors);
+      this.family = family;
+      this.lbPolicy = lbPolicy;
+      this.partitionName = partitionName;
+   }
+
+   public StatelessHomeClusteredProxy()
+   {
+   }
+
+   public Object invoke(Object proxy, Method method, Object[] args)
+           throws Throwable
+   {
+      long hash = MethodHashing.calculateHash(method);
+      Object ret = ProxyUtils.handleCallLocally(hash, proxy, this, method, args);
+      if (ret != null)
+      {
+         return ret;
+      }
+      
+      ret = handleEjb21CallLocally(method, args);
+      if (ret != null)
+      {
+         return ret;
+      }
+
+      MethodInvocation sri = new MethodInvocation(interceptors, hash, method, method, null);
+      sri.setArguments(args);
+      sri.setInstanceResolver(metadata);
+      sri.getMetaData().addMetaData(Dispatcher.DISPATCHER, Dispatcher.OID, containerId, PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(ClusterConstants.CLUSTERED_REMOTING, ClusterConstants.CLUSTER_FAMILY_WRAPPER, family, PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(ClusterConstants.CLUSTERED_REMOTING, ClusterConstants.LOADBALANCE_POLICY, lbPolicy, PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(InvokeRemoteInterceptor.REMOTING, InvokeRemoteInterceptor.SUBSYSTEM, "AOP", PayloadKey.AS_IS);
+      sri.getMetaData().addMetaData(ClusteredIsLocalInterceptor.PARTITION_NAME, ClusteredIsLocalInterceptor.PARTITION_NAME, partitionName, PayloadKey.TRANSIENT);
+      sri.getMetaData().addMetaData(IsLocalInterceptor.IS_LOCAL, IsLocalInterceptor.GUID, containerGuid, PayloadKey.AS_IS);
+      
+      return sri.invokeNext();
+   }
+
+   public String toString()
+   {
+      return containerId.toString() + ":Home:Clustered";
+   }
+
+   public Object getAsynchronousProxy(Object proxy)
+   {
+      throw new RuntimeException("NOT IMPLEMENTED");
+   }
+
+   private Object handleEjb21CallLocally(Method method, Object[] args)
+   {
+      if (method.equals(ProxyUtils.GET_HOME_HANDLE))
+      {
+         return homeHandle;
+      }
+      else if (method.equals(ProxyUtils.GET_EJB_METADATA))
+      {
+         return ejbMetaData;
+      }
+
+      return null;
+   }
+}

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/resources/test/ejbthree1109/test-interceptors-aop.xml
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/resources/test/ejbthree1109/test-interceptors-aop.xml	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/resources/test/ejbthree1109/test-interceptors-aop.xml	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE aop PUBLIC
+   "-//JBoss//DTD JBOSS AOP 1.0//EN"
+   "http://labs.jboss.com/portal/jbossaop/dtd/jboss-aop_1_0.dtd">
+
+<aop>
+   <interceptor class="org.jboss.ejb3.test.ejbthree1109.LoadBalanceAssertInterceptor" scope="PER_VM"/>
+
+   <stack name="TestClusteredStatelessSessionClientInterceptors">
+      <interceptor-ref name="org.jboss.ejb3.remoting.ClusteredIsLocalInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.remoting.ClusterChooserInterceptor"/>
+      <interceptor-ref name="org.jboss.ejb3.test.ejbthree1109.LoadBalanceAssertInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+   </stack>
+   
+   <stack name="TestClusteredStatefulSessionClientInterceptors">
+      <interceptor-ref name="org.jboss.ejb3.remoting.ClusteredIsLocalInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.security.SecurityClientInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.tx.ClientTxPropagationInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.remoting.ClusterChooserInterceptor"/>
+      <interceptor-ref name="org.jboss.ejb3.test.ejbthree1109.LoadBalanceAssertInterceptor"/>
+      <interceptor-ref name="org.jboss.aspects.remoting.InvokeRemoteInterceptor"/>
+   </stack>
+   
+</aop>
\ No newline at end of file

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/LoadBalanceAssertInterceptor.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/LoadBalanceAssertInterceptor.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/LoadBalanceAssertInterceptor.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,79 @@
+/*
+ * 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.ejb3.test.ejbthree1109;
+
+import java.io.Serializable;
+
+import javax.ejb.EJBHome;
+
+import junit.framework.TestCase;
+
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aop.metadata.SimpleMetaData;
+import org.jboss.aspects.remoting.ClusterConstants;
+import org.jboss.aspects.remoting.FamilyWrapper;
+import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
+import org.jboss.ejb3.stateless.StatelessClusterProxyFactory;
+import org.jboss.logging.Logger;
+import org.jboss.remoting.InvokerLocator;
+
+/**
+ * LoadBalanceAsserInterceptor.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class LoadBalanceAssertInterceptor implements Interceptor, ClusterConstants, Serializable
+{
+   /** The serialVersionUID */
+   private static final long serialVersionUID = -4720740446500840159L;
+   
+   private static final Logger log = Logger.getLogger(LoadBalanceAssertInterceptor.class);
+   
+   private InvokerLocator prevChosenTarget;
+   
+   public String getName()
+   {
+      return LoadBalanceAssertInterceptor.class.getSimpleName();
+   }
+
+   public Object invoke(Invocation invocation) throws Throwable
+   {
+      String family = (String) invocation.getMetaData(CLUSTERED_REMOTING, CLUSTER_FAMILY);
+      if (family.endsWith(StatelessClusterProxyFactory.HOME_FAMILY))
+      {
+         InvokerLocator chosenTarget = (InvokerLocator)invocation.getMetaData(InvokeRemoteInterceptor.REMOTING, InvokeRemoteInterceptor.INVOKER_LOCATOR);
+         
+         synchronized (this)
+         {
+            if (prevChosenTarget != null)
+            {
+               log.info("Compare targets, previous " + prevChosenTarget + " with chosen " + chosenTarget);
+               TestCase.assertNotSame(prevChosenTarget, chosenTarget);
+            }
+            prevChosenTarget = chosenTarget;
+         }
+      }
+      
+      return invocation.invokeNext();
+   }
+}

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemote.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemote.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemote.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,37 @@
+/*
+ * 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.ejb3.test.ejbthree1109;
+
+import java.rmi.RemoteException;
+import java.util.UUID;
+
+import javax.ejb.EJBObject;
+
+/**
+ * WaiterRemote.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public interface WaiterRemote extends EJBObject
+{
+   UUID whoServes(String servee) throws RemoteException;
+}

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemoteHome.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemoteHome.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterRemoteHome.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,39 @@
+/*
+ * 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.ejb3.test.ejbthree1109;
+
+import java.rmi.RemoteException;
+
+import javax.ejb.CreateException;
+import javax.ejb.EJBHome;
+
+/**
+ * WaiterRemoteHome.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public interface WaiterRemoteHome extends EJBHome
+{
+   public WaiterRemote create() throws CreateException, RemoteException;
+   
+   public WaiterRemote create(String text) throws CreateException, RemoteException;
+}

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSfsbEjb21Bean.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSfsbEjb21Bean.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSfsbEjb21Bean.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,62 @@
+/*
+ * 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.ejb3.test.ejbthree1109;
+
+import java.util.UUID;
+
+import javax.ejb.Init;
+import javax.ejb.Remote;
+import javax.ejb.RemoteHome;
+import javax.ejb.Stateful;
+
+import org.jboss.annotation.ejb.Clustered;
+import org.jboss.annotation.ejb.RemoteBinding;
+import org.jboss.logging.Logger;
+
+/**
+ * WaiterBean.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+ at Stateful
+ at Clustered()
+ at Remote(WaiterRemote.class)
+ at RemoteHome(WaiterRemoteHome.class)
+ at RemoteBinding(jndiBinding = "WaiterSfsbEjb21Bean/remote", interceptorStack = "TestClusteredStatefulSessionClientInterceptors")
+public class WaiterSfsbEjb21Bean
+{
+   private static final Logger log = Logger.getLogger(WaiterSlsbEjb21Bean.class);
+         
+   private static final UUID id = UUID.randomUUID();
+
+   public UUID whoServes(String servee)
+   {
+      log.info(id + " serves "+ servee);
+      return id;
+   }
+   
+   @Init
+   public void ejbCreate(String text)
+   {
+      log.info("ejbCreate(" + text + ") and hashcode " + this.hashCode());
+   }
+}
\ No newline at end of file

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSlsbEjb21Bean.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSlsbEjb21Bean.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/WaiterSlsbEjb21Bean.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,56 @@
+/*
+ * 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.ejb3.test.ejbthree1109;
+
+import java.util.UUID;
+
+import javax.ejb.Remote;
+import javax.ejb.RemoteHome;
+import javax.ejb.Stateless;
+
+import org.jboss.annotation.ejb.Clustered;
+import org.jboss.annotation.ejb.RemoteBinding;
+import org.jboss.ha.framework.interfaces.RoundRobin;
+import org.jboss.logging.Logger;
+
+/**
+ * WaiterBean.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+ at Stateless
+ at Clustered(loadBalancePolicy=RoundRobin.class)
+ at Remote(WaiterRemote.class)
+ at RemoteHome(WaiterRemoteHome.class)
+ at RemoteBinding(jndiBinding = "WaiterSlsbEjb21Bean/remote", interceptorStack = "TestClusteredStatelessSessionClientInterceptors")
+public class WaiterSlsbEjb21Bean
+{
+   private static final Logger log = Logger.getLogger(WaiterSlsbEjb21Bean.class);
+         
+   private static final UUID id = UUID.randomUUID();
+
+   public UUID whoServes(String servee)
+   {
+      log.info(id + " serves "+ servee);
+      return id;
+   }
+}
\ No newline at end of file

Added: branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/unit/ClusteredHomeBeanUnitTestCase.java
===================================================================
--- branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/unit/ClusteredHomeBeanUnitTestCase.java	                        (rev 0)
+++ branches/JBPAPP_4_2_0_GA_CP/ejb3/src/test/org/jboss/ejb3/test/ejbthree1109/unit/ClusteredHomeBeanUnitTestCase.java	2008-06-10 09:41:28 UTC (rev 74347)
@@ -0,0 +1,124 @@
+/*
+ * 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.ejb3.test.ejbthree1109.unit;
+
+import java.util.Properties;
+import java.util.UUID;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import junit.framework.Test;
+
+import org.jboss.ejb3.test.ejbthree1109.WaiterRemote;
+import org.jboss.ejb3.test.ejbthree1109.WaiterRemoteHome;
+import org.jboss.test.JBossClusteredTestCase;
+
+/**
+ * ClusteredHomeBeanUnitTestCase.
+ * 
+ * @author <a href="mailto:galder.zamarreno at jboss.com">Galder Zamarreno</a>
+ */
+public class ClusteredHomeBeanUnitTestCase extends JBossClusteredTestCase
+{
+   public ClusteredHomeBeanUnitTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite() throws Exception
+   {
+      return getDeploySetup(ClusteredHomeBeanUnitTestCase.class, "ejbthree1109.jar");
+   }
+   
+   @Override
+   protected void setUp() throws Exception
+   {
+      getLog().info(getName());
+   }
+
+   @Override
+   protected void tearDown() throws Exception
+   {
+   }
+
+   public void testSlsbHomeAndBeanLoadBalancing() throws Exception
+   {
+      Context ctx = getFirstInitialContext();
+      
+      WaiterRemoteHome home = (WaiterRemoteHome)ctx.lookup("WaiterSlsbEjb21Bean/home");
+      log.info("Ejb21 home lookup returned " + home);
+      for (int i = 0; i < 5; i++)
+      {
+         /* Home load balancing is checked via LoadBalanceAssertInterceptor */
+         WaiterRemote waiter = home.create();
+         log.info("Create call on Ejb21 home returned " + waiter);
+         UUID previous = null;
+         for (int j = 0; j < 5; j++)
+         {
+            UUID current = waiter.whoServes("me-" + i + "-" + j);
+
+            if (previous != null)
+            {
+               log.info("Compare UUIDs, previous " + previous + " with current " + current);
+               assertNotSame(previous, current);
+            }
+            
+            previous = current;
+         }
+      }
+   }
+   
+   public void testSfsbHomeAndBeanLoadBalancing() throws Exception
+   {
+      Context ctx = getFirstInitialContext();
+      
+      WaiterRemoteHome home = (WaiterRemoteHome)ctx.lookup("WaiterSfsbEjb21Bean/home");
+      log.info("Ejb21 home lookup returned " + home);
+      for (int i = 0; i < 5; i++)
+      {
+         /* Home load balancing is checked via LoadBalanceAssertInterceptor */
+         WaiterRemote waiter = home.create("new-" + i);
+         log.info("Create call on Ejb21 home returned " + waiter);
+         UUID previous = null;
+         for (int j = 0; j < 5; j++)
+         {
+            UUID current = waiter.whoServes("me-" + i + "-" + j);
+
+            if (previous != null)
+            {
+               log.info("Compare UUIDs, previous " + previous + " with current " + current);
+               assertSame(previous, current);
+            }            
+         }
+      }
+   }
+   
+   private Context getFirstInitialContext() throws Exception
+   {
+      String[] urls = getNamingURLs();
+      Properties env = new Properties();
+      env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
+      env.setProperty(Context.PROVIDER_URL, urls[0]);
+      return new InitialContext(env);
+   }
+}




More information about the jboss-cvs-commits mailing list