[jboss-cvs] JBossAS SVN: r92304 - in projects/ejb3/trunk: proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/jndiregistrar and 6 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Thu Aug 13 08:17:46 EDT 2009
Author: jaikiran
Date: 2009-08-13 08:17:45 -0400 (Thu, 13 Aug 2009)
New Revision: 92304
Added:
projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/ejbthree1884/
projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/ejbthree1884/unit/
projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/ejbthree1884/unit/RemoteProxyFactoryJNDIBindingTestCase.java
Modified:
projects/ejb3/trunk/proxy-clustered/pom.xml
projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/jndiregistrar/JndiClusteredSessionRegistrarBase.java
projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/objectfactory/session/SessionClusteredProxyObjectFactory.java
projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/jndiregistrar/JndiSessionRegistrarBase.java
projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/objectfactory/ProxyObjectFactory.java
Log:
EJBTHREE-1884 Remote proxyfactories will now be bound to the JNDI
Modified: projects/ejb3/trunk/proxy-clustered/pom.xml
===================================================================
--- projects/ejb3/trunk/proxy-clustered/pom.xml 2009-08-13 11:43:08 UTC (rev 92303)
+++ projects/ejb3/trunk/proxy-clustered/pom.xml 2009-08-13 12:17:45 UTC (rev 92304)
@@ -90,7 +90,7 @@
<dependency>
<groupId>org.jboss.ejb3</groupId>
<artifactId>jboss-ejb3-proxy-impl</artifactId>
- <version>1.0.1</version>
+ <version>1.0.4-SNAPSHOT</version>
</dependency>
<dependency>
@@ -100,6 +100,19 @@
</dependency>
<dependency>
+ <groupId>org.jboss.naming</groupId>
+ <artifactId>jnpserver</artifactId>
+ <version>5.0.0.CR1</version>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.jboss</groupId>
+ <artifactId>jboss-common-core</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
<groupId>org.jboss.cluster</groupId>
<artifactId>jboss-ha-client</artifactId>
<version>1.1.1.GA</version>
Modified: projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/jndiregistrar/JndiClusteredSessionRegistrarBase.java
===================================================================
--- projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/jndiregistrar/JndiClusteredSessionRegistrarBase.java 2009-08-13 11:43:08 UTC (rev 92303)
+++ projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/jndiregistrar/JndiClusteredSessionRegistrarBase.java 2009-08-13 12:17:45 UTC (rev 92304)
@@ -22,6 +22,8 @@
package org.jboss.ejb3.proxy.clustered.jndiregistrar;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -29,27 +31,36 @@
import java.util.concurrent.atomic.AtomicInteger;
import javax.naming.Context;
+import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import org.jboss.aop.Advisor;
+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.InvokeRemoteInterceptor;
import org.jboss.ejb3.proxy.clustered.objectfactory.ClusteredProxyFactoryReferenceAddressTypes;
import org.jboss.ejb3.proxy.clustered.registry.ProxyClusteringInfo;
import org.jboss.ejb3.proxy.clustered.registry.ProxyClusteringRegistry;
import org.jboss.ejb3.proxy.clustered.registry.ProxyClusteringRegistryListener;
+import org.jboss.ejb3.proxy.impl.factory.ProxyFactory;
import org.jboss.ejb3.proxy.impl.jndiregistrar.JndiReferenceBinding;
import org.jboss.ejb3.proxy.impl.jndiregistrar.JndiReferenceBindingSet;
import org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase;
import org.jboss.ejb3.proxy.impl.objectfactory.ProxyFactoryReferenceAddressTypes;
+import org.jboss.ejb3.proxy.impl.remoting.IsLocalProxyFactoryInterceptor;
+import org.jboss.ha.client.loadbalance.LoadBalancePolicy;
import org.jboss.ha.framework.interfaces.FamilyClusterInfo;
import org.jboss.logging.Logger;
import org.jboss.metadata.ejb.jboss.ClusterConfigMetaData;
+import org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData;
import org.jboss.metadata.ejb.jboss.JBossSessionBeanMetaData;
+import org.jboss.naming.Util;
import org.jboss.remoting.InvokerLocator;
-
-
/**
* Responsible for binding of ObjectFactories and creation/registration of
* associated ProxyFactories, centralizing operations common to that of all
@@ -57,23 +68,24 @@
*
* @author Brian Stansberry
*/
-public abstract class JndiClusteredSessionRegistrarBase
- extends JndiSessionRegistrarBase
- implements ProxyClusteringRegistryListener
+public abstract class JndiClusteredSessionRegistrarBase extends JndiSessionRegistrarBase
+ implements
+ ProxyClusteringRegistryListener
{
// --------------------------------------------------------------------------------||
// Class Members ------------------------------------------------------------------||
// --------------------------------------------------------------------------------||
-
+
private static final Logger log = Logger.getLogger(JndiClusteredSessionRegistrarBase.class);
-
+
// --------------------------------------------------------------------------------||
// Instance Members ---------------------------------------------------------------||
// --------------------------------------------------------------------------------||
-
+
private final ProxyClusteringRegistry registry;
- private final Map<String, BeanClusteringRegistryInfo> bindingsByContainer = new ConcurrentHashMap<String, BeanClusteringRegistryInfo>();
+ private final Map<String, BeanClusteringRegistryInfo> bindingsByContainer = new ConcurrentHashMap<String, BeanClusteringRegistryInfo>();
+
// --------------------------------------------------------------------------------||
// Constructor --------------------------------------------------------------------||
// --------------------------------------------------------------------------------||
@@ -84,11 +96,10 @@
* @param sessionProxyObjectFactoryType
* @param registry registry of clustering information about deployed containers
*/
- public JndiClusteredSessionRegistrarBase(String sessionProxyObjectFactoryType,
- ProxyClusteringRegistry registry)
+ public JndiClusteredSessionRegistrarBase(String sessionProxyObjectFactoryType, ProxyClusteringRegistry registry)
{
super(sessionProxyObjectFactoryType);
-
+
assert registry != null : "registry is null";
this.registry = registry;
this.registry.registerListener(this);
@@ -110,45 +121,90 @@
BeanClusteringRegistryInfo registryEntry = bindingsByContainer.get(beanClusteringInfo.getContainerName());
if (registryEntry != null)
{
- bindings= registryEntry.bindings;
+ bindings = registryEntry.bindings;
}
-
+
if (bindings == null)
{
// We aren't handling this bean
return;
}
-
+
Context context = bindings.getContext();
-
- FamilyClusterInfo fci = beanClusteringInfo.getFamilyWrapper().get();
+
+ FamilyClusterInfo fci = beanClusteringInfo.getFamilyWrapper().get();
String familyName = fci.getFamilyName();
-
+ log.debug("Cluster topology changed for family " + familyName + " new view id " + fci.getCurrentViewId()
+ + " - Updating JNDI bindings for container " + beanClusteringInfo.getContainerName());
+
for (JndiReferenceBinding binding : bindings.getDefaultRemoteBindings())
{
- RefAddr refAddr = getFirstRefAddr(binding.getReference(), ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME);
+ RefAddr refAddr = getFirstRefAddr(binding.getReference(),
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME);
if (refAddr != null && familyName.equals(refAddr.getContent()))
{
redecorateReferenceForClusteringTargets(binding.getReference(), fci);
rebind(context, binding.getJndiName(), binding.getReference());
}
+
+ // The remote proxyfactory in JNDI too needs to be updated with the changes in the
+ // clustering family. This involves unbinding the remote proxyfactory from JNDI,
+ // creating a new proxy for the proxyfactory with this new FamilyCluster info
+ // and finally binding this new proxy for the proxyfactory to the JNDI
+ String proxyFactoryKey = this.getSingleRequiredRefAddr(binding.getReference(),
+ ProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_PROXY_FACTORY_REGISTRY_KEY);
+ // first create a new proxy. if we run into problems creating a new proxy,
+ // let's NOT unbind the existing one since a change in topology should not
+ // result in loss of proxy factory
+ ProxyFactory existingProxyFactoryInJNDI = null;
+ try
+ {
+ existingProxyFactoryInJNDI = (ProxyFactory) context.lookup(proxyFactoryKey);
+
+ }
+ catch (NamingException ne)
+ {
+ // ignore and skip. If there is not proxyfactory bound or if there is some other
+ // issue related to naming, let's not try to "update" the proxy factory.
+ log.debug("Could not update the cluster topology changes to proxyfactory at key " + proxyFactoryKey);
+ continue;
+ }
+ // create a new proxy to proxyfactory with the available information in JNDI Reference,
+ // the previously bound proxy to the proxyfactory and the beanClusteringInfo which has
+ // contains the updated information of the cluster topology
+ ProxyFactory updatedProxyToProxyFactory = this.updateProxyForRemoteProxyFactory(proxyFactoryKey, binding
+ .getReference(), existingProxyFactoryInJNDI, beanClusteringInfo);
+ try
+ {
+ Util.rebind(context, proxyFactoryKey, updatedProxyToProxyFactory);
+ log.debug("Bound an updated proxyfactory at key " + proxyFactoryKey);
+ }
+ catch (NamingException ne)
+ {
+ // let's just log a WARN since we don't want the other operations to fail because of this
+ log.warn("Exception while rebinding a new proxyfactory at key " + proxyFactoryKey
+ + " with updated clustered topology", ne);
+ }
+
}
-
+
for (JndiReferenceBinding binding : bindings.getHomeRemoteBindings())
{
- RefAddr refAddr = getFirstRefAddr(binding.getReference(), ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME);
+ RefAddr refAddr = getFirstRefAddr(binding.getReference(),
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME);
if (refAddr != null && familyName.equals(refAddr.getContent()))
{
redecorateReferenceForClusteringTargets(binding.getReference(), fci);
rebind(context, binding.getJndiName(), binding.getReference());
}
}
-
+
for (Set<JndiReferenceBinding> businessBindings : bindings.getBusinessRemoteBindings().values())
- {
+ {
for (JndiReferenceBinding binding : businessBindings)
{
- RefAddr refAddr = getFirstRefAddr(binding.getReference(), ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME);
+ RefAddr refAddr = getFirstRefAddr(binding.getReference(),
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME);
if (refAddr != null && familyName.equals(refAddr.getContent()))
{
redecorateReferenceForClusteringTargets(binding.getReference(), fci);
@@ -156,6 +212,7 @@
}
}
}
+
}
public void beanClusteringInfoAdded(ProxyClusteringInfo beanClusteringInfo)
@@ -172,7 +229,7 @@
{
bindingsByContainer.remove(containerName);
}
- }
+ }
// --------------------------------------------------------------------------------||
// Accessors / Mutators -----------------------------------------------------------||
@@ -200,27 +257,92 @@
}
return key;
}
-
+
/**
* Overrides the superclass version to add clustering related {@link RefAddr}s
* to the binding references.
*/
@Override
- protected JndiReferenceBindingSet createJndiReferenceBindingSet(final Context context,
- final JBossSessionBeanMetaData smd, final ClassLoader cl,
- final String containerName, final String containerGuid, final Advisor advisor)
+ protected JndiReferenceBindingSet createJndiReferenceBindingSet(final Context context,
+ final JBossSessionBeanMetaData smd, final ClassLoader cl, final String containerName,
+ final String containerGuid, final Advisor advisor)
{
- JndiReferenceBindingSet bindings = super.createJndiReferenceBindingSet(context, smd, cl, containerName, containerGuid, advisor);
-
+ JndiReferenceBindingSet bindings = super.createJndiReferenceBindingSet(context, smd, cl, containerName,
+ containerGuid, advisor);
+
decorateReferencesForClustering(bindings);
-
+
// Store ref to bindings so we can rebind upon topology changes
- BeanClusteringRegistryInfo registryInfo = getBeanClusteringRegistryInfo(containerName);
+ BeanClusteringRegistryInfo registryInfo = getBeanClusteringRegistryInfo(containerName);
registryInfo.bindings = bindings;
-
+
return bindings;
}
+ @Override
+ protected ProxyFactory createProxyToProxyFactory(String proxyFactoryKey, String remotingUrl,
+ ProxyFactory proxyFactory, ClassLoader cl, JBossEnterpriseBeanMetaData smd)
+ {
+ InvokerLocator locator = null;
+ try
+ {
+ locator = new InvokerLocator(remotingUrl);
+ }
+ catch (MalformedURLException mue)
+ {
+ throw new RuntimeException("Unable to create a remoting proxy for ProxyFactory " + proxyFactoryKey
+ + " with remoting url " + remotingUrl, mue);
+
+ }
+
+ ProxyClusteringInfo bci = registry.getBeanClusteringInfo(proxyFactoryKey);
+
+ if (bci == null)
+ {
+ throw new IllegalStateException("Cannot find " + ProxyClusteringInfo.class.getSimpleName()
+ + " for proxyFactoryKey " + proxyFactoryKey);
+ }
+
+ String partitionName = bci.getPartitionName();
+
+ assert partitionName != null && !partitionName.trim().equals("") : " Partition name is required, but is not available in ProxyClusteringInfo";
+
+ String lbpClass = bci.getHomeLoadBalancePolicy().getName();
+
+ assert lbpClass != null && !lbpClass.trim().equals("") : LoadBalancePolicy.class.getSimpleName()
+ + " class name is required, but is not available in ProxyClusteringInfo";
+
+ LoadBalancePolicy loadBalancePolicy;
+ try
+ {
+ log.debug("Instantiating loadbalancer policy " + lbpClass + " for remote proxyfactory bound at key "
+ + proxyFactoryKey);
+ loadBalancePolicy = (LoadBalancePolicy) cl.loadClass(lbpClass).newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Could not load loadbalancer policy " + lbpClass
+ + " while creating a proxy to remote proxyfactory", e);
+ }
+
+ FamilyWrapper wrapper = bci.getFamilyWrapper();
+ FamilyClusterInfo familyClusterInfo = wrapper.get();
+ log.debug("Remote proxyfactory for key " + proxyFactoryKey + " will be associated with family name "
+ + familyClusterInfo.getFamilyName() + " view id " + familyClusterInfo.getCurrentViewId()
+ + " with available targets " + familyClusterInfo.getTargets());
+
+ Class<ProxyFactory>[] interfaces = this.getAllProxyFactoryInterfaces((Class<ProxyFactory>) proxyFactory
+ .getClass());
+ Interceptor[] interceptors =
+ {IsLocalProxyFactoryInterceptor.singleton, ClusterChooserInterceptor.singleton, InvokeRemoteInterceptor.singleton};
+
+ ClusteredPojiProxy handler = new ClusteredPojiProxy(proxyFactoryKey, locator, interceptors, wrapper,
+ loadBalancePolicy, partitionName, null);
+ // register the handler
+
+ return (ProxyFactory) Proxy.newProxyInstance(interfaces[0].getClassLoader(), interfaces, handler);
+ }
+
// --------------------------------------------------------------------------------||
// Private ------------------------------------------------------------------------||
// --------------------------------------------------------------------------------||
@@ -248,12 +370,12 @@
{
decorateReferenceForClustering(binding.getReference());
}
-
+
for (JndiReferenceBinding binding : bindings.getHomeRemoteBindings())
{
decorateReferenceForClustering(binding.getReference());
}
-
+
for (Set<JndiReferenceBinding> businessBindings : bindings.getBusinessRemoteBindings().values())
{
for (JndiReferenceBinding binding : businessBindings)
@@ -262,7 +384,7 @@
}
}
}
-
+
/**
* Add clustering related <code>RefAddr</code>s to <code>Reference</code>
*
@@ -270,24 +392,28 @@
*/
private void decorateReferenceForClustering(Reference ref)
{
- String proxyFactoryKey = getSingleRequiredRefAddr(ref, ProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_PROXY_FACTORY_REGISTRY_KEY);
+ String proxyFactoryKey = getSingleRequiredRefAddr(ref,
+ ProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_PROXY_FACTORY_REGISTRY_KEY);
ProxyClusteringInfo bci = registry.getBeanClusteringInfo(proxyFactoryKey);
-
+
if (bci == null)
{
- throw new IllegalStateException("Cannot find " + ProxyClusteringInfo.class.getSimpleName() +
- " for proxyFactoryKey " + proxyFactoryKey);
+ throw new IllegalStateException("Cannot find " + ProxyClusteringInfo.class.getSimpleName()
+ + " for proxyFactoryKey " + proxyFactoryKey);
}
-
- RefAddr partitionRef = new StringRefAddr(ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_PARTITION_NAME, bci.getPartitionName());
+
+ RefAddr partitionRef = new StringRefAddr(
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_PARTITION_NAME, bci.getPartitionName());
addRefAddrToReference(ref, partitionRef);
- RefAddr lbpRef = new StringRefAddr(ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_PROXY_FACTORY_LOAD_BALANCE_POLICY, bci.getHomeLoadBalancePolicy().getName());
+ RefAddr lbpRef = new StringRefAddr(
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_PROXY_FACTORY_LOAD_BALANCE_POLICY, bci
+ .getHomeLoadBalancePolicy().getName());
addRefAddrToReference(ref, lbpRef);
FamilyClusterInfo fci = bci.getFamilyWrapper().get();
- RefAddr familyNameRef = new StringRefAddr(ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME,
- fci.getFamilyName());
+ RefAddr familyNameRef = new StringRefAddr(
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_FAMILY_NAME, fci.getFamilyName());
addRefAddrToReference(ref, familyNameRef);
-
+
decorateReferenceForClusteringTargets(ref, fci);
}
@@ -304,7 +430,8 @@
for (int i = 0; i < ref.size(); i++)
{
RefAddr refAddr = ref.get(i);
- if (ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_TARGET_INVOKER_LOCATOR_URL.equals(refAddr.getType()))
+ if (ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_TARGET_INVOKER_LOCATOR_URL.equals(refAddr
+ .getType()))
{
ref.remove(i);
i--;
@@ -312,7 +439,7 @@
}
decorateReferenceForClusteringTargets(ref, fci);
}
-
+
/**
* Adds a <code>RefAddr</code> of type {@link ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_TARGET_INVOKER_LOCATOR_URL}
* to <code>ref</code> for each target associated with <code>fci</code>.
@@ -332,18 +459,18 @@
assert correctType : target + " is not an instance of InvokerLocator";
if (!correctType)
throw new IllegalStateException(target + " is not an instance of InvokerLocator");
-
+
String url = ((InvokerLocator) target).getOriginalURI();
- RefAddr targetRef = new StringRefAddr(ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_TARGET_INVOKER_LOCATOR_URL, url);
+ RefAddr targetRef = new StringRefAddr(
+ ClusteredProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_CLUSTER_TARGET_INVOKER_LOCATOR_URL, url);
addRefAddrToReference(ref, targetRef);
}
}
-
+
private void addRefAddrToReference(Reference ref, RefAddr refAddr)
{
- log.debug("Adding " + RefAddr.class.getSimpleName() + " to "
- + Reference.class.getSimpleName() + ": Type \"" + refAddr.getType() + "\", Content \""
- + refAddr.getContent() + "\"");
+ log.debug("Adding " + RefAddr.class.getSimpleName() + " to " + Reference.class.getSimpleName() + ": Type \""
+ + refAddr.getType() + "\", Content \"" + refAddr.getContent() + "\"");
ref.add(refAddr);
}
@@ -365,12 +492,12 @@
}
}
}
-
+
if (result == null)
{
throw new IllegalStateException(ref + " has no RefAddr object of type " + refAddrType);
}
-
+
return (String) result.getContent();
}
@@ -386,11 +513,96 @@
}
return null;
}
-
+
private static class BeanClusteringRegistryInfo
{
private final AtomicInteger familyCount = new AtomicInteger();
+
private JndiReferenceBindingSet bindings;
- }
+ }
+ /**
+ * Utility method to create an updated proxy for the remote proxyfactory.
+ * <br>
+ * Note that this method is expected to be used at runtime (i.e. when the EJB container bindings are
+ * available in JNDI) for recreation of an existing proxy to the proxyfactory. This method must
+ * not be used during deployment (when the JNDI bindings are not yet available). For deployment time
+ * creation of proxy for the proxyFactory is handled by the other method
+ * {@link JndiClusteredSessionRegistrarBase#createProxyToProxyFactory(String, String, ProxyFactory, ClassLoader, JBossEnterpriseBeanMetaData)}
+ *
+ * <p>
+ * Also see {@link JndiClusteredSessionRegistrarBase#clusterTopologyChanged(ProxyClusteringInfo)} method
+ * where this is used. Internally this method uses a combination of information available in JNDI and also
+ * the latest clustering topology (that is available in the passed <code>clusteringInfo</code> parameter),
+ * to (re)create an updated proxy for the proxyfactory.
+ * </p>
+ *
+ * @param proxyFactoryKey
+ * @param reference
+ * @param proxyFactory
+ * @param clusteringInfo
+ * @return
+ */
+ private ProxyFactory updateProxyForRemoteProxyFactory(String proxyFactoryKey, Reference reference,
+ ProxyFactory proxyFactory, ProxyClusteringInfo clusteringInfo)
+ {
+ // Obtain the URL for invoking upon the Registry
+ String url = this.getSingleRequiredRefAddr(reference,
+ ProxyFactoryReferenceAddressTypes.REF_ADDR_TYPE_INVOKER_LOCATOR_URL);
+
+ // Create an InvokerLocator
+ assert url != null && !url.trim().equals("") : InvokerLocator.class.getSimpleName()
+ + " URL is required, but is not specified; improperly bound reference in JNDI";
+ InvokerLocator locator;
+ try
+ {
+ locator = new InvokerLocator(url);
+ }
+ catch (MalformedURLException mue)
+ {
+ throw new RuntimeException("Unable to create a remoting proxy for ProxyFactory " + proxyFactoryKey
+ + " with remoting url " + url, mue);
+ }
+
+ // get the partition name
+ String partitionName = clusteringInfo.getPartitionName();
+
+ assert partitionName != null && !partitionName.trim().equals("") : " Partition name is required, but was not available in ProxyClusteringInfo "
+ + clusteringInfo;
+
+ // load balancer policy - Note we are creating a proxyfactory so we use the *home* loadbalance policy
+ // and not the loadbalance policy
+ Class<? extends LoadBalancePolicy> lbpClass = clusteringInfo.getHomeLoadBalancePolicy();
+
+ assert lbpClass != null : " LoadBalancePolicy is required, but is not available in the ProxyClusteringInfo "
+ + clusteringInfo;
+
+ LoadBalancePolicy loadBalancePolicyInstance = null;
+
+ try
+ {
+ // create a loadbalancer policy instance using the classloader associated with the
+ // previous proxy
+ loadBalancePolicyInstance = lbpClass.newInstance();
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("Could not create loadbalancer policy instance for " + lbpClass
+ + " while creating a proxy to remote proxyfactory", e);
+ }
+ // family wrapper (which contains the latest information of the cluster topology)
+ FamilyWrapper wrapper = clusteringInfo.getFamilyWrapper();
+ // the interfaces to be exposed by the proxy for the proxyfactory
+ Class<?>[] interfaces = this.getAllProxyFactoryInterfaces((Class<ProxyFactory>) proxyFactory.getClass());
+ // interceptors to the proxy
+ Interceptor[] interceptors =
+ {IsLocalProxyFactoryInterceptor.singleton, ClusterChooserInterceptor.singleton, InvokeRemoteInterceptor.singleton};
+ // an invocation handler which internally will apply the interceptors and do other magic :)
+ ClusteredPojiProxy handler = new ClusteredPojiProxy(proxyFactoryKey, locator, interceptors, wrapper,
+ loadBalancePolicyInstance, partitionName, null);
+
+ // finally the proxy for the proxyfactory
+ return (ProxyFactory) Proxy.newProxyInstance(interfaces[0].getClassLoader(), interfaces, handler);
+ }
+
}
Modified: projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/objectfactory/session/SessionClusteredProxyObjectFactory.java
===================================================================
--- projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/objectfactory/session/SessionClusteredProxyObjectFactory.java 2009-08-13 11:43:08 UTC (rev 92303)
+++ projects/ejb3/trunk/proxy-clustered/src/main/java/org/jboss/ejb3/proxy/clustered/objectfactory/session/SessionClusteredProxyObjectFactory.java 2009-08-13 12:17:45 UTC (rev 92304)
@@ -37,7 +37,9 @@
import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
import org.jboss.ejb3.proxy.clustered.objectfactory.ClusteredProxyFactoryReferenceAddressTypes;
import org.jboss.ejb3.proxy.impl.factory.ProxyFactory;
+import org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase;
import org.jboss.ejb3.proxy.impl.objectfactory.ProxyFactoryReferenceAddressTypes;
+import org.jboss.ejb3.proxy.impl.objectfactory.ProxyObjectFactory;
import org.jboss.ejb3.proxy.impl.objectfactory.session.SessionProxyObjectFactory;
import org.jboss.ejb3.proxy.impl.remoting.IsLocalProxyFactoryInterceptor;
import org.jboss.ha.client.loadbalance.LoadBalancePolicy;
@@ -91,8 +93,18 @@
* Here we replace the superclass implementation to create a cluster aware
* proxy that will load balance requests to the server-side proxy factory.
*
+ * Deprecated since https://jira.jboss.org/jira/browse/EJBTHREE-1884 - The
+ * {@link ProxyObjectFactory} is no longer responsible for creating a proxy
+ * to the {@link ProxyFactory}. Instead the {@link ProxyObjectFactory} will
+ * lookup in the JNDI for the {@link ProxyFactory} using the
+ * <code>proxyFactoryRegistryKey</code>. The responsibility of
+ * binding the proxyfactory to jndi will rest with the {@link JndiSessionRegistrarBase}
+ *
+ * @see The new {@link #getProxyFactoryFromJNDI(String, javax.naming.Context, java.util.Hashtable)
+ *
* {@inheritDoc}
*/
+ @Deprecated
@Override
protected ProxyFactory createProxyFactoryProxy(Name name, Map<String, List<String>> refAddrs,
String proxyFactoryRegistryKey) throws Exception
Modified: projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/jndiregistrar/JndiSessionRegistrarBase.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/jndiregistrar/JndiSessionRegistrarBase.java 2009-08-13 11:43:08 UTC (rev 92303)
+++ projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/jndiregistrar/JndiSessionRegistrarBase.java 2009-08-13 12:17:45 UTC (rev 92304)
@@ -21,8 +21,12 @@
*/
package org.jboss.ejb3.proxy.impl.jndiregistrar;
+import java.lang.reflect.Proxy;
+import java.net.MalformedURLException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -36,12 +40,16 @@
import org.jboss.aop.Advisor;
import org.jboss.aop.Dispatcher;
+import org.jboss.aop.advice.Interceptor;
+import org.jboss.aspects.remoting.InvokeRemoteInterceptor;
+import org.jboss.aspects.remoting.PojiProxy;
import org.jboss.ejb3.common.registrar.spi.DuplicateBindException;
import org.jboss.ejb3.common.registrar.spi.Ejb3RegistrarLocator;
import org.jboss.ejb3.common.registrar.spi.NotBoundException;
import org.jboss.ejb3.common.string.StringUtils;
import org.jboss.ejb3.proxy.impl.factory.ProxyFactory;
import org.jboss.ejb3.proxy.impl.objectfactory.ProxyFactoryReferenceAddressTypes;
+import org.jboss.ejb3.proxy.impl.remoting.IsLocalProxyFactoryInterceptor;
import org.jboss.ejb3.proxy.impl.remoting.ProxyRemotingUtils;
import org.jboss.logging.Logger;
import org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData;
@@ -56,9 +64,9 @@
/**
* JndiSessionRegistrarBase
- *
+ *
* Responsible for binding of ObjectFactories and
- * creation/registration of associated ProxyFactories,
+ * creation/registration of associated ProxyFactories,
* centralizing operations common to that of all Session
* EJB Implementations
*
@@ -96,8 +104,8 @@
/**
* Creates a JNDI Registrar from the specified configuration properties, none of
* which may be null.
- *
- * @param sessionProxyObjectFactoryType String representation of the JNDI Object
+ *
+ * @param sessionProxyObjectFactoryType String representation of the JNDI Object
* Factory Class Name (fully-qualified) to use for this Session EJB
*/
public JndiSessionRegistrarBase(final String sessionProxyObjectFactoryType)
@@ -130,11 +138,11 @@
// --------------------------------------------------------------------------------||
/**
- * Binds into JNDI all appropriate objects required
+ * Binds into JNDI all appropriate objects required
* by the EJB described by the specified metadata. Additionally
* responsible for creation and registration of any all ProxyFactory
* implementations required by the EJB
- *
+ *
* @param context The JNDI Context to use for binding
* @param smd the Container's metadata
* @param cl The CL of the Container
@@ -154,7 +162,7 @@
/**
* Creates all of the <code>Reference</code> objects that should be bound
* in JNDI for the EJB, and determines the correct JNDI name for each.
- * Additionally responsible for creation and registration of any all
+ * Additionally responsible for creation and registration of any all
* ProxyFactory implementations required by the EJB.
*
* @param smd the Container's metadata
@@ -162,14 +170,14 @@
* @param containerName The name under which the target container is registered
* @param containerGuid The globally-unique name of the container
* @param advisor The advisor to use for generated proxies
- *
+ *
* @return data object encapsulating the references and their JNDI names
*/
protected JndiReferenceBindingSet createJndiReferenceBindingSet(final Context context,
final JBossSessionBeanMetaData smd, final ClassLoader cl, final String containerName,
final String containerGuid, final Advisor advisor)
{
- // Log
+ // Log
String ejbName = smd.getEjbName();
log.debug("Found Session Bean: " + ejbName);
@@ -252,6 +260,8 @@
Reference defaultRemoteRef = createStandardReference(JndiSessionRegistrarBase.OBJECT_FACTORY_CLASSNAME_PREFIX
+ defaultRemoteClassName, defaultRemoteProxyFactoryKey, containerName, false);
+ // Also bind remote proxy factory to jndi
+ this.bindRemoteProxyFactory(context, defaultRemoteProxyFactoryKey, defaultClientBindUrl, factory, cl, smd);
/*
* Set up references for Home
*/
@@ -288,7 +298,7 @@
}
/*
- * If no @RemoteBindings are defined, make a default remote binding
+ * If no @RemoteBindings are defined, make a default remote binding
*/
// Get RemoteBindings
@@ -327,7 +337,7 @@
}
/*
- * If there are @RemoteBindings and a remote view
+ * If there are @RemoteBindings and a remote view
*/
// Remote Bindings are defined, create a binding for each
@@ -432,6 +442,13 @@
JndiSessionRegistrarBase.OBJECT_FACTORY_CLASSNAME_PREFIX + defaultRemoteClassName,
remoteBindingProxyFactoryKey, containerName, false);
+ // Also bind the remote proxy factory to jndi (after unbinding any existing instances)
+ if (reregister)
+ {
+ unbind(context, remoteBindingProxyFactoryKey);
+ }
+ this.bindRemoteProxyFactory(context, remoteBindingProxyFactoryKey, clientBindUrl, remoteBindingProxyFactory, cl, smd);
+
// Add a Reference Address for the Remoting URL
log.debug("Adding " + RefAddr.class.getSimpleName() + " to @RemoteBinding "
+ Reference.class.getSimpleName() + ": Type \"" + remoteBindingRemotingRefAddr.getType()
@@ -585,17 +602,17 @@
}
/**
- * Unbinds from JNDI all appropriate objects registered
+ * Unbinds from JNDI all appropriate objects registered
* by the EJB described by the specified metadata. Additionally
* responsible for destruction and deregistration of any all ProxyFactory
* implementations required by the EJB
- *
+ *
* @param context The JNDI Context to use for unbinding
* @param smd
*/
public void unbindEjb(final Context context, final JBossSessionBeanMetaData smd)
{
- // Log
+ // Log
String ejbName = smd.getEjbName();
log.debug("Unbinding JNDI References for Session Bean: " + ejbName);
@@ -635,6 +652,8 @@
// Find and deregister a remote proxy factory
String remoteProxyFactoryKey = this.getProxyFactoryRegistryKey(defaultRemoteJndiName, smd, false);
this.deregisterProxyFactory(remoteProxyFactoryKey);
+ // also remove the remote proxy factory from jndi
+ this.unbind(context, remoteProxyFactoryKey);
// Determine if remote home and business remotes are bound to same JNDI Address
boolean bindRemoteAndHomeTogether = this.isHomeAndBusinessBoundTogether(smd, false);
@@ -671,6 +690,8 @@
String remoteBindingProxyFactoryKey = this.getProxyFactoryRegistryKey(remoteBindingJndiName, smd,
false);
this.deregisterProxyFactory(remoteBindingProxyFactoryKey);
+ // also remove the remote proxy factory from jndi
+ this.unbind(context, remoteBindingProxyFactoryKey);
}
}
}
@@ -739,9 +760,9 @@
/**
* Creates and returns a new local proxy factory for this Session Bean
- *
+ *
* @param name The unique name for the ProxyFactory
- * @param containerName The name of the Container upon which Proxies
+ * @param containerName The name of the Container upon which Proxies
* from the returned ProxyFactory will invoke
* @param containerGuid The globally-unique name of the container
* @param smd The metadata representing this Session EJB
@@ -753,9 +774,9 @@
/**
* Creates and returns a new remote proxy factory for this Session Bean
- *
+ *
* @param name The unique name for the ProxyFactory
- * @param containerName The name of the Container upon which Proxies
+ * @param containerName The name of the Container upon which Proxies
* from the returned ProxyFactory will invoke
* @param containerGuid The globally-unique name of the container
* @param smd The metadata representing this Session EJB
@@ -775,8 +796,8 @@
/**
* Creates a new <code>Reference</code> whose <code>classname</code> is
- * the given <code>referenceName</code> and whose <code>classFactory</code>
- * is {@link #getSessionProxyObjectFactoryType()}, adding
+ * the given <code>referenceName</code> and whose <code>classFactory</code>
+ * is {@link #getSessionProxyObjectFactoryType()}, adding
* the requisite Registry key for the ProxyFactory and the requisite
* target EJB Container Name as ReferenceAddresses.
*/
@@ -898,7 +919,7 @@
/**
* Binds the specified Reference into JNDI at the specified address
- *
+ *
* @param context The JNDI Context to use
* @param address the address
* @param ref the reference to bind
@@ -918,7 +939,7 @@
/**
* Re-binds the specified Reference into JNDI at the specified address
- *
+ *
* @param context The JNDI Context to use
* @param address the address
* @param object the object to bind
@@ -938,7 +959,7 @@
/**
* Unbinds the specified address from JNDI
- *
+ *
* @param context The JNDI Context to use
* @param address
*/
@@ -960,9 +981,9 @@
}
/**
- * Returns whether the business interfaces and EJB2.x Home should be bound to
- * the same JNDI Name
- *
+ * Returns whether the business interfaces and EJB2.x Home should be bound to
+ * the same JNDI Name
+ *
* @param smd
* @param isLocal
* @return
@@ -1022,8 +1043,8 @@
/**
* Creates and returns a new RefAddr to flag the proper
* InvokerLocator URL used by remoting for the EJB represented
- * by the specified metadata
- *
+ * by the specified metadata
+ *
* @param clientBindUrl
* @return
*/
@@ -1040,11 +1061,11 @@
}
/**
- * Returns the name of the unique key under which a Proxy Factory will
+ * Returns the name of the unique key under which a Proxy Factory will
* be registered. Will follow form:
- *
+ *
* ProxyFactory/{ejbName}/{jndiName}
- *
+ *
* @param jndiName
* @param smd
* @param isLocal
@@ -1077,10 +1098,10 @@
}
/**
- * Makes a comma-delimited list of interfaces bound for setting the
- * Classname of the Reference. This will show up in JNDIView and make
+ * Makes a comma-delimited list of interfaces bound for setting the
+ * Classname of the Reference. This will show up in JNDIView and make
* it clear to application developers what will be castable from the lookup result
- *
+ *
* @param refAddrs
* @return
*/
@@ -1110,8 +1131,8 @@
}
/**
- * Returns whether the specified RefAddr type denotes an EJB Interface
- *
+ * Returns whether the specified RefAddr type denotes an EJB Interface
+ *
* @param refAddrType
* @return
*/
@@ -1124,8 +1145,8 @@
}
/**
- * Registers the specified proxy factory into the registry
- *
+ * Registers the specified proxy factory into the registry
+ *
* @param name The unique name for the ProxyFactory
* @param factory
* @param smd Metadata describing the EJB
@@ -1143,8 +1164,8 @@
{
/*
* Note on registry key collisions:
- *
- * Indicates that either the keys created are not unique or that we're attempting to redeploy
+ *
+ * Indicates that either the keys created are not unique or that we're attempting to redeploy
* an EJB that was not properly deregistered. Either way, this is a programmatic problem
* and not the fault of the bean provider/developer/deployer
*/
@@ -1154,9 +1175,111 @@
}
}
- /**
+ /**
+ * The remote proxy factory will be bound to the jndi at the key <code>proxyFactoryKey</code>.
+ *
+ * Internally this method creates a Remoting proxy for the remote proxyfactory, fronted by
+ * the {@link IsLocalProxyFactoryInterceptor} and the {@link InvokeRemoteInterceptor} interceptors
+ *
+ * @param context
+ * @param proxyFactoryKey
+ * @param remotingUrl
+ * @param proxyFactory
+ * @param cl
+ * @param smd
+ */
+ protected void bindRemoteProxyFactory(Context context, String proxyFactoryKey, String remotingUrl,
+ ProxyFactory proxyFactory, ClassLoader cl, JBossEnterpriseBeanMetaData smd)
+ {
+
+ ProxyFactory proxyToProxyFactory = this.createProxyToProxyFactory(proxyFactoryKey, remotingUrl, proxyFactory, cl, smd);
+ // now bind
+ try
+ {
+ log.debug("Binding remote ProxyFactory to JNDI, at key " + proxyFactoryKey);
+ Util.bind(context, proxyFactoryKey, proxyToProxyFactory);
+ }
+ catch (NamingException ne)
+ {
+ throw new RuntimeException("Could not bind remote proxy factory to JNDI, at key " + proxyFactoryKey, ne);
+ }
+
+ }
+
+ /**
+ * Creates a remoting {@link PojiProxy} for the proxy factory and fronts it with
+ * the {@link IsLocalProxyFactoryInterceptor} and {@link InvokeRemoteInterceptor} interceptors
+ *
+ * @param proxyFactoryKey
+ * @param remotingUrl
+ * @param proxyFactory
+ * @param cl
+ * @param smd
+ *
+ * @return
+ */
+ protected ProxyFactory createProxyToProxyFactory(String proxyFactoryKey, String remotingUrl,
+ ProxyFactory proxyFactory, ClassLoader cl, JBossEnterpriseBeanMetaData smd)
+ {
+ try
+ {
+ InvokerLocator locator = new InvokerLocator(remotingUrl);
+ // Create a POJI Proxy to the Registrar
+ Interceptor[] interceptors =
+ {IsLocalProxyFactoryInterceptor.singleton, InvokeRemoteInterceptor.singleton};
+ PojiProxy handler = new PojiProxy(proxyFactoryKey, locator, interceptors);
+ // The proxy should me marked as implementing interface(s) of type ProxyFactory
+ // and the other sub-interfaces of ProxyFactory (whichever applicable for this specific
+ // proxyfactory). We need the specific sub-interfaces to ensure that the ObjectFactories
+ // can invoke the APIs on the sub-interfaces
+ Class<ProxyFactory>[] proxyFactoryInterfaces = this.getAllProxyFactoryInterfaces((Class<ProxyFactory>)proxyFactory.getClass());
+
+ return (ProxyFactory) Proxy.newProxyInstance(proxyFactoryInterfaces[0].getClassLoader(), proxyFactoryInterfaces, handler);
+ }
+ catch (MalformedURLException mue)
+ {
+ throw new RuntimeException("Unable to create a remoting proxy for ProxyFactory " + proxyFactoryKey
+ + " with remoting url " + remotingUrl, mue);
+
+ }
+ }
+
+ /**
+ * Returns all the interfaces of type {@link ProxyFactory} that are implemented
+ * by the proxyFactory klass
+ *
+ * @param klass
+ * @return
+ */
+ protected Class<ProxyFactory>[] getAllProxyFactoryInterfaces(Class<ProxyFactory> klass)
+ {
+ Set<Class<ProxyFactory>> proxyFactoryInterfaces = new HashSet<Class<ProxyFactory>>();
+
+ // See if super class implements and ProxyFactory interface(s)
+ if (klass.getSuperclass() != null && ProxyFactory.class.isAssignableFrom(klass.getSuperclass()))
+ {
+ Class<ProxyFactory>[] intfs = getAllProxyFactoryInterfaces((Class<ProxyFactory>)(klass.getSuperclass()));
+ proxyFactoryInterfaces.addAll(Arrays.asList(intfs));
+
+ }
+ // Iterate through the directly implemented interfaces and
+ // check whether any ProxyFactory interface is being implemented
+ Class<?>[] allInterfaces = klass.getInterfaces();
+ for (Class<?> intf : allInterfaces)
+ {
+ if (ProxyFactory.class.isAssignableFrom(intf))
+ {
+ proxyFactoryInterfaces.add((Class<ProxyFactory>)intf);
+ }
+ }
+ return (Class<ProxyFactory>[]) proxyFactoryInterfaces.toArray(new Class<?>[proxyFactoryInterfaces.size()]);
+ }
+
+
+
+ /**
* Deregisters the proxy factory with the specified name from the registry
- *
+ *
* @param name
*/
protected void deregisterProxyFactory(String name)
@@ -1178,7 +1301,7 @@
// Deregister with AOP if registered
//TODO This should probably be in a cleaner location, ie.
// implement a callback for AOP Registration/Deregistration
- // that decouples JNDI Registration and abstracts whether
+ // that decouples JNDI Registration and abstracts whether
// a Proxy Factory is Remote or not
if (Dispatcher.singleton.isRegistered(name))
{
Modified: projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/objectfactory/ProxyObjectFactory.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/objectfactory/ProxyObjectFactory.java 2009-08-13 11:43:08 UTC (rev 92303)
+++ projects/ejb3/trunk/proxy-impl/src/main/java/org/jboss/ejb3/proxy/impl/objectfactory/ProxyObjectFactory.java 2009-08-13 12:17:45 UTC (rev 92304)
@@ -35,6 +35,8 @@
import javax.naming.Context;
import javax.naming.Name;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;
@@ -46,6 +48,7 @@
import org.jboss.ejb3.common.registrar.spi.Ejb3RegistrarLocator;
import org.jboss.ejb3.common.registrar.spi.NotBoundException;
import org.jboss.ejb3.proxy.impl.factory.ProxyFactory;
+import org.jboss.ejb3.proxy.impl.jndiregistrar.JndiSessionRegistrarBase;
import org.jboss.ejb3.proxy.impl.remoting.IsLocalProxyFactoryInterceptor;
import org.jboss.logging.Logger;
import org.jboss.remoting.InvokerLocator;
@@ -53,14 +56,12 @@
/**
* ProxyObjectFactory
*
- * Base upon which Proxy Object Factories may build. Defines
- * abstractions to:
- *
+ * Base upon which Proxy Object Factories may build. Defines abstractions to:
+ *
* <ul>
- * <li>Obtain a proxy based on metadata received
- * from Reference Address information associated with the bound
- * Reference</li>
- * <li>Use a pluggable ProxyFactoryRegistry</li>
+ * <li>Obtain a proxy based on metadata received from Reference Address
+ * information associated with the bound Reference</li>
+ * <li>Use a pluggable ProxyFactoryRegistry</li>
* </ul>
*
* @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
@@ -73,7 +74,7 @@
// --------------------------------------------------------------------------------||
private static final long serialVersionUID = 1L;
-
+
/**
* Logger
*/
@@ -85,11 +86,11 @@
/**
* Returns an appropriate Proxy based on the Reference Address information
- * associated with the Reference (obj) bound at name in the specified nameCtx with
- * specified environment.
- *
- * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
- * javax.naming.Name, javax.naming.Context, java.util.Hashtable)
+ * associated with the Reference (obj) bound at name in the specified nameCtx
+ * with specified environment.
+ *
+ * @see javax.naming.spi.ObjectFactory#getObjectInstance(java.lang.Object,
+ * javax.naming.Name, javax.naming.Context, java.util.Hashtable)
*/
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment)
throws Exception
@@ -131,7 +132,7 @@
{
try
{
- // Get local EJB3 Registrar
+ // Get local EJB3 Registrar
Ejb3Registrar registrar = Ejb3RegistrarLocator.locateRegistrar();
Object pfObj = registrar.lookup(proxyFactoryRegistryKey);
@@ -145,13 +146,13 @@
// in an inner try/catch; let it propagate to the outer catch.
catch (NotBoundException nbe)
{
- proxyFactory = createProxyFactoryProxy(name, refAddrs, proxyFactoryRegistryKey);
+ proxyFactory = this.getProxyFactoryFromJNDI(proxyFactoryRegistryKey, nameCtx, environment);
}
}
// Registrar is not local, so use Remoting to Obtain Proxy Factory
else
{
- proxyFactory = createProxyFactoryProxy(name, refAddrs, proxyFactoryRegistryKey);
+ proxyFactory = this.getProxyFactoryFromJNDI(proxyFactoryRegistryKey, nameCtx, environment);
}
// Get the proxy returned from the ProxyFactory
@@ -164,13 +165,23 @@
/**
* Creates a remoting proxy to the proxy factory.
- *
+ *
+ * Deprecated since https://jira.jboss.org/jira/browse/EJBTHREE-1884 - The
+ * {@link ProxyObjectFactory} is no longer responsible for creating a proxy
+ * to the {@link ProxyFactory}. Instead the {@link ProxyObjectFactory} will
+ * lookup in the JNDI for the {@link ProxyFactory} using the
+ * <code>proxyFactoryRegistryKey</code>. The responsibility of
+ * binding the proxyfactory to jndi will rest with the {@link JndiSessionRegistrarBase}
+ * and it's sub-implementations.
+ *
* @param name
* @param refAddrs
* @param proxyFactoryRegistryKey
* @return
* @throws Exception
+ *
*/
+ @Deprecated
protected ProxyFactory createProxyFactoryProxy(Name name, Map<String, List<String>> refAddrs,
String proxyFactoryRegistryKey) throws Exception
{
@@ -200,10 +211,44 @@
}
/**
- * Obtains the single value of the specified type as obtained from the specified reference
- * addresses bound at the specified Name. Asserts that the value exists and is the only one
- * for the specified type.
- *
+ * Returns the {@link ProxyFactory} from the JNDI.
+ *
+ * @param proxyFactoryKey
+ * The key to {@link ProxyFactory} in the JNDI
+ * @param context
+ * The JNDI context
+ * @param environment
+ * JNDI environment
+ * @return
+ */
+ protected ProxyFactory getProxyFactoryFromJNDI(String proxyFactoryKey, Context context, Hashtable<?, ?> environment)
+ {
+ try
+ {
+ Object factory = context.lookup(proxyFactoryKey);
+
+ assert factory instanceof ProxyFactory : "Unexpected object of type " + factory.getClass()
+ + " in JNDI, at key " + proxyFactoryKey + " Expected type " + ProxyFactory.class;
+
+ return (ProxyFactory) factory;
+ }
+ catch (NameNotFoundException nnfe)
+ {
+ throw new RuntimeException("Could not find proxyfactory in JNDI at " + proxyFactoryKey
+ + " -looking up local Proxy from Remote JVM?");
+ }
+ catch (NamingException e)
+ {
+ throw new RuntimeException("Exception while trying to locate proxy factory in JNDI, at key " + proxyFactoryKey);
+ }
+
+ }
+
+ /**
+ * Obtains the single value of the specified type as obtained from the
+ * specified reference addresses bound at the specified Name. Asserts that
+ * the value exists and is the only one for the specified type.
+ *
* @param name
* @param referenceAddresses
* @param refAddrType
@@ -222,10 +267,10 @@
}
/**
- * Obtains the single value of the specified type as obtained from the specified reference
- * addresses bound at the specified Name. Asserts that the value exists and is the only one
- * for the specified type.
- *
+ * Obtains the single value of the specified type as obtained from the
+ * specified reference addresses bound at the specified Name. Asserts that
+ * the value exists and is the only one for the specified type.
+ *
* @param name
* @param referenceAddresses
* @param refAddrType
@@ -250,9 +295,9 @@
/**
* Looks to the metadata specified by the reference addresses to determine if
- * an EJB3 Business View is defined here. Additionally checks that both local
+ * an EJB3 Business View is defined here. Additionally checks that both local
* and remote business interfaces are not bound to the same JNDI Address
- *
+ *
* @param name
* @param referenceAddresses
* @return
@@ -275,7 +320,7 @@
throw new RuntimeException(errorMessage);
}
- // Set
+ // Set
hasBusiness = hasLocalBusiness || hasRemoteBusiness;
// Return
@@ -284,11 +329,11 @@
}
/**
- * If the specified proxy has been defined outside of
- * this naming Context's ClassLoader, it must be reconstructed
- * using the TCL so we avoid CCE. This is especially vital using
- * a scope ClassLoader (ie. has defined by Servlet spec during Web Injection)
- *
+ * If the specified proxy has been defined outside of this naming Context's
+ * ClassLoader, it must be reconstructed using the TCL so we avoid CCE. This
+ * is especially vital using a scope ClassLoader (ie. has defined by Servlet
+ * spec during Web Injection)
+ *
* @param proxy
*/
protected Object redefineProxyInTcl(Object proxy)
@@ -362,7 +407,7 @@
/**
* Determines if the specified metadata contains a type of local business
- *
+ *
* @param referenceAddresses
* @return
*/
@@ -374,7 +419,7 @@
/**
* Determines if the specified metadata contains a type of remote business
- *
+ *
* @param referenceAddresses
* @return
*/
@@ -391,7 +436,9 @@
protected abstract Object getProxy(ProxyFactory proxyFactory, Name name, Map<String, List<String>> referenceAddresses);
/**
- * Obtains the type or supertype used by proxy factories for this Object Factory
+ * Obtains the type or supertype used by proxy factories for this Object
+ * Factory
+ *
* @return
*/
protected abstract Class<?> getProxyFactoryClass();
@@ -401,12 +448,13 @@
// --------------------------------------------------------------------------------||
/**
- * Underlying Enumeration for handling Reference Addresses is clumsy (though ordered properly);
- * iterate through and put in a useful form for this implementation
- *
+ * Underlying Enumeration for handling Reference Addresses is clumsy (though
+ * ordered properly); iterate through and put in a useful form for this
+ * implementation
+ *
* @param ref
* @return A Map consisting of keys holding reference types, and values of
- * Lists containing their contents
+ * Lists containing their contents
*/
private Map<String, List<String>> getReferenceAddresses(Reference ref)
{
Added: projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/ejbthree1884/unit/RemoteProxyFactoryJNDIBindingTestCase.java
===================================================================
--- projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/ejbthree1884/unit/RemoteProxyFactoryJNDIBindingTestCase.java (rev 0)
+++ projects/ejb3/trunk/proxy-impl/src/test/java/org/jboss/ejb3/test/proxy/impl/ejbthree1884/unit/RemoteProxyFactoryJNDIBindingTestCase.java 2009-08-13 12:17:45 UTC (rev 92304)
@@ -0,0 +1,334 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt 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.proxy.impl.ejbthree1884.unit;
+
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NameNotFoundException;
+
+import org.jboss.ejb3.common.registrar.spi.Ejb3RegistrarLocator;
+import org.jboss.ejb3.common.registrar.spi.NotBoundException;
+import org.jboss.ejb3.proxy.impl.factory.ProxyFactory;
+import org.jboss.ejb3.proxy.impl.factory.session.stateless.StatelessSessionRemoteProxyFactory;
+import org.jboss.ejb3.proxy.impl.jndiregistrar.JndiStatelessSessionRegistrar;
+import org.jboss.ejb3.test.proxy.impl.common.SessionTestCaseBase;
+import org.jboss.ejb3.test.proxy.impl.common.Utils;
+import org.jboss.ejb3.test.proxy.impl.common.container.SessionContainer;
+import org.jboss.ejb3.test.proxy.impl.common.container.StatefulContainer;
+import org.jboss.ejb3.test.proxy.impl.common.container.StatelessContainer;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.service.MyServiceBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.sfsb.MyStateful2xOnlyBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.sfsb.MyStateful2xOnlyWithBindingsBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.sfsb.MyStateful30OnlyBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.sfsb.MyStatefulLocalBusiness;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.sfsb.MyStatefulLocalOnlyBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.slsb.MyStateless2xOnlyWithBindingsBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.slsb.MyStateless30OnlyBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.slsb.MyStatelessBean;
+import org.jboss.ejb3.test.proxy.impl.common.ejb.slsb.MyStatelessBeanWithBindings;
+import org.jboss.logging.Logger;
+import org.jboss.metadata.ejb.jboss.JBossSessionBeanMetaData;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * RemoteProxyFactoryJNDIBindingTestCase
+ *
+ * Test case to ensure that the remote proxy factory of
+ * a bean is bound in JNDI
+ *
+ * @see https://jira.jboss.org/jira/browse/EJBTHREE-1884
+ * @author Jaikiran Pai
+ * @version $Revision: $
+ */
+public class RemoteProxyFactoryJNDIBindingTestCase extends SessionTestCaseBase
+{
+
+ /**
+ * Logger
+ */
+ private static Logger logger = Logger.getLogger(RemoteProxyFactoryJNDIBindingTestCase.class);
+
+ /**
+ * The {@link SessionContainer} which is instantiated by each test. Depending
+ * on the test, its either a {@link StatefulContainer} or a {@link StatelessContainer}
+ */
+ private SessionContainer sessionContainer;
+
+ @BeforeClass
+ public static void beforeClass() throws Throwable
+ {
+ SessionTestCaseBase.setUpBeforeClass();
+ bootstrap.deploy(SessionTestCaseBase.class);
+ }
+
+ @AfterClass
+ public static void afterClass() throws Throwable
+ {
+ if (bootstrap != null)
+ {
+ bootstrap.shutdown();
+ }
+ bootstrap = null;
+ }
+
+ /**
+ * This method takes care of any cleanup required after each test.
+ */
+ @After
+ public void cleanupAfterEachTest()
+ {
+ // There might be a case when while running the test, a bean was registered to JNDI
+ // but before it got unbound, the test failed (either a "Failure" or an "Error").
+ // In such cases, ensure that the bean is unbound from the JNDI, so that if the
+ // subsequent test tries to bind the same EJB again then it won't run into a
+ // name already bound error.
+ if (sessionContainer != null)
+ {
+ logger.info("Unbinding: " + sessionContainer.getName());
+ try
+ {
+ Ejb3RegistrarLocator.locateRegistrar().unbind(sessionContainer.getName());
+ }
+ catch (NotBoundException nbe)
+ {
+ // we are ok with this exception, which indicates that the test case had
+ // already unbound the ejb related bindings.
+ logger.debug(sessionContainer.getName() + " was already unbound");
+
+ }
+ }
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a EJB3 view SLSB
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForEJB3SLSBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStateless30OnlyBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a EJB2.x view SLSB
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForEJB2xSLSBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStateful2xOnlyBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a EJB3 view SFSB
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForEJB3SFSBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStateful30OnlyBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a EJB2.x view SFSB
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForEJB2xSFSBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStateful2xOnlyBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a Service bean
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForServiceBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyServiceBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a SLSB which exposes both EJB2.x and EJB3 view.
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForMixedSLSBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStatelessBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a bean which exposes EJB3 view with RemoteBindings
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForMixedBeanWithRemoteBindings() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStatelessBeanWithBindings.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a SFSB which exposes EJB2.x view with RemoteBindings
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForEJB2xSFSBWithRemoteBindings() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStateful2xOnlyWithBindingsBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is bound in the JNDI for
+ * a SLSB which exposes EJB2.x view with RemoteBindings
+ * @throws Throwable
+ */
+ @Test
+ public void testRemoteProxyFactoryForEJB2xSLSBWithRemoteBindings() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStateless2xOnlyWithBindingsBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ testRemoteProxyFactoryBinding(smd);
+
+ }
+
+ /**
+ * Tests that a remote proxyfactory is NOT bound in the JNDI for
+ * a bean which only exposes a local view
+ * @throws Throwable
+ */
+ @Test
+ public void testAbsenceOfRemoteProxyFactoryLocalOnlyBean() throws Throwable
+ {
+ this.sessionContainer = Utils.createSlsb(MyStatefulLocalOnlyBean.class);
+ JBossSessionBeanMetaData smd = this.sessionContainer.getMetaData();
+ // bind to JNDI
+ Ejb3RegistrarLocator.locateRegistrar().bind(sessionContainer.getName(), sessionContainer);
+ try
+ {
+ testRemoteProxyFactoryBinding(smd);
+ Assert.fail("Found a remote proxyfactory in JNDI for a local-only view bean");
+ }
+ catch (NameNotFoundException nnfe)
+ {
+ // expected, since the bean has only local view. So no remote proxyfactory
+ }
+ // Further lookup the local bean and invoke a method
+ Context ctx = new InitialContext();
+ String localJndiName = smd.getLocalJndiName();
+ logger.debug("Looking up local bean at " + localJndiName);
+ Object obj = ctx.lookup(localJndiName);
+
+ Assert.assertNotNull("Lookup of local bean at " + localJndiName + " returned null", obj);
+ Assert.assertTrue("Lookup at " + localJndiName + " returned unexpected object " + obj,
+ obj instanceof MyStatefulLocalBusiness);
+
+ MyStatefulLocalBusiness bean = (MyStatefulLocalBusiness) obj;
+ int counter = bean.getNextCounter();
+ logger.debug("Got counter " + counter);
+
+ Assert.assertEquals("Unexpected counter value = " + counter, counter, 0);
+
+ }
+
+ /**
+ * Helper method to construct the correct remote proxyfactory JNDI name
+ * and lookup the remote proxyfactory with that jndi name
+ * @param smd
+ * @throws Exception
+ */
+ private void testRemoteProxyFactoryBinding(JBossSessionBeanMetaData smd) throws Exception
+ {
+ // A bit of a hack. These are actually internal classes of proxy-impl,
+ // but since the proxyfactory jndi name generation is part of these
+ // classes, we hence have to rely on them.
+ JndiStatelessSessionRegistrar jndiRegistrar = new JndiStatelessSessionRegistrar(
+ StatelessSessionRemoteProxyFactory.class.getName());
+ String remoteProxyFactoryJNDIName = jndiRegistrar.getProxyFactoryRegistryKey(smd.getJndiName(), smd, false);
+
+ Assert.assertNotNull("Could not get remote proxyfactory jndi name from jndi registrar",
+ remoteProxyFactoryJNDIName);
+
+ Context ctx = new InitialContext();
+ logger.debug("Looking up remote proxy factory at " + remoteProxyFactoryJNDIName + " for EJB " + smd.getEjbName());
+ Object remoteProxyFactory = ctx.lookup(remoteProxyFactoryJNDIName);
+
+ Assert.assertNotNull("Null returned from JNDI for remote proxyfactory key " + remoteProxyFactoryJNDIName,
+ remoteProxyFactory);
+ Assert.assertTrue("Unexpected object type " + remoteProxyFactory.getClass() + " for JNDI name "
+ + remoteProxyFactoryJNDIName, remoteProxyFactory instanceof ProxyFactory);
+
+ }
+}
More information about the jboss-cvs-commits
mailing list