You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by iv...@apache.org on 2010/03/17 00:30:35 UTC

svn commit: r924049 - in /wicket/trunk/wicket-guice/src: main/java/org/apache/wicket/guice/ test/java/org/apache/wicket/guice/

Author: ivaynberg
Date: Tue Mar 16 23:30:35 2010
New Revision: 924049

URL: http://svn.apache.org/viewvc?rev=924049&view=rev
Log:
WICKET-2761 InjectorHolder.getInjector().inject(this) doesn't work with wicket-guice

Added:
    wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java   (with props)
    wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestNoComponent.java   (with props)
Removed:
    wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/InjectionFlagCachingGuiceComponentInjector.java
Modified:
    wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceComponentInjector.java
    wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceProxyTargetLocator.java
    wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java
    wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponent.java

Modified: wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceComponentInjector.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceComponentInjector.java?rev=924049&r1=924048&r2=924049&view=diff
==============================================================================
--- wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceComponentInjector.java (original)
+++ wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceComponentInjector.java Tue Mar 16 23:30:35 2010
@@ -16,30 +16,19 @@
  */
 package org.apache.wicket.guice;
 
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
-import java.lang.reflect.Type;
-
 import org.apache.wicket.Application;
 import org.apache.wicket.Component;
-import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.application.IComponentInstantiationListener;
-import org.apache.wicket.proxy.LazyInitProxyFactory;
+import org.apache.wicket.injection.IFieldValueFactory;
 
-import com.google.inject.BindingAnnotation;
 import com.google.inject.Guice;
 import com.google.inject.ImplementedBy;
-import com.google.inject.Inject;
 import com.google.inject.Injector;
 import com.google.inject.Module;
 import com.google.inject.Stage;
 
 /**
- * Injects fields/members of components using Guice.
+ * Injects field members of components using Guice.
  * <p>
  * Add this to your application in its {@link Application#init()} method like so:
  * 
@@ -53,8 +42,12 @@ import com.google.inject.Stage;
  * 
  * @author Alastair Maw
  */
