[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