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