[jboss-cvs] JBossAS SVN: r73641 - in projects/ejb3/trunk/core/src: main/java/org/jboss/ejb3/proxy/factory/stateless and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Fri May 23 18:08:18 EDT 2008


Author: bstansberry at jboss.com
Date: 2008-05-23 18:08:18 -0400 (Fri, 23 May 2008)
New Revision: 73641

Added:
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/unit/StatefulProxyFactoryLoadBalancingTestCase.java
Modified:
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateful/StatefulClusterProxyFactory.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateless/StatelessClusterProxyFactory.java
   projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/remoting/ClusteredIsLocalInterceptor.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTester.java
   projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTesterBase.java
Log:
[EJBTHREE-1375] Properly load balance SFSB creation

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateful/StatefulClusterProxyFactory.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateful/StatefulClusterProxyFactory.java	2008-05-23 21:36:44 UTC (rev 73640)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateful/StatefulClusterProxyFactory.java	2008-05-23 22:08:18 UTC (rev 73641)
@@ -21,6 +21,7 @@
  */
 package org.jboss.ejb3.proxy.factory.stateful;
 
+import java.lang.reflect.Proxy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -30,8 +31,11 @@
 import org.jboss.aop.AspectManager;
 import org.jboss.aop.Dispatcher;
 import org.jboss.aop.advice.AdviceStack;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aspects.remoting.ClusterChooserInterceptor;
+import org.jboss.aspects.remoting.ClusteredPojiProxy;
 import org.jboss.aspects.remoting.FamilyWrapper;
-import org.jboss.aspects.remoting.Remoting;
+import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
 import org.jboss.ejb3.SpecificationInterfaceType;
 import org.jboss.ejb3.annotation.Clustered;
 import org.jboss.ejb3.annotation.RemoteBinding;
@@ -41,12 +45,14 @@
 import org.jboss.ejb3.proxy.factory.RemoteProxyFactory;
 import org.jboss.ejb3.proxy.factory.RemoteProxyFactoryRegistry;
 import org.jboss.ejb3.proxy.handler.stateful.StatefulClusteredInvocationHandler;
+import org.jboss.ejb3.remoting.ClusteredIsLocalInterceptor;
 import org.jboss.ejb3.remoting.LoadBalancePolicyNotRegisteredException;
 import org.jboss.ejb3.session.ProxyAccessType;
 import org.jboss.ejb3.session.SessionContainer;
 import org.jboss.ejb3.session.SessionSpecContainer;
-import org.jboss.ha.client.loadbalance.FirstAvailable;
 import org.jboss.ha.client.loadbalance.LoadBalancePolicy;
+import org.jboss.ha.client.loadbalance.RoundRobin;
+import org.jboss.ha.client.loadbalance.aop.FirstAvailable;
 import org.jboss.ha.framework.interfaces.ClusteringTargetsRepository;
 import org.jboss.ha.framework.interfaces.DistributedReplicantManager;
 import org.jboss.ha.framework.interfaces.HAPartition;
@@ -77,6 +83,7 @@
    private HATarget hatarget;
    private String proxyFamilyName;
    private String partitionName;
+   private HAPartition partition;
    private LoadBalancePolicy lbPolicy;
    private FamilyWrapper wrapper;
 
@@ -141,12 +148,12 @@
    {
       this.init();
       
-      RemoteBinding binding = this.getBinding();
       InvokerLocator locator = this.getLocator();
       SessionContainer container = this.getContainer();
       partitionName = container.getPartitionName();
       proxyFamilyName = container.getDeploymentQualifiedName() + locator.getProtocol() + partitionName;
-      HAPartition partition = HAPartitionLocator.getHAPartitionLocator().getHAPartition(partitionName, container.getInitialContextProperties());
+      partition = HAPartitionLocator.getHAPartitionLocator().getHAPartition(partitionName, container.getInitialContextProperties());
+      drm = partition.getDistributedReplicantManager();
       hatarget = new HATarget(partition, proxyFamilyName, locator, HATarget.ENABLE_INVOCATIONS);
       ClusteringTargetsRepository.initTarget(proxyFamilyName, hatarget.getReplicants());
       container.getClusterFamilies().put(proxyFamilyName, hatarget);
@@ -171,14 +178,44 @@
       }
       wrapper = new FamilyWrapper(proxyFamilyName, hatarget.getReplicants());
       