-public class GuiceComponentInjector implements IComponentInstantiationListener
+public class GuiceComponentInjector extends org.apache.wicket.injection.Injector
+		implements
+			IComponentInstantiationListener
 {
+	private final IFieldValueFactory fieldValueFactory;
+
 	/**
 	 * Creates a new Wicket GuiceComponentInjector instance.
 	 * <p>
@@ -81,7 +74,15 @@ public class GuiceComponentInjector impl
 	{
 		this(app, Guice.createInjector(app.getConfigurationType().equals(Application.DEVELOPMENT)
 				? Stage.DEVELOPMENT
-				: Stage.PRODUCTION, modules));
+				: Stage.PRODUCTION, modules), true);
+	}
+
+	/**
+	 * @see GuiceComponentInjector(Application app, Injector injector, boolean wrapInProxies)
+	 */
+	public GuiceComponentInjector(Application app, Injector injector)
+	{
+		this(app, injector, true);
 	}
 
 	/**
@@ -90,139 +91,25 @@ public class GuiceComponentInjector impl
 	 * 
 	 * @param app
 	 * @param injector
+	 * @param wrapInProxies
+	 *            whether or not wicket should wrap dependencies with specialized proxies that can
+	 *            be safely serialized. in most cases this should be set to true.
 	 */
-	public GuiceComponentInjector(Application app, Injector injector)
+	public GuiceComponentInjector(Application app, Injector injector, final boolean wrapInProxies)
 	{
 		app.setMetaData(GuiceInjectorHolder.INJECTOR_KEY, new GuiceInjectorHolder(injector));
+		fieldValueFactory = new GuiceFieldValueFactory(wrapInProxies);
+		bind(app);
 	}
 
+	@Override
 	public void inject(Object object)
 	{
-		Class< ? > current = object.getClass();
-		do
-		{
-			Field[] currentFields = current.getDeclaredFields();
-			for (final Field field : currentFields)
-			{
-				Inject injectAnnotation = field.getAnnotation(Inject.class);
-				if (!Modifier.isStatic(field.getModifiers()) && injectAnnotation != null)
-				{
-					try
-					{
-						Annotation bindingAnnotation = findBindingAnnotation(field.getAnnotations());
-						Object proxy = LazyInitProxyFactory.createProxy(field.getType(),
-								new GuiceProxyTargetLocator(field, bindingAnnotation,
-										injectAnnotation.optional()));
-
-						if (!field.isAccessible())
-						{
-							field.setAccessible(true);
-						}
-						field.set(object, proxy);
-					}
-					catch (IllegalAccessException e)
-					{
-						throw new WicketRuntimeException("Error Guice-injecting field " +
-								field.getName() + " in " + object, e);
-					}
-					catch (MoreThanOneBindingException e)
-					{
-						throw new RuntimeException(
-								"Can't have more than one BindingAnnotation on field " +
-										field.getName() + " of class " +
-										object.getClass().getName());
-					}
-				}
-			}
-			Method[] currentMethods = current.getDeclaredMethods();
-			for (final Method method : currentMethods)
-			{
-				Inject injectAnnotation = method.getAnnotation(Inject.class);
-				if (!Modifier.isStatic(method.getModifiers()) && injectAnnotation != null)
-				{
-					Annotation[][] paramAnnotations = method.getParameterAnnotations();
-					Class< ? >[] paramTypes = method.getParameterTypes();
-					Type[] genericParamTypes = method.getGenericParameterTypes();
-					Object[] args = new Object[paramTypes.length];
-					for (int i = 0; i < paramTypes.length; i++)
-					{
-						Type paramType;
-						if (genericParamTypes[i] instanceof ParameterizedType)
-						{
-							paramType = ((ParameterizedType)genericParamTypes[i]).getRawType();
-						}
-						else
-						{
-							paramType = paramTypes[i];
-						}
-						try
-						{
-							Annotation bindingAnnotation = findBindingAnnotation(paramAnnotations[i]);
-							args[i] = LazyInitProxyFactory.createProxy(paramTypes[i],
-									new GuiceProxyTargetLocator(method, i, bindingAnnotation,
-											injectAnnotation.optional()));
-						}
-						catch (MoreThanOneBindingException e)
-						{
-							throw new RuntimeException(
-									"Can't have more than one BindingAnnotation on parameter " + i +
-											"(" + paramType + ") of method " + method.getName() +
-											" of class " + object.getClass().getName());
-						}
-					}
-					try
-					{
-						method.invoke(object, args);
-					}
-					catch (IllegalAccessException e)
-					{
-						throw new WicketRuntimeException(e);
-					}
-					catch (InvocationTargetException e)
-					{
-						throw new WicketRuntimeException(e);
-					}
-				}
-			}
-			current = current.getSuperclass();
-		}
-		// Do a null check in case Object isn't in the current classloader.
-		while (current != null && current != Object.class);
+		inject(object, fieldValueFactory);
 	}
 
 	public void onInstantiation(Component component)
 	{
 		inject(component);
 	}
-
-	/**
-	 * 
-	 * @param annotations
-	 * @return
-	 * @throws MoreThanOneBindingException
-	 */
-	public static Annotation findBindingAnnotation(final Annotation[] annotations)
-			throws MoreThanOneBindingException
-	{
-		Annotation bindingAnnotation = null;
-
-		// Work out if we have a BindingAnnotation on this parameter.
-		for (Annotation annotation : annotations)
-		{
-			if (annotation.annotationType().getAnnotation(BindingAnnotation.class) != null)
-			{
-				if (bindingAnnotation != null)
-				{
-					throw new MoreThanOneBindingException();
-				}
-				bindingAnnotation = annotation;
-			}
-		}
-		return bindingAnnotation;
-	}
-
-	public static class MoreThanOneBindingException extends Exception
-	{
-		private static final long serialVersionUID = 1L;
-	}
 }

