[seam-commits] Seam SVN: r11214 - in branches/community/Seam_2_2: examples and 4 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Thu Jun 25 16:25:20 EDT 2009


Author: dan.j.allen
Date: 2009-06-25 16:25:20 -0400 (Thu, 25 Jun 2009)
New Revision: 11214

Added:
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/AppleJuice.java
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/OrangeJuice.java
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/JuiceTestBar.java
Removed:
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceImpl.java
Modified:
   branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Guice.xml
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBar.java
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBarModule.java
   branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/GuiceTest.java
   branches/community/Seam_2_2/examples/guice/view/bar.xhtml
   branches/community/Seam_2_2/examples/readme.txt
   branches/community/Seam_2_2/src/ioc/org/jboss/seam/ioc/guice/GuiceInterceptor.java
Log:
JBSEAM-4245 - disinjection in the Guice interceptor
Thanks to Pawel Wrzeszcz


Modified: branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Guice.xml
===================================================================
--- branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Guice.xml	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/doc/Seam_Reference_Guide/en-US/Guice.xml	2009-06-25 20:25:20 UTC (rev 11214)
@@ -10,7 +10,7 @@
       resolution. The Guice integration (part of the Seam IoC module) allows use of Guice injection
       for all Seam components annotated with the <literal>@Guice</literal> annotation. In addition
       to the regular bijection that Seam performs (which becomes optional), Seam also delegates
-      to known Guice injectors to satisify the dependencies of the component. Guice may be useful to
+      to known Guice injectors to satisfy the dependencies of the component. Guice may be useful to
       tie non-Seam parts of large or legacy applications together with Seam. 
    </para> 
 
@@ -40,7 +40,7 @@
 
       <para>
           This Guice injection will happen on every method call, just like with bijection. Guice
-          injects based on type and binding. To satisify the dependencies in the previous example,
+          injects based on type and binding. To satisfy the dependencies in the previous example,
           you might have bound the following implementations in a Guice module, where
           <literal>@Special</literal> is an annotation you define in your application.
       </para>
@@ -70,7 +70,7 @@
 
       <para>
          You tell Seam which Guice injector to use by hooking it into the injection property
