[webbeans-commits] Webbeans SVN: r907 - in ri/trunk: webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy and 2 other directories.

webbeans-commits at lists.jboss.org webbeans-commits at lists.jboss.org
Mon Jan 12 15:01:29 EST 2009


Author: pete.muir at jboss.org
Date: 2009-01-12 15:01:29 -0500 (Mon, 12 Jan 2009)
New Revision: 907

Added:
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/ForwardingEjbDescriptor.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/InternalEjbDescriptor.java
Modified:
   ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/ejb/spi/EjbDescriptor.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/EnterpriseBean.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/SimpleBean.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/ClientProxyMethodHandler.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/EnterpriseBeanProxyMethodHandler.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/EjbDescriptorCache.java
Log:
WBRI-68, no tests :-(

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/EnterpriseBean.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/EnterpriseBean.java	2009-01-12 17:43:26 UTC (rev 906)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/EnterpriseBean.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -18,9 +18,13 @@
 package org.jboss.webbeans.bean;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Type;
 import java.util.HashSet;
 import java.util.Set;
 
+import javassist.util.proxy.ProxyFactory;
+import javassist.util.proxy.ProxyObject;
+
 import javax.webbeans.ApplicationScoped;
 import javax.webbeans.CreationException;
 import javax.webbeans.Decorator;
@@ -35,8 +39,10 @@
 import javax.webbeans.Specializes;
 
 import org.jboss.webbeans.ManagerImpl;
+import org.jboss.webbeans.bean.proxy.EnterpriseBeanProxyMethodHandler;
 import org.jboss.webbeans.context.DependentContext;
-import org.jboss.webbeans.ejb.spi.EjbDescriptor;
+import org.jboss.webbeans.ejb.InternalEjbDescriptor;
+import org.jboss.webbeans.ejb.spi.BusinessInterfaceDescriptor;
 import org.jboss.webbeans.introspector.AnnotatedClass;
 import org.jboss.webbeans.introspector.AnnotatedField;
 import org.jboss.webbeans.introspector.AnnotatedMethod;
@@ -44,6 +50,7 @@
 import org.jboss.webbeans.introspector.jlr.AnnotatedClassImpl;
 import org.jboss.webbeans.log.LogProvider;
 import org.jboss.webbeans.log.Logging;
+import org.jboss.webbeans.util.Proxies;
 
 /**
  * An enterprise bean representation
@@ -57,7 +64,9 @@
    private LogProvider log = Logging.getLogProvider(EnterpriseBean.class);
 
    // The EJB descriptor
-   private EjbDescriptor<T> ejbDescriptor;
+   private InternalEjbDescriptor<T> ejbDescriptor;
+   
+   private Class<T> proxyClass;
 
    // The remove method on the bean class (do not call!)
    private AnnotatedMethod<?> removeMethod;
@@ -99,12 +108,12 @@
    protected void init()
    {
       super.init();
-      Iterable<EjbDescriptor<T>> ejbDescriptors = manager.getEjbDescriptorCache().get(getType());
+      Iterable<InternalEjbDescriptor<T>> ejbDescriptors = manager.getEjbDescriptorCache().get(getType());
       if (ejbDescriptors == null)
       {
          throw new DefinitionException("Not an EJB " + toString());
       }
-      for (EjbDescriptor<T> ejbDescriptor : ejbDescriptors)
+      for (InternalEjbDescriptor<T> ejbDescriptor : ejbDescriptors)
       {
          if (this.ejbDescriptor == null)
          {
@@ -115,6 +124,8 @@
             throw new RuntimeException("TODO Multiple EJBs have the same bean class! " + getType());
          }
       }
+      initTypesFromLocalInterfaces();
+      initProxyClass();
       initRemoveMethod();
       initInjectionPoints();
       checkEnterpriseBeanTypeAllowed();
@@ -139,6 +150,32 @@
          }
       }
    }
+   
+   protected void initTypes()
+   {
+      // Noop, occurs too early
+      // TODO points at class hierachy problem :-(
+   }
+   
+   protected void initTypesFromLocalInterfaces()
+   {
+      types = new HashSet<Type>();
+      for (BusinessInterfaceDescriptor<?> businessInterfaceDescriptor : ejbDescriptor.getLocalBusinessInterfaces())
+      {
+         types.add(businessInterfaceDescriptor.getInterface());
+      }
+      types.add(Object.class);
+   }
+   
+   protected void initProxyClass()
+   {
+      ProxyFactory proxyFactory = Proxies.getProxyFactory(getTypes());
+      
+      @SuppressWarnings("unchecked")
+      Class<T> proxyClass = proxyFactory.createClass();
+      
+      this.proxyClass = proxyClass;
+   }
 
    /**
     * Validates for non-conflicting roles
@@ -275,13 +312,21 @@
       try
       {
          DependentContext.INSTANCE.setActive(true);
-         // TODO Implement enterprise bean proxies and select the correct
-         // jndiName
-         return (T) manager.getNaming().lookup(ejbDescriptor.getLocalJndiName(), getType());
+         T instance = proxyClass.newInstance();
+         ((ProxyObject) instance).setHandler(new EnterpriseBeanProxyMethodHandler(this)); 
+         return instance;
       }
+      catch (InstantiationException e)
+      {
+         throw new RuntimeException("Could not instantiate enterprise proxy for " + toString(), e);
+      }
+      catch (IllegalAccessException e)
+      {
+         throw new RuntimeException("Could not access bean correctly when creating enterprise proxy for " + toString(), e);
+      }
       catch (Exception e)
       {
-         throw new CreationException("could not find the name in JNDI " + ejbDescriptor.getLocalJndiName(), e);
+         throw new CreationException("could not find the EJB in JNDI " + proxyClass, e);
       }
       finally
       {
@@ -448,7 +493,7 @@
       return injectionPointsAreSerializable();
    }
 
-   public EjbDescriptor<T> getEjbDescriptor()
+   public InternalEjbDescriptor<T> getEjbDescriptor()
    {
       return ejbDescriptor;
    }

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/SimpleBean.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/SimpleBean.java	2009-01-12 17:43:26 UTC (rev 906)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/SimpleBean.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -34,8 +34,8 @@
 import org.jboss.webbeans.ManagerImpl;
 import org.jboss.webbeans.MetaDataCache;
 import org.jboss.webbeans.context.DependentContext;
+import org.jboss.webbeans.injection.InjectionPointImpl;
 import org.jboss.webbeans.injection.InjectionPointProvider;
-import org.jboss.webbeans.injection.InjectionPointImpl;
 import org.jboss.webbeans.introspector.AnnotatedClass;
 import org.jboss.webbeans.introspector.AnnotatedConstructor;
 import org.jboss.webbeans.introspector.AnnotatedField;
@@ -418,6 +418,15 @@
          return;
       }
    }
+   
+   /**
+    * Initializes the bean type
+    */
+   protected void initType()
+   {
+      log.trace("Bean type specified in Java");
+      this.type = getAnnotatedItem().getType();
+   }
 
    /**
     * Returns the constructor

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/ClientProxyMethodHandler.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/ClientProxyMethodHandler.java	2009-01-12 17:43:26 UTC (rev 906)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/ClientProxyMethodHandler.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -63,15 +63,23 @@
    }
 
    /**
-    * The method proxy
+    * Invokes the method on the correct version of the instance as obtained by
+    * a context lookup
     * 
-    * Uses reflection to look up the corresponding method on the proxy and
-    * executes that method with the same parameters.
-    * 
-    * @param self A reference to the proxy
-    * @param proxiedMethod The method to execute
-    * @param proceed The next method to proceed to
-    * @param args The method calling arguments
+    * @param self          the proxy instance.
+    * @param thisMethod    the overridden method declared in the super
+    *                      class or interface.
+    * @param proceed       the forwarder method for invoking the overridden 
+    *                      method.  It is null if the overridden mehtod is
+    *                      abstract or declared in the interface.
+    * @param args          an array of objects containing the values of
+    *                      the arguments passed in the method invocation
+    *                      on the proxy instance.  If a parameter type is
+    *                      a primitive type, the type of the array element
+    *                      is a wrapper class.
+    * @return              the resulting value of the method invocation.
+    *
+    * @throws Throwable    if the method invocation fails.
     */
    public Object invoke(Object self, Method proxiedMethod, Method proceed, Object[] args) throws Throwable
    {

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/EnterpriseBeanProxyMethodHandler.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/EnterpriseBeanProxyMethodHandler.java	2009-01-12 17:43:26 UTC (rev 906)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bean/proxy/EnterpriseBeanProxyMethodHandler.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -18,9 +18,13 @@
 package org.jboss.webbeans.bean.proxy;
 
 import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
 
 import javassist.util.proxy.MethodHandler;
 
+import org.jboss.webbeans.CurrentManager;
+import org.jboss.webbeans.bean.EnterpriseBean;
 import org.jboss.webbeans.log.LogProvider;
 import org.jboss.webbeans.log.Logging;
 import org.jboss.webbeans.util.Reflections;
@@ -29,42 +33,65 @@
  * Method handler for enterprise bean client proxies
  * 
  * @author Nicklas Karlsson
+ * @author Pete Muir
  *
  */
 public class EnterpriseBeanProxyMethodHandler implements MethodHandler
 {
    // The log provider
-   private LogProvider log = Logging.getLogProvider(EnterpriseBeanProxyMethodHandler.class);
+   private static final transient LogProvider log = Logging.getLogProvider(EnterpriseBeanProxyMethodHandler.class);
+
    // The container provided proxy that implements all interfaces
-   private Object proxy;
+   private final Map<Class<?>, Object> proxiedInstances;
+   private final Map<Class<?>, String> jndiNames;
 
    /**
     * Constructor
     * 
     * @param proxy The generic proxy
     */
-   public EnterpriseBeanProxyMethodHandler(Object proxy)
+   public EnterpriseBeanProxyMethodHandler(EnterpriseBean<?> bean)
    {
-      this.proxy = proxy;
-      log.trace("Created enterprise bean proxy method handler for " + proxy);
+      this.proxiedInstances = new HashMap<Class<?>, Object>();
+      this.jndiNames = bean.getEjbDescriptor().getLocalBusinessInterfacesJndiNames();
+      log.trace("Created enterprise bean proxy method handler for " + bean);
    }
 
    /**
-    * The method proxy
+    * Lookups the EJB in the container and executes the method on it
     * 
-    * Executes the corresponding method on the proxy
-    * 
-    * @param self A reference to the proxy
-    * @param method The method to execute
-    * @param process The next method to proceed to
-    * @param args The method calling arguments
+    * @param self          the proxy instance.
+    * @param method        the overridden method declared in the super
+    *                      class or interface.
+    * @param proceed       the forwarder method for invoking the overridden 
+    *                      method.  It is null if the overridden method is
+    *                      abstract or declared in the interface.
+    * @param args          an array of objects containing the values of
+    *                      the arguments passed in the method invocation
+    *                      on the proxy instance.  If a parameter type is
+    *                      a primitive type, the type of the array element
+    *                      is a wrapper class.
+    * @return              the resulting value of the method invocation.
+    *
+    * @throws Throwable    if the method invocation fails.
     */
-   //@Override
    public Object invoke(Object self, Method method, Method proceed, Object[] args) throws Throwable
    {
-      Method proxiedMethod = Reflections.lookupMethod(method, proxy);
-      Object returnValue = Reflections.invokeAndWrap(proxiedMethod, proxy, args);
-      log.trace("Executed " + method + " on " + proxy + " with parameters " + args + " and got return value " + returnValue);
+      Class<?> businessInterface = method.getDeclaringClass();
+      Object proxiedInstance = proxiedInstances.get(businessInterface);
+      if (proxiedInstance == null)
+      {
+         String jndiName = jndiNames.get(businessInterface);
+         if (jndiName == null)
+         {
+            throw new IllegalStateException("Unable to establish jndi name to use to lookup EJB");
+         }
+         proxiedInstance = CurrentManager.rootManager().getNaming().lookup(jndiName, businessInterface);
+         proxiedInstances.put(businessInterface, proxiedInstance);
+      }
+      Method proxiedMethod = Reflections.lookupMethod(method, proxiedInstance);
+      Object returnValue = Reflections.invokeAndWrap(proxiedMethod, proxiedInstance, args);
+      log.trace("Executed " + method + " on " + proxiedInstance + " with parameters " + args + " and got return value " + returnValue);
       return returnValue;
    }
 

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/EjbDescriptorCache.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/EjbDescriptorCache.java	2009-01-12 17:43:26 UTC (rev 906)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/EjbDescriptorCache.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -36,17 +36,17 @@
    private static final long serialVersionUID = 1L;
 
    // EJB name -> EJB descriptor map
-   private ConcurrentMap<String, EjbDescriptor<?>> ejbsByName;
+   private ConcurrentMap<String, InternalEjbDescriptor<?>> ejbsByName;
    // EJB implementation class -> EJB descriptors map
-   private ConcurrentMap<Class<?>, Set<EjbDescriptor<?>>> ejbsByBeanClass;
+   private ConcurrentMap<Class<?>, Set<InternalEjbDescriptor<?>>> ejbsByBeanClass;
 
    /**
     * Constructor
     */
    public EjbDescriptorCache()
    {
-      this.ejbsByName = new ConcurrentHashMap<String, EjbDescriptor<?>>();
-      this.ejbsByBeanClass = new ConcurrentHashMap<Class<?>, Set<EjbDescriptor<?>>>();
+      this.ejbsByName = new ConcurrentHashMap<String, InternalEjbDescriptor<?>>();
+      this.ejbsByBeanClass = new ConcurrentHashMap<Class<?>, Set<InternalEjbDescriptor<?>>>();
    }
 
    /**
@@ -55,7 +55,7 @@
     * @param ejbName The EJB name
     * @return The EJB descriptor
     */
-   public EjbDescriptor<?> get(String ejbName)
+   public InternalEjbDescriptor<?> get(String ejbName)
    {
       return ejbsByName.get(ejbName);
    }
@@ -67,7 +67,7 @@
     * @return An iterator
     */
    @SuppressWarnings("unchecked")
-   public <T> Iterable<EjbDescriptor<T>> get(Class<T> beanClass)
+   public <T> Iterable<InternalEjbDescriptor<T>> get(Class<T> beanClass)
    {
       return (Iterable) ejbsByBeanClass.get(beanClass);
    }
@@ -77,11 +77,12 @@
     * 
     * @param ejbDescriptor The EJB descriptor to add
     */
-   public void add(EjbDescriptor<?> ejbDescriptor)
+   public <T> void add(EjbDescriptor<T> ejbDescriptor)
    {
-      ejbsByName.put(ejbDescriptor.getEjbName(), ejbDescriptor);
-      ejbsByBeanClass.putIfAbsent(ejbDescriptor.getType(), new CopyOnWriteArraySet<EjbDescriptor<?>>());
-      ejbsByBeanClass.get(ejbDescriptor.getType()).add(ejbDescriptor);
+      InternalEjbDescriptor<T> internalEjbDescriptor = new InternalEjbDescriptor<T>(ejbDescriptor);
+      ejbsByName.put(ejbDescriptor.getEjbName(), internalEjbDescriptor);
+      ejbsByBeanClass.putIfAbsent(ejbDescriptor.getType(), new CopyOnWriteArraySet<InternalEjbDescriptor<?>>());
+      ejbsByBeanClass.get(ejbDescriptor.getType()).add(internalEjbDescriptor);
    }
 
    /**

Added: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/ForwardingEjbDescriptor.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/ForwardingEjbDescriptor.java	                        (rev 0)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/ForwardingEjbDescriptor.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -0,0 +1,58 @@
+package org.jboss.webbeans.ejb;
+
+import java.lang.reflect.Method;
+
+import org.jboss.webbeans.ejb.spi.BusinessInterfaceDescriptor;
+import org.jboss.webbeans.ejb.spi.EjbDescriptor;
+
+public abstract class ForwardingEjbDescriptor<T> implements EjbDescriptor<T>
+{
+   
+   protected abstract EjbDescriptor<T> delegate();
+   
+   public String getEjbName()
+   {
+      return delegate().getEjbName();
+   }
+   
+   public Iterable<BusinessInterfaceDescriptor<?>> getLocalBusinessInterfaces()
+   {
+      return delegate().getLocalBusinessInterfaces();
+   }
+   
+   public Iterable<BusinessInterfaceDescriptor<?>> getRemoteBusinessInterfaces()
+   {
+      return delegate().getRemoteBusinessInterfaces();
+   }
+   
+   public Iterable<Method> getRemoveMethods()
+   {
+      return delegate().getRemoveMethods();
+   }
+   
+   public Class<T> getType()
+   {
+      return delegate().getType();
+   }
+   
+   public boolean isMessageDriven()
+   {
+      return delegate().isMessageDriven();
+   }
+   
+   public boolean isSingleton()
+   {
+      return delegate().isSingleton();
+   }
+   
+   public boolean isStateful()
+   {
+      return delegate().isStateful();
+   }
+   
+   public boolean isStateless()
+   {
+      return delegate().isStateless();
+   }
+   
+}


Property changes on: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/ForwardingEjbDescriptor.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Added: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/InternalEjbDescriptor.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/InternalEjbDescriptor.java	                        (rev 0)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/InternalEjbDescriptor.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -0,0 +1,41 @@
+package org.jboss.webbeans.ejb;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.webbeans.ejb.spi.BusinessInterfaceDescriptor;
+import org.jboss.webbeans.ejb.spi.EjbDescriptor;
+
+public class InternalEjbDescriptor<T> extends ForwardingEjbDescriptor<T> implements EjbDescriptor<T>
+{
+ 
+   private final Map<Class<?>, String> localBusinessInterfacesJndiNames;
+   private final EjbDescriptor<T> delegate;
+   
+   public InternalEjbDescriptor(EjbDescriptor<T> ejbDescriptor)
+   {
+      this.delegate = ejbDescriptor;
+      this.localBusinessInterfacesJndiNames = new HashMap<Class<?>, String>();
+      for (BusinessInterfaceDescriptor<?> businessInterfaceDescriptor : ejbDescriptor.getLocalBusinessInterfaces())
+      {
+         localBusinessInterfacesJndiNames.put(businessInterfaceDescriptor.getInterface(), businessInterfaceDescriptor.getJndiName());
+      }
+      // Internally, Object.class is added to the type hierachy of an 
+      // EnterpriseBean, so we need to represent that here. We can just use any
+      // of the local business interfaces
+      localBusinessInterfacesJndiNames.put(Object.class, ejbDescriptor.getLocalBusinessInterfaces().iterator().next().getJndiName());
+   }
+   
+   public Map<Class<?>, String> getLocalBusinessInterfacesJndiNames()
+   {
+      return Collections.unmodifiableMap(localBusinessInterfacesJndiNames);
+   }
+   
+   @Override
+   protected EjbDescriptor<T> delegate()
+   {
+      return delegate;
+   }
+   
+}


Property changes on: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ejb/InternalEjbDescriptor.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/ejb/spi/EjbDescriptor.java
===================================================================
--- ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/ejb/spi/EjbDescriptor.java	2009-01-12 17:43:26 UTC (rev 906)
+++ ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/ejb/spi/EjbDescriptor.java	2009-01-12 20:01:29 UTC (rev 907)
@@ -93,11 +93,4 @@
     */
    public String getEjbName();
    
-   /**
-    * @return The JNDI string which can be used to lookup a proxy which 
-    * implements all local business interfaces 
-    * 
-    */
-   public String getLocalJndiName();
-   
 }




More information about the weld-commits mailing list