-      this.drm = partition.getDistributedReplicantManager();
       drm.registerListener(proxyFamilyName, this);
       
       super.start();
       
+      // Set up the proxy to ourself. Needs to be clustered so it can load 
+      // balance requests (EJBTHREE-1375). We use the home load balance policy.
+      
+      LoadBalancePolicy factoryLBP = null;
+      if (clustered.homeLoadBalancePolicy() == null || clustered.homeLoadBalancePolicy().equals(ClusteredDefaults.LOAD_BALANCE_POLICY_DEFAULT))
+      {
+         factoryLBP = new RoundRobin();
+      }
+      else
+      {
+         String policyClass = clustered.homeLoadBalancePolicy();
+         try
+         {
+            RemoteProxyFactoryRegistry registry = container.getDeployment().getRemoteProxyFactoryRegistry();
+            Class<LoadBalancePolicy> policy = registry.getLoadBalancePolicy(policyClass);
+            policyClass = policy.getName();
+         }
+         catch (LoadBalancePolicyNotRegisteredException e){}
+         
+         factoryLBP = (LoadBalancePolicy)Thread.currentThread().getContextClassLoader().loadClass(policyClass)
+               .newInstance();
+      }
+      
       Class<?>[] interfaces = {ProxyFactory.class};
       String targetId = getTargetId();
-      Object factoryProxy = Remoting.createPojiProxy(targetId, interfaces, ProxyFactoryHelper.getClientBindUrl(binding));
+      Interceptor[] interceptors = { new ClusteredIsLocalInterceptor(), 
+                                     new ClusterChooserInterceptor(), 
+                                     InvokeRemoteInterceptor.singleton
+      };
+      
+      // We can use the same FamilyWrapper as we use for the bean
+      ClusteredPojiProxy proxy = new ClusteredPojiProxy(targetId, locator, interceptors, wrapper, 
+                                                        factoryLBP, partitionName, null);
+      Object factoryProxy =  Proxy.newProxyInstance(interfaces[0].getClassLoader(), interfaces, proxy);
       try
       {
          Util.rebind(getContainer().getInitialContext(), jndiName + PROXY_FACTORY_NAME, factoryProxy);
@@ -213,7 +250,7 @@
       AdviceStack stack = AspectManager.instance().getAdviceStack(stackName);
       if (stack == null) throw new RuntimeException("unable to find interceptor stack: " + stackName);
       StatefulClusteredInvocationHandler handler = new StatefulClusteredInvocationHandler(getContainer(), stack.createInterceptors(getContainer()
-            .getAdvisor(), null), this.wrapper, this.lbPolicy, partitionName, id, businessInterfaceType);
+            .getAdvisor(), null), this.wrapper, this.lbPolicy, partitionName, getLocator(), id, businessInterfaceType);
       
       if(type.equals(SpecificationInterfaceType.EJB21))
       {
@@ -254,7 +291,7 @@
       {
          // Update the FamilyClusterInfo with the new targets
          ArrayList targets = new ArrayList(newReplicants);
-         wrapper.get().updateClusterInfo(targets, newReplicantsViewId); 
+         wrapper.get().updateClusterInfo(targets, newReplicantsViewId);
       }
       catch (Exception e)
       {

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateless/StatelessClusterProxyFactory.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateless/StatelessClusterProxyFactory.java	2008-05-23 21:36:44 UTC (rev 73640)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/proxy/factory/stateless/StatelessClusterProxyFactory.java	2008-05-23 22:08:18 UTC (rev 73641)
@@ -90,6 +90,7 @@
       String partitionName = container.getPartitionName();
       proxyFamilyName = container.getDeploymentQualifiedName() + locator.getProtocol() + partitionName;
       HAPartition partition = HAPartitionLocator.getHAPartitionLocator().getHAPartition(partitionName, container.getInitialContextProperties());
+      drm = partition.getDistributedReplicantManager();
       hatarget = new HATarget(partition, proxyFamilyName, locator, HATarget.ENABLE_INVOCATIONS);
       ClusteringTargetsRepository.initTarget(proxyFamilyName, hatarget.getReplicants());
       
@@ -115,7 +116,6 @@
       }
       wrapper = new FamilyWrapper(proxyFamilyName, hatarget.getReplicants());
       
-      this.drm = partition.getDistributedReplicantManager();
       drm.registerListener(proxyFamilyName, this);
       
       super.start();
@@ -132,7 +132,6 @@
 
    public Object createProxyBusiness(String businessInterfaceClassName)
    {
-      Object containerId = getContainer().getObjectName().getCanonicalName();
       String stackName = this.getStackNameInterceptors();
       if (binding.interceptorStack() != null && !binding.interceptorStack().equals(""))
       {
@@ -146,7 +145,7 @@
       String partitionName = ((StatelessContainer) getContainer()).getPartitionName();
 
       proxy = constructProxy(new StatelessClusteredInvocationHandler(getContainer(), stack.createInterceptors(
-            getContainer().getAdvisor(), null), wrapper, lbPolicy, partitionName, businessInterfaceClassName),
+            getContainer().getAdvisor(), null), wrapper, lbPolicy, partitionName, getLocator(), businessInterfaceClassName),
             SpecificationInterfaceType.EJB30_BUSINESS);
       return proxy;
    }