Added: wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java?rev=924049&view=auto
==============================================================================
--- wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java (added)
+++ wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java Tue Mar 16 23:30:35 2010
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.guice;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+import org.apache.wicket.WicketRuntimeException;
+import org.apache.wicket.injection.IFieldValueFactory;
+import org.apache.wicket.proxy.IProxyTargetLocator;
+import org.apache.wicket.proxy.LazyInitProxyFactory;
+
+import com.google.inject.BindingAnnotation;
+import com.google.inject.Inject;
+
+public class GuiceFieldValueFactory implements IFieldValueFactory
+{
+	private final boolean wrapInProxies;
+
+	GuiceFieldValueFactory(final boolean wrapInProxies)
+	{
+		this.wrapInProxies = wrapInProxies;
+	}
+
+	public Object getFieldValue(Field field, Object fieldOwner)
+	{
+		Object target = null;
+
+		if (supportsField(field))
+		{
+			Inject injectAnnotation = field.getAnnotation(Inject.class);
+			if (!Modifier.isStatic(field.getModifiers()) && injectAnnotation != null)
+			{
+				try
+				{
+					Annotation bindingAnnotation = findBindingAnnotation(field.getAnnotations());
+					final IProxyTargetLocator locator = new GuiceProxyTargetLocator(field,
+							bindingAnnotation, injectAnnotation.optional());
+
+					if (wrapInProxies)
+					{
+						target = LazyInitProxyFactory.createProxy(field.getType(), locator);
+					}
+					else
+					{
+						target = locator.locateProxyTarget();
+					}
+
+					if (!field.isAccessible())
+					{
+						field.setAccessible(true);
+					}
+
+					field.set(fieldOwner, target);
+
+				}
+				catch (IllegalAccessException e)
+				{
+					throw new WicketRuntimeException("Error Guice-injecting field " +
+							field.getName() + " in " + fieldOwner, e);
+				}
+				catch (MoreThanOneBindingException e)
+				{
+					throw new RuntimeException(
+							"Can't have more than one BindingAnnotation on field " +
+									field.getName() + " of class " +
+									fieldOwner.getClass().getName());
+				}
+			}
+		}
+
+		return target;
+	}
+
+	public boolean supportsField(Field field)
+	{
+		return field.isAnnotationPresent(Inject.class);
+	}
+
+	private Annotation findBindingAnnotation(final Annotation[] annotations)
+			throws MoreThanOneBindingException
+	{
+		Annotation bindingAnnotation = null;
+
+		// Work out if we have a BindingAnnotation on this parameter.
+		for (Annotation annotation : annotations)
+		{
+			if (annotation.annotationType().getAnnotation(BindingAnnotation.class) != null)
+			{
+				if (bindingAnnotation != null)
+				{
+					throw new MoreThanOneBindingException();
+				}
+				bindingAnnotation = annotation;
+			}
+		}
+		return bindingAnnotation;
+	}
+
+	public static class MoreThanOneBindingException extends Exception
+	{
+		private static final long serialVersionUID = 1L;
+	}
+}

Propchange: wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceProxyTargetLocator.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceProxyTargetLocator.java?rev=924049&r1=924048&r2=924049&view=diff
==============================================================================
--- wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceProxyTargetLocator.java (original)
+++ wicket/trunk/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceProxyTargetLocator.java Tue Mar 16 23:30:35 2010
@@ -18,7 +18,6 @@ package org.apache.wicket.guice;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 
 import org.apache.wicket.Application;
@@ -38,34 +37,16 @@ class GuiceProxyTargetLocator implements
 
 	private final boolean optional;
 
-	private final String[] data;
+	private final String className;
 