-         of the Guice initization component in the Seam component descriptor (components.xml):
+         of the Guice initialization component in the Seam component descriptor (components.xml):
       </para>
 
       <programlisting role="XML"><![CDATA[<components xmlns="http://jboss.com/products/seam/components"

Added: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/AppleJuice.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/AppleJuice.java	                        (rev 0)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/AppleJuice.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -0,0 +1,28 @@
+package org.jboss.seam.example.guice;
+
+/**
+ * @author Pawel Wrzeszcz (pwrzeszcz [at] jboss . org)
+ */
+public class AppleJuice implements Juice
+{
+   private static final String name = "Apple Juice";
+   private static final int price = 10;
+
+   public AppleJuice() {}
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public int getPrice()
+   {
+      return price;
+   }
+
+   @Override
+   public String toString()
+   {
+      return name;
+   }
+}
\ No newline at end of file

Modified: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBar.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBar.java	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBar.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -11,8 +11,8 @@
 @Guice // Activates @Inject on a Seam component
 public class JuiceBar
 {
-   @Inject private Juice juiceOfTheDay; // Guice looks at the variable type, not name
-   @Inject @Orange private Juice anotherJuice;
+   @Inject protected Juice juiceOfTheDay; // Guice looks at the variable type, not name
+   @Inject @Orange protected Juice anotherJuice;
 
    public Juice getJuiceOfTheDay()
    {

Modified: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBarModule.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBarModule.java	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceBarModule.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -2,6 +2,7 @@
 
 import com.google.inject.Module;
 import com.google.inject.Binder;
+import com.google.inject.Scopes;
 
 /**
  * @author Pawel Wrzeszcz (pwrzeszcz [at] jboss . org)
@@ -10,7 +11,8 @@
 {
    public void configure(Binder binder)
    {
-      binder.bind(Juice.class).toInstance(new JuiceImpl("Apple Juice", 10));
-      binder.bind(Juice.class).annotatedWith(Orange.class).toInstance(new JuiceImpl("Orange Juice", 12)); 
+      binder.bind(Juice.class).to(AppleJuice.class); // Create a new instance every time.
+       
+      binder.bind(Juice.class).annotatedWith(Orange.class).to(OrangeJuice.class).in(Scopes.SINGLETON);
    }
 }

Deleted: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceImpl.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceImpl.java	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/JuiceImpl.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -1,32 +0,0 @@
-package org.jboss.seam.example.guice;
-
-/**
- * @author Pawel Wrzeszcz (pwrzeszcz [at] jboss . org)
- */
-public class JuiceImpl implements Juice
-{
-   private String name;
-   private int price;
-
-   public JuiceImpl(String name, int price)
-   {
-      this.name = name;
-      this.price = price;
-   }
-
-    public String getName()
-   {
-      return name;
-   }
-
-   public int getPrice()
-   {
-      return price;
-   }
-
-   @Override
-   public String toString()
-   {
-      return name + " (" + price + " cents)";
-   }
-}

Added: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/OrangeJuice.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/OrangeJuice.java	                        (rev 0)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/OrangeJuice.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -0,0 +1,28 @@
+package org.jboss.seam.example.guice;
+
+/**
+ * @author Pawel Wrzeszcz (pwrzeszcz [at] jboss . org)
+ */
+public class OrangeJuice implements Juice
+{
+   private static final String name = "Orange Juice";
+   private static final int price = 12;
+
+   public OrangeJuice() {}
+
+   public String getName()
+   {
+      return name;
+   }
+
+   public int getPrice()
+   {
+      return price;
+   }
+
+   @Override
+   public String toString()
+   {
+      return name + " (" + price + " cents)";
+   }
+}

Modified: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/GuiceTest.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/GuiceTest.java	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/GuiceTest.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -1,33 +1,83 @@
 package org.jboss.seam.example.guice.test;
 
 import org.jboss.seam.example.guice.JuiceBar;
+import org.jboss.seam.example.guice.Juice;
+import org.jboss.seam.example.guice.AppleJuice;
+import org.jboss.seam.example.guice.Orange;
+import org.jboss.seam.example.guice.OrangeJuice;
 import org.jboss.seam.mock.SeamTest;
-import org.jboss.seam.ioc.guice.Injector;
 import org.testng.annotations.Test;
 
-import java.util.Arrays;
+import com.google.inject.Injector;
+import com.google.inject.Key;
 
 /**
  * @author Pawel Wrzeszcz (pwrzeszcz [at] jboss . org)
  */
 public class GuiceTest extends SeamTest
 {
-   private static final String[] expectedModules = { "org.jboss.seam.example.guice.JuiceBarModule" };
+   @Test
+   public void testGuiceInjector() throws Exception
+   {
+      new ComponentTest()
+      {
+         @Override
+         protected void testComponents() throws Exception
+         {
+            Injector injector = (Injector) getInstance("guiceExampleInjector");
 
+            Object juiceInstance = injector.getInstance(Juice.class);
+            assert juiceInstance instanceof AppleJuice : juiceInstance;
+
+            Object orangeInstance = injector.getInstance(Key.get(Juice.class, Orange.class));
+            assert orangeInstance instanceof OrangeJuice : orangeInstance;
+         }
+      }.run();
+   }
+
    @Test
-   public void testGuice()
+   public void testGuiceIntegration() throws Exception
    {
       new ComponentTest()
       {
+         @Override
          protected void testComponents() throws Exception
          {
-            Injector injector = (Injector) getValue("guiceExampleInjector");
-            assert Arrays.equals(expectedModules, injector.getModules());
+            JuiceBar juiceBar = (JuiceBar) getInstance("juiceBar");
 
-            JuiceBar juiceBar = (JuiceBar) getValue("juiceBar");
-            assert "Apple Juice".equals(juiceBar.getJuiceOfTheDay().getName());
-            assert "Orange Juice".equals(juiceBar.getAnotherJuice().getName());             
+            Juice juiceOfTheDay = juiceBar.getJuiceOfTheDay();
+            assert "Apple Juice".equals(juiceOfTheDay.getName()) : juiceOfTheDay.getName();
+            Juice anotherJuice = juiceBar.getAnotherJuice();
+            assert "Orange Juice".equals(anotherJuice.getName()) : anotherJuice.getName();
+
+            Juice juiceOfTheDay2 = juiceBar.getJuiceOfTheDay();
+            assert juiceOfTheDay != juiceOfTheDay2 : "A new instance should be created by Guice.";
+            Juice anotherJuice2 = juiceBar.getAnotherJuice();
+            assert anotherJuice == anotherJuice2 : "Different instances returned for the singleton object.";
          }
-      };
+      }.run();
    }
+
+   @Test
+   public void testGuiceDisinjection() throws Exception
+   {
+      new ComponentTest()
+      {
+         @Override
+         protected void testComponents() throws Exception
+         {
+            JuiceTestBar juiceBar = (JuiceTestBar) getInstance("juiceTestBar");
+            juiceBar.getJuiceOfTheDay(); // Call a method to trigger Guice injection
+
+            assert juiceBar.getJuiceOfTheDay() != null;
+            assert juiceBar.getAnotherJuice() != null;
+
+            // Reflection to obtain the field value would not work here due to the proxy
+            assert juiceBar.getJuiceOfTheDayBypassInterceptors() == null
+                        : "Value injected by Guice was not cleared after the call";
+            assert juiceBar.getAnotherJuiceBypassInterceptors() == null
+                        : "Value injected by Guice was not cleared after the call";         
+         }
+      }.run();
+   }
 }

Added: branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/JuiceTestBar.java
===================================================================
--- branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/JuiceTestBar.java	                        (rev 0)
+++ branches/community/Seam_2_2/examples/guice/src/org/jboss/seam/example/guice/test/JuiceTestBar.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -0,0 +1,29 @@
+package org.jboss.seam.example.guice.test;
+
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.intercept.BypassInterceptors;
+import org.jboss.seam.example.guice.JuiceBar;
+import org.jboss.seam.example.guice.Juice;
+import org.jboss.seam.ioc.guice.Guice;
+
+/**
+ * A component used by the disinjection test to obtain the values of the fields after the proxied call.
+ *
+ * @author Pawel Wrzeszcz (pawel . wrzeszcz [at] gmail . com)
+ */
+ at Name("juiceTestBar")
+ at Guice
+public class JuiceTestBar extends JuiceBar
+{
+   @BypassInterceptors
+   public Juice getJuiceOfTheDayBypassInterceptors()
+   {
+      return juiceOfTheDay;
+   }
+
+   @BypassInterceptors
+   public Juice getAnotherJuiceBypassInterceptors()
+   {
+      return anotherJuice;
+   }
+}

Modified: branches/community/Seam_2_2/examples/guice/view/bar.xhtml
===================================================================
--- branches/community/Seam_2_2/examples/guice/view/bar.xhtml	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/examples/guice/view/bar.xhtml	2009-06-25 20:25:20 UTC (rev 11214)
@@ -17,6 +17,7 @@
                 </ul>
                 <p><em>* Juice of the day</em></p>
             </div>
+            <p><small>This page is intentionally static (no form action).</small></p>
         </h:form>
     </body>
 </html>

Modified: branches/community/Seam_2_2/examples/readme.txt
===================================================================
--- branches/community/Seam_2_2/examples/readme.txt	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/examples/readme.txt	2009-06-25 20:25:20 UTC (rev 11214)
@@ -30,6 +30,8 @@
                       
 groovybooking/        The Seam Booking demo ported to Groovy.
 
+guice/                An example demonstrating the use of Google Guice with Seam.
+
 hibernate/            The Seam Booking demo ported to Hibernate3.
 
 icefaces/             The Seam Booking demo with ICEfaces, instead of 
@@ -109,7 +111,7 @@
 
 1. Download and unzip JBoss AS 4.2.3.GA from:
    
-   http://labs.jboss.com/jbossas/downloads
+   http://jboss.org/jbossas/downloads
 
 2. Make sure you have an up to date version of Seam: 
 

Modified: branches/community/Seam_2_2/src/ioc/org/jboss/seam/ioc/guice/GuiceInterceptor.java
===================================================================
--- branches/community/Seam_2_2/src/ioc/org/jboss/seam/ioc/guice/GuiceInterceptor.java	2009-06-25 16:11:02 UTC (rev 11213)
+++ branches/community/Seam_2_2/src/ioc/org/jboss/seam/ioc/guice/GuiceInterceptor.java	2009-06-25 20:25:20 UTC (rev 11214)
@@ -1,15 +1,25 @@
 package org.jboss.seam.ioc.guice;
 
 import org.jboss.seam.Component;
+import org.jboss.seam.contexts.Contexts;
+import org.jboss.seam.util.Reflections;
+import org.jboss.seam.util.Strings;
 import org.jboss.seam.annotations.intercept.AroundInvoke;
 import org.jboss.seam.annotations.intercept.Interceptor;
 import org.jboss.seam.core.Expressions;
 import org.jboss.seam.intercept.InvocationContext;
+import org.jboss.seam.intercept.AbstractInterceptor;
 import org.jboss.seam.log.Log;
 import org.jboss.seam.log.Logging;
 
 import com.google.inject.Injector;
+import com.google.inject.Inject;
 
+import java.lang.reflect.Field;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * Triggers Guice injection on a Seam component.
  *
@@ -17,33 +27,57 @@
  * @author Tomasz Szymanski (tszymanski [at] jboss.org)
  */
 @Interceptor
-public class GuiceInterceptor
+public class GuiceInterceptor extends AbstractInterceptor
 {
    private static final Log log = Logging.getLog(GuiceInterceptor.class);
 
    private static final long serialVersionUID = -6716553117162905303L;
 
+   private static final String GUICE_COMPONENT_FIELDS_MAP = "org.jboss.seam.GuiceComponentFieldsMap";
+
    private transient Injector defaultInjector = null;
 
    @AroundInvoke
    public Object aroundInvoke(InvocationContext invocationContext) throws Exception
    {
-      final Injector injector = getInjectorForClass(invocationContext.getMethod().getDeclaringClass());
+      inject(invocationContext.getTarget());
 
+      Object result = invocationContext.proceed();
+
+      disinject(invocationContext.getTarget());
+
+      return result;
+   }
+
+   private void inject(Object target)
+   {
       if (log.isTraceEnabled())
       {
-         log.trace("Injecting members of: #0", invocationContext.getTarget().getClass().getName());
+         log.trace("Injecting members of component '#0'", getComponent().getName());
       }
 
-      injector.injectMembers(invocationContext.getTarget());
+      getGuiceInjector().injectMembers(target);
+    }
 
-      return invocationContext.proceed();
+   private void disinject(Object target) throws Exception
+   {
+      for (Field guiceField : getGuiceAnnotatedFields())
+      {
+         if (!guiceField.isAccessible())
+         {
+            guiceField.setAccessible(true);
+         }
+         Reflections.set(guiceField, target, null);
+      }
    }
 
-   private Injector getInjectorForClass(final Class<?> declaringClass)
+   /**
+    * @return a Guice injector for the current component
+    */
+   private Injector getGuiceInjector()
    {
       final String expr;
-      Guice guice = declaringClass.getAnnotation(Guice.class);
+      Guice guice = getComponent().getBeanClass().getAnnotation(Guice.class);
       if (guice != null) {
          expr = guice.value();
       }
@@ -52,8 +86,8 @@
       }
 
       // Optimize lookups for default injector
-      return (expr != null && expr.length() > 0)
-         ? getInjectorByName(expr) : getCachedDefaultInjector();
+      return Strings.isEmpty(expr)
+         ? getCachedDefaultInjector() : getInjectorByName(expr);
    }
 
    private Injector getCachedDefaultInjector()
@@ -76,7 +110,7 @@
       return defaultInjector;
    }
 
-   public static Injector getInjectorByName(final String expr)
+   private static Injector getInjectorByName(final String expr)
    {
       Object result;
 
@@ -96,4 +130,37 @@
 
       return (Injector) result;
    }
+
+   /**
+    * @return a collection of all component fields injected by Guice (annotated with the @Inject annotation)
+    */
+   private Collection<Field> getGuiceAnnotatedFields()
+   {
+      final Map<Class,Collection<Field>> fieldsMap = getGuiceComponentFieldsMap();
+      Collection<Field> annotatedFields = fieldsMap.get(getComponent().getBeanClass());
+      if (annotatedFields == null)
+      {
+         annotatedFields = Reflections.getFields(getComponent().getBeanClass(), Inject.class);
+         fieldsMap.put(getComponent().getBeanClass(), annotatedFields);
+      }
+      return annotatedFields;
+   }
+
+   /**
+    * @return a cache that stores fields annotated with the @Inject annotation for the Guice component classes
+    */
+   @SuppressWarnings("unchecked")
+   private Map<Class,Collection<Field>> getGuiceComponentFieldsMap()
+   {
+      if (Contexts.getApplicationContext().get(GUICE_COMPONENT_FIELDS_MAP) == null)
+      {
+         Contexts.getApplicationContext().set(GUICE_COMPONENT_FIELDS_MAP, new HashMap<Class, Collection<Field>>());
+      }
+      return (Map<Class, Collection<Field>>) Contexts.getApplicationContext().get(GUICE_COMPONENT_FIELDS_MAP);
+   }
+
+   public boolean isInterceptorEnabled()
+   {
+      return true;
+   }
 }




More information about the seam-commits mailing list