@@ -162,6 +161,7 @@
       return false;
    }
    
+   @SuppressWarnings("unchecked")
    public synchronized void replicantsChanged (String key, 
          List newReplicants, 
          int newReplicantsViewId,
@@ -170,7 +170,7 @@
       try
       {
          // Update the FamilyClusterInfo with the new targets
-         ArrayList targets = new ArrayList(newReplicants);
+         ArrayList<Object> targets = new ArrayList<Object>(newReplicants);
          wrapper.get().updateClusterInfo(targets, newReplicantsViewId);
          
          // Rebind the proxy as the old one has been serialized

Modified: projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/remoting/ClusteredIsLocalInterceptor.java
===================================================================
--- projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/remoting/ClusteredIsLocalInterceptor.java	2008-05-23 21:36:44 UTC (rev 73640)
+++ projects/ejb3/trunk/core/src/main/java/org/jboss/ejb3/remoting/ClusteredIsLocalInterceptor.java	2008-05-23 22:08:18 UTC (rev 73641)
@@ -23,6 +23,7 @@
 
 import org.jboss.aop.Dispatcher;
 import org.jboss.aop.joinpoint.Invocation;
+import org.jboss.aspects.remoting.ClusterConstants;
 import org.jboss.logging.Logger;
 import org.jboss.ejb3.Container;
 import org.jboss.ejb3.EJBContainer;
@@ -42,8 +43,6 @@
    private static final long serialVersionUID = 5765933584762500725L;
 
    private static final Logger log = Logger.getLogger(ClusteredIsLocalInterceptor.class);
-
-   public static final String PARTITION_NAME = "PARTITION_NAME";
    
    public Object invoke(Invocation invocation) throws Throwable
    {
@@ -58,7 +57,7 @@
    private Container findLocalContainer(Invocation invocation)
    {
       String guid = (String)invocation.getMetaData(IS_LOCAL, GUID);
-      String partitionName = (String) invocation.getMetaData(PARTITION_NAME, PARTITION_NAME);
+      String partitionName = (String) invocation.getMetaData(ClusterConstants.CLUSTERED_REMOTING, ClusterConstants.PARTITION_NAME);
       
       Container container = null;
       try

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTester.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTester.java	2008-05-23 21:36:44 UTC (rev 73640)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTester.java	2008-05-23 22:08:18 UTC (rev 73641)
@@ -39,6 +39,8 @@
    
    VMID getVMID();
    
+   VMID getCreatorVMID();
+   
    VMID getVMIDFromRemote(VMTester remote) throws NamingException;
    
    VMID getVMIDFromRemoteLookup(String jndiURL, String name) throws NamingException;

Modified: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTesterBase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTesterBase.java	2008-05-23 21:36:44 UTC (rev 73640)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/islocal/VMTesterBase.java	2008-05-23 22:08:18 UTC (rev 73641)
@@ -38,11 +38,18 @@
 {
    private static final Logger log = Logger.getLogger(VMTesterBase.class);
    
+   private final VMID creatorVMID = VMTester.VMID;
+   
    public VMID getVMID()
    {
       log.debug("Ignore; just a stack trace", new Exception("Ignore; just a stack trace"));
       return VMTester.VMID;
    }
+   
+   public VMID getCreatorVMID()
+   {
+      return creatorVMID;
+   }
 
    public VMID getVMIDFromRemoteLookup(String jndiURL, String name)
    throws NamingException

Added: projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/unit/StatefulProxyFactoryLoadBalancingTestCase.java
===================================================================
--- projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/unit/StatefulProxyFactoryLoadBalancingTestCase.java	                        (rev 0)
+++ projects/ejb3/trunk/core/src/test/java/org/jboss/ejb3/test/clusteredsession/unit/StatefulProxyFactoryLoadBalancingTestCase.java	2008-05-23 22:08:18 UTC (rev 73641)
@@ -0,0 +1,110 @@
+/*
+ * 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.clusteredsession.unit;
+
+import java.rmi.dgc.VMID;
+import java.util.Properties;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+
+import junit.framework.Test;
+
+import org.jboss.ejb3.test.clusteredsession.islocal.VMTester;
+import org.jboss.test.JBossClusteredTestCase;
+
+/**
+ * @author Brian Stansberry
+ *
+ */
+public class StatefulProxyFactoryLoadBalancingTestCase extends JBossClusteredTestCase
+{
+   public static final String TESTER_JNDI_NAME = "NonClusteredStatelessRemote";
+   
+   /**
+    * Create a new StatefulProxyFactoryLoadBalancingTestCase.
+    * 
+    * @param name
+    */
+   public StatefulProxyFactoryLoadBalancingTestCase(String name)
+   {
+      super(name);
+   }
+
+   public static Test suite() throws Exception
+   {
+      return getDeploySetup(StatefulProxyFactoryLoadBalancingTestCase.class,
+                           "clusteredsession-local.jar");
+   }
+   
+   public void testFactoryProxyLoadBalancing() throws Exception
+   {
+      String[] jndiURLs = getNamingURLs();
+      
+      Properties env1 = new Properties();
+      env1.setProperty(Context.PROVIDER_URL, jndiURLs[0]);
+      env1.setProperty("jnp.disableDiscovery", "true");
+      InitialContext ctx1 = new InitialContext(env1);
+      VMTester tester1 = (VMTester) ctx1.lookup(TESTER_JNDI_NAME);
+      
+      VMID create1 = tester1.getCreatorVMID();
+      // confirm that the bean didn't have to migrate
+      assertEquals(create1, tester1.getVMID());
+      
+      // Get another bean from the same server; should target
+      // a different server from the first
+      VMTester tester2 = (VMTester) ctx1.lookup(TESTER_JNDI_NAME);
+      
+      VMID create2 = tester2.getCreatorVMID();
+      assertEquals(create2, tester2.getVMID());      
+      assertFalse(create1.equals(create2));
+      
+      // A third bean should come from the same as the first
+      VMTester tester3 = (VMTester) ctx1.lookup(TESTER_JNDI_NAME);
+      
+      VMID create3 = tester3.getCreatorVMID();
+      assertEquals(create3, tester3.getVMID());
+      assertEquals(create1, create3);
+      
+      // Get the next proxy from the other server, but the overall 
+      // bean creation should still be round robin
+      
+      Properties env2 = new Properties();
+      env2.setProperty(Context.PROVIDER_URL, jndiURLs[1]);
+      env2.setProperty("jnp.disableDiscovery", "true");
+      InitialContext ctx2 = new InitialContext(env2);
+      VMTester tester4 = (VMTester) ctx2.lookup(TESTER_JNDI_NAME);
+      
+      VMID create4 = tester4.getCreatorVMID();
+      assertEquals(create4, tester4.getVMID());
+      assertEquals(create2, create4);
+      
+      // One last time
+      VMTester tester5 = (VMTester) ctx2.lookup(TESTER_JNDI_NAME);
+      
+      VMID create5 = tester5.getCreatorVMID();
+      assertEquals(create5, tester5.getVMID());
+      assertEquals(create1, create5);
+   }
+
+}




More information about the jboss-cvs-commits mailing list