-	/** index of argument in the method being injected, or -1 for field */
-	private final int argIndex;
+	private final String fieldName;
 
 	public GuiceProxyTargetLocator(Field field, Annotation bindingAnnotation, boolean optional)
 	{
 		this.bindingAnnotation = bindingAnnotation;
 		this.optional = optional;
-		data = new String[2];
-		data[0] = field.getDeclaringClass().getName();
-		data[1] = field.getName();
-		argIndex = -1;
-	}
-
-	public GuiceProxyTargetLocator(Method method, int argIndex, Annotation bindingAnnotation,
-			boolean optional)
-	{
-		this.bindingAnnotation = bindingAnnotation;
-		this.optional = optional;
-		data = new String[2 + method.getParameterTypes().length];
-		data[0] = method.getDeclaringClass().getName();
-		data[1] = method.getName();
-		for (int i = 0; i < method.getParameterTypes().length; i++)
-		{
-			data[2 + i] = method.getParameterTypes()[i].getName();
-		}
-		this.argIndex = argIndex;
+		className = field.getDeclaringClass().getName();
+		fieldName = field.getName();
 	}
 
 	public Object locateProxyTarget()
@@ -77,27 +58,14 @@ class GuiceProxyTargetLocator implements
 		try
 		{
 
-			Class< ? > clazz = Classes.resolveClass(data[0]);
-			if (argIndex < 0)
-			{
-				final Field field = clazz.getDeclaredField(data[1]);
-				type = field.getGenericType();
-			}
-			else
-			{
-				Class< ? >[] paramTypes = new Class[data.length - 2];
-				for (int i = 2; i < data.length; i++)
-				{
-					paramTypes[i - 2] = Classes.resolveClass(data[i]);
-				}
-				final Method method = clazz.getDeclaredMethod(data[1], paramTypes);
-				type = method.getGenericParameterTypes()[argIndex];
-			}
+			Class< ? > clazz = Classes.resolveClass(className);
+			final Field field = clazz.getDeclaredField(fieldName);
+			type = field.getGenericType();
 		}
 		catch (Exception e)
 		{
-			throw new WicketRuntimeException("Error accessing member: " + data[1] + " of class: " +
-					data[0], e);
+			throw new WicketRuntimeException("Error accessing member: " + fieldName +
+					" of class: " + className, e);
 		}
 
 		// using TypeLiteral to retrieve the key gives us automatic support for

Modified: wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java?rev=924049&r1=924048&r2=924049&view=diff
==============================================================================
--- wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java (original)
+++ wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java Tue Mar 16 23:30:35 2010
@@ -89,6 +89,10 @@ public class GuiceInjectorTest extends T
 			TestComponent clonedComponent = (TestComponent)Objects.cloneObject(testComponent);
 			doChecksForComponent(clonedComponent);
 
+			// Test injection of a class that does not extend Component
+			TestNoComponent noncomponent = new TestNoComponent();
+			doChecksForNoComponent(noncomponent);
+
 		}
 		finally
 		{
@@ -97,22 +101,21 @@ public class GuiceInjectorTest extends T
 		}
 	}
 
+	private void doChecksForNoComponent(TestNoComponent component)
+	{
+		assertEquals(ITestService.RESULT_RED, component.getString());
+	}
+
 	private void doChecksForComponent(TestComponent component)
 	{
 		assertEquals(ITestService.RESULT, component.getInjectedField().getString());
 		assertEquals(null, component.getInjectedOptionalField());
 		assertEquals(ITestService.RESULT_RED, component.getInjectedFieldRed().getString());
 		assertEquals(ITestService.RESULT_BLUE, component.getInjectedFieldBlue().getString());
-		assertEquals(ITestService.RESULT, component.getInjectedMethod().getString());
-		assertEquals(ITestService.RESULT_BLUE, component.getInjectedMethodBlue().getString());
-		assertEquals(ITestService.RESULT_RED, component.getInjectedMethodRed().getString());
 
 		assertEquals(ITestService.RESULT, component.getInjectedFieldProvider().get().getString());
-		assertEquals(ITestService.RESULT, component.getInjectedMethodProvider().get().getString());
 
 		assertEquals(ITestService.RESULT, component.getInjectedTypeLiteralField().get(
 				ITestService.RESULT));
-		assertEquals(ITestService.RESULT, component.getInjectedTypeLiteralMethod().get(
-				ITestService.RESULT));
 	}
 }

Modified: wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponent.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponent.java?rev=924049&r1=924048&r2=924049&view=diff
==============================================================================
--- wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponent.java (original)
+++ wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponent.java Tue Mar 16 23:30:35 2010
@@ -49,15 +49,12 @@ public class TestComponent extends Compo
 	@Inject
 	private Map<String, String> injectedTypeLiteralField;
 
-	private ITestService injectedMethod, injectedMethodRed, injectedMethodBlue;
-
-	private Provider<ITestService> injectedMethodProvider;
-
-	private Map<String, String> injectedTypeLiteralMethod;
+	private final TestNoComponent noComponent;
 
 	public TestComponent(String id)
 	{
 		super(id);
+		noComponent = new TestNoComponent();
 	}
 
 	public ITestService getInjectedField()
@@ -75,21 +72,6 @@ public class TestComponent extends Compo
 		return injectedFieldRed;
 	}
 
-	public ITestService getInjectedMethod()
-	{
-		return injectedMethod;
-	}
-
-	public ITestService getInjectedMethodBlue()
-	{
-		return injectedMethodBlue;
-	}
-
-	public ITestService getInjectedMethodRed()
-	{
-		return injectedMethodRed;
-	}
-
 	public Provider<ITestService> getInjectedFieldProvider()
 	{
 		return injectedFieldProvider;
@@ -110,49 +92,15 @@ public class TestComponent extends Compo
 		return injectedTypeLiteralField;
 	}
 
-	public Provider<ITestService> getInjectedMethodProvider()
-	{
-		return injectedMethodProvider;
-	}
-
-	public Map<String, String> getInjectedTypeLiteralMethod()
-	{
-		return injectedTypeLiteralMethod;
-	}
-
-	@Inject
-	public void injectProvider(Provider<ITestService> provider)
-	{
-		injectedMethodProvider = provider;
-	}
-
-	@Inject
-	public void injectService(ITestService service)
-	{
-		injectedMethod = service;
-	}
-
-	@Inject
-	public void injectServiceBlue(@Blue ITestService service)
-	{
-		injectedMethodBlue = service;
-	}
-
-	@Inject
-	public void injectServiceRed(@Red ITestService service)
+	@Override
+	protected void onRender()
 	{
-		injectedMethodRed = service;
+		// Do nothing.
 	}
 
-	@Inject
-	public void injectTypeLiteral(Map<String, String> map)
+	public String getNoComponentString()
 	{
-		injectedTypeLiteralMethod = map;
+		return noComponent.getString();
 	}
 
-	@Override
-	protected void onRender()
-	{
-		// Do nothing.
-	}
 }

Added: wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestNoComponent.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestNoComponent.java?rev=924049&view=auto
==============================================================================
--- wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestNoComponent.java (added)
+++ wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestNoComponent.java Tue Mar 16 23:30:35 2010
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.guice;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.IClusterable;
+import org.apache.wicket.injection.Injector;
+
+import com.google.inject.Inject;
+
+/**
+ * Tests injection of services in classes which do not extend {@link Component}
+ */
+@SuppressWarnings("serial")
+public class TestNoComponent implements IClusterable
+{
+
+	@Inject
+	@Red
+	private ITestService testService;
+
+	/**
+	 * 
+	 * Construct.
+	 */
+	public TestNoComponent()
+	{
+		Injector.get().inject(this);
+	}
+
+	/**
+	 * @return if injection works should return {@link ITestService#RESULT_RED}
+	 */
+	public String getString()
+	{
+		return testService.getString();
+	}
+}

Propchange: wicket/trunk/wicket-guice/src/test/java/org/apache/wicket/guice/TestNoComponent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain