Repository: wicket Updated Branches: refs/heads/wicket-6.x 594d36ec8 -> f5ce3f27c
WICKET-5686 @Inject should require the bean dependency instead of setting null Add test case for Guice Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/f5ce3f27 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/f5ce3f27 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/f5ce3f27 Branch: refs/heads/wicket-6.x Commit: f5ce3f27cfaf9a0ece3f6c0c203cde578337d8fc Parents: ee4ebba Author: Martin Tzvetanov Grigorov <[email protected]> Authored: Thu Aug 28 12:01:30 2014 +0300 Committer: Martin Tzvetanov Grigorov <[email protected]> Committed: Thu Aug 28 12:02:42 2014 +0300 ---------------------------------------------------------------------- .../wicket/guice/GuiceFieldValueFactory.java | 17 +- .../wicket/guice/AbstractInjectorTest.java | 179 +++++++++++++++++++ .../wicket/guice/GuiceInjectInjectorTest.java | 34 ++++ .../apache/wicket/guice/GuiceInjectorTest.java | 178 ------------------ .../guice/JavaxInjectGuiceInjectorTest.java | 39 +++- .../wicket/guice/JavaxInjectTestComponent.java | 13 ++ .../wicket/guice/TestComponentInterface.java | 1 - 7 files changed, 268 insertions(+), 193 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java b/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java index ed137f5..d1543e1 100644 --- a/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java +++ b/wicket-guice/src/main/java/org/apache/wicket/guice/GuiceFieldValueFactory.java @@ -22,13 +22,13 @@ import java.lang.reflect.Modifier; import javax.inject.Qualifier; -import com.google.inject.BindingAnnotation; -import com.google.inject.Inject; -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; + /** * */ @@ -62,9 +62,9 @@ public class GuiceFieldValueFactory implements IFieldValueFactory { try { + boolean optional = injectAnnotation != null && injectAnnotation.optional(); Annotation bindingAnnotation = findBindingAnnotation(field.getAnnotations()); - final IProxyTargetLocator locator = new GuiceProxyTargetLocator(field, - bindingAnnotation, injectAnnotation != null ? injectAnnotation.optional() : false); + final IProxyTargetLocator locator = new GuiceProxyTargetLocator(field, bindingAnnotation, optional); if (wrapInProxies) { @@ -79,13 +79,6 @@ public class GuiceFieldValueFactory implements IFieldValueFactory { 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) { http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/test/java/org/apache/wicket/guice/AbstractInjectorTest.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/AbstractInjectorTest.java b/wicket-guice/src/test/java/org/apache/wicket/guice/AbstractInjectorTest.java new file mode 100644 index 0000000..30111ac --- /dev/null +++ b/wicket-guice/src/test/java/org/apache/wicket/guice/AbstractInjectorTest.java @@ -0,0 +1,179 @@ +/* + * 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.util.HashMap; +import java.util.Map; + +import javax.inject.Named; + +import org.apache.wicket.Session; +import org.apache.wicket.ThreadContext; +import org.apache.wicket.core.util.lang.WicketObjects; +import org.apache.wicket.mock.MockApplication; +import org.apache.wicket.mock.MockWebRequest; +import org.apache.wicket.protocol.http.WebSession; +import org.apache.wicket.protocol.http.mock.MockServletContext; +import org.apache.wicket.request.Url; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.google.inject.Binder; +import com.google.inject.Module; +import com.google.inject.Provider; +import com.google.inject.TypeLiteral; +import com.google.inject.name.Names; + +/** + */ +public abstract class AbstractInjectorTest extends Assert +{ + + protected abstract TestNoComponentInterface newTestNoComponent(); + + protected abstract TestComponentInterface newTestComponent(String id); + + private final MockApplication app = new MockApplication(); + + @Before + public void before() + { + app.setServletContext(new MockServletContext(app, null)); + + ThreadContext.setApplication(app); + + app.setName(getClass().getName()); + app.initApplication(); + + Session session = new WebSession(new MockWebRequest(Url.parse("/"))); + app.getSessionStore().bind(null, session); + ThreadContext.setSession(session); + + GuiceComponentInjector injector = new GuiceComponentInjector(app, new Module() + { + @Override + public void configure(final Binder binder) + { + binder.bind(ITestService.class).to(TestService.class); + binder.bind(ITestService.class) + .annotatedWith(Red.class) + .to(TestServiceRed.class); + binder.bind(ITestService.class) + .annotatedWith(Blue.class) + .to(TestServiceBlue.class); + binder.bind(new TypeLiteral<Map<String, String>>() + { + }).toProvider(new Provider<Map<String, String>>() + { + @Override + public Map<String, String> get() + { + Map<String, String> strings = new HashMap<String, String>(); + + strings.put(ITestService.RESULT, ITestService.RESULT); + + return strings; + } + }); + + binder.bind(String.class).annotatedWith(Names.named("named1")).toInstance("NAMED_1"); + binder.bind(String.class).annotatedWith(Names.named("named2")).toInstance("NAMED_2"); + + binder.bind(String.class).annotatedWith(new Jsr330Named("named1")).toInstance("NAMED_1"); + binder.bind(String.class).annotatedWith(new Jsr330Named("named2")).toInstance("NAMED_2"); + } + + }); + app.getComponentInstantiationListeners().add(injector); + } + + @After + public void after() + { + app.internalDestroy(); + ThreadContext.detach(); + } + + /** + * testInjectionAndSerialization() + */ + @Test + public void testInjectionAndSerialization() + { + // Create a new component, which should be automatically injected, + // and test to make sure the injection has worked. + TestComponentInterface testComponent = newTestComponent("id"); + doChecksForComponent(testComponent); + + // Serialize and deserialize the object, and check it still works. + TestComponentInterface clonedComponent = (TestComponentInterface)WicketObjects.cloneObject(testComponent); + doChecksForComponent(clonedComponent); + + // Test injection of a class that does not extend Component + TestNoComponentInterface noncomponent = newTestNoComponent(); + doChecksForNoComponent(noncomponent); + } + + private void doChecksForNoComponent(final TestNoComponentInterface noncomponent) + { + assertEquals(ITestService.RESULT_RED, noncomponent.getString()); + } + + private void doChecksForComponent(final TestComponentInterface 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.getInjectedFieldProvider().get().getString()); + + assertEquals(ITestService.RESULT, + component.getInjectedTypeLiteralField().get(ITestService.RESULT)); + + assertEquals("NAMED_1", component.getNamed1()); + assertEquals("NAMED_2", component.getNamed2()); + } + + /** + * Helper class to make binding of an instance of javax.inject.Named less verbose + */ + private static class Jsr330Named implements Named + { + private final String name; + + private Jsr330Named(String name) + { + this.name = name; + } + + @Override + public String value() + { + return name; + } + + @Override + public Class<? extends Annotation> annotationType() + { + return Named.class; + } + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectInjectorTest.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectInjectorTest.java b/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectInjectorTest.java new file mode 100644 index 0000000..f820209 --- /dev/null +++ b/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectInjectorTest.java @@ -0,0 +1,34 @@ +/* + * 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; + +/** + */ +public class GuiceInjectInjectorTest extends AbstractInjectorTest +{ + @Override + protected TestComponentInterface newTestComponent(String id) + { + return new TestComponent(id); + } + + @Override + protected TestNoComponentInterface newTestNoComponent() + { + return new TestNoComponent(); + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java b/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java deleted file mode 100644 index 26e31f1..0000000 --- a/wicket-guice/src/test/java/org/apache/wicket/guice/GuiceInjectorTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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.util.HashMap; -import java.util.Map; - -import javax.inject.Named; - -import com.google.inject.Binder; -import com.google.inject.Module; -import com.google.inject.Provider; -import com.google.inject.TypeLiteral; -import com.google.inject.name.Names; -import org.apache.wicket.Session; -import org.apache.wicket.ThreadContext; -import org.apache.wicket.mock.MockApplication; -import org.apache.wicket.mock.MockWebRequest; -import org.apache.wicket.protocol.http.WebSession; -import org.apache.wicket.protocol.http.mock.MockServletContext; -import org.apache.wicket.request.Url; -import org.apache.wicket.core.util.lang.WicketObjects; -import org.apache.wicket.util.lang.Args; -import org.junit.Assert; -import org.junit.Test; - -/** - */ -public class GuiceInjectorTest extends Assert -{ - /** - * testInjectionAndSerialization() - */ - @Test - public void testInjectionAndSerialization() - { - MockApplication app = new MockApplication(); - app.setServletContext(new MockServletContext(app, null)); - try - { - ThreadContext.setApplication(app); - - app.setName(getClass().getName()); - app.initApplication(); - - Session session = new WebSession(new MockWebRequest(Url.parse("/"))); - app.getSessionStore().bind(null, session); - ThreadContext.setSession(session); - - GuiceComponentInjector injector = new GuiceComponentInjector(app, new Module() - { - @Override - public void configure(final Binder binder) - { - binder.bind(ITestService.class).to(TestService.class); - binder.bind(ITestService.class) - .annotatedWith(Red.class) - .to(TestServiceRed.class); - binder.bind(ITestService.class) - .annotatedWith(Blue.class) - .to(TestServiceBlue.class); - binder.bind(new TypeLiteral<Map<String, String>>() - { - }).toProvider(new Provider<Map<String, String>>() - { - @Override - public Map<String, String> get() - { - Map<String, String> strings = new HashMap<String, String>(); - - strings.put(ITestService.RESULT, ITestService.RESULT); - - return strings; - } - }); - - binder.bind(String.class).annotatedWith(Names.named("named1")).toInstance("NAMED_1"); - binder.bind(String.class).annotatedWith(Names.named("named2")).toInstance("NAMED_2"); - - binder.bind(String.class).annotatedWith(new Jsr330Named("named1")).toInstance("NAMED_1"); - binder.bind(String.class).annotatedWith(new Jsr330Named("named2")).toInstance("NAMED_2"); - } - - }); - app.getComponentInstantiationListeners().add(injector); - - // Create a new component, which should be automatically injected, - // and test to make sure the injection has worked. - TestComponentInterface testComponent = newTestComponent("id"); - doChecksForComponent(testComponent); - - // Serialize and deserialize the object, and check it still works. - TestComponentInterface clonedComponent = (TestComponentInterface)WicketObjects.cloneObject(testComponent); - doChecksForComponent(clonedComponent); - - // Test injection of a class that does not extend Component - TestNoComponentInterface noncomponent = newTestNoComponent(); - doChecksForNoComponent(noncomponent); - - } - finally - { - app.internalDestroy(); - ThreadContext.detach(); - } - } - - private void doChecksForNoComponent(final TestNoComponentInterface noncomponent) - { - assertEquals(ITestService.RESULT_RED, noncomponent.getString()); - } - - private void doChecksForComponent(final TestComponentInterface 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.getInjectedFieldProvider().get().getString()); - - assertEquals(ITestService.RESULT, - component.getInjectedTypeLiteralField().get(ITestService.RESULT)); - - assertEquals("NAMED_1", component.getNamed1()); - assertEquals("NAMED_2", component.getNamed2()); - } - - protected TestNoComponentInterface newTestNoComponent() - { - return new TestNoComponent(); - } - - protected TestComponentInterface newTestComponent(String id) - { - return new TestComponent(id); - } - - /** - * Helper class to make binding of an instance of javax.inject.Named less verbose - */ - private static class Jsr330Named implements Named - { - private final String name; - - private Jsr330Named(String name) - { - this.name = name; - } - - @Override - public String value() - { - return name; - } - - @Override - public Class<? extends Annotation> annotationType() - { - return Named.class; - } - } -} http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectGuiceInjectorTest.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectGuiceInjectorTest.java b/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectGuiceInjectorTest.java index 4dd4831..7935606 100644 --- a/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectGuiceInjectorTest.java +++ b/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectGuiceInjectorTest.java @@ -16,13 +16,20 @@ */ package org.apache.wicket.guice; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.is; + +import com.google.inject.ConfigurationException; +import com.google.inject.spi.Message; +import org.apache.wicket.settings.IResourceSettings; +import org.junit.Test; /** */ -public class JavaxInjectGuiceInjectorTest extends GuiceInjectorTest +public class JavaxInjectGuiceInjectorTest extends AbstractInjectorTest { @Override - protected TestComponentInterface newTestComponent(String id) + protected JavaxInjectTestComponent newTestComponent(String id) { return new JavaxInjectTestComponent(id); } @@ -32,4 +39,32 @@ public class JavaxInjectGuiceInjectorTest extends GuiceInjectorTest { return new JavaxInjectTestNoComponent(); } + + /** + * https://issues.apache.org/jira/browse/WICKET-5686 + * + * Wicket-Guice creates a lazy proxy that fails only when trying to use it + * + * @see org.apache.wicket.guice.GuiceFieldValueFactory#GuiceFieldValueFactory(boolean) + */ + @Test + public void required() + { + JavaxInjectTestComponent component = newTestComponent("id"); + + // get the lazy proxy + IResourceSettings nonExisting = component.getNonExisting(); + + try + { + // call any method on the lazy proxy + nonExisting.getCachingStrategy(); + fail("Fields annotated with @javax.inject.Inject are required!"); + } + catch (ConfigurationException cx) + { + Message message = cx.getErrorMessages().iterator().next(); + assertThat(message.getMessage(), is(equalTo("No implementation for org.apache.wicket.settings.IResourceSettings was bound."))); + } + } } http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectTestComponent.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectTestComponent.java b/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectTestComponent.java index 5792be5..6f462a6 100644 --- a/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectTestComponent.java +++ b/wicket-guice/src/test/java/org/apache/wicket/guice/JavaxInjectTestComponent.java @@ -23,6 +23,7 @@ import javax.inject.Named; import com.google.inject.Provider; import org.apache.wicket.Component; +import org.apache.wicket.settings.IResourceSettings; /** */ @@ -55,6 +56,13 @@ public class JavaxInjectTestComponent extends Component implements TestComponent @Named("named2") private String named2; + /** + * A non-existing bean. + * IResourceSettings is chosen randomly. Any non-primitive type would suffice + */ + @Inject + private IResourceSettings nonExisting; + private final JavaxInjectTestNoComponent noComponent; /** @@ -137,6 +145,11 @@ public class JavaxInjectTestComponent extends Component implements TestComponent return injectedTypeLiteralField; } + public IResourceSettings getNonExisting() + { + return nonExisting; + } + @Override protected void onRender() { http://git-wip-us.apache.org/repos/asf/wicket/blob/f5ce3f27/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponentInterface.java ---------------------------------------------------------------------- diff --git a/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponentInterface.java b/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponentInterface.java index c7fb85b..77e9e52 100644 --- a/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponentInterface.java +++ b/wicket-guice/src/test/java/org/apache/wicket/guice/TestComponentInterface.java @@ -38,5 +38,4 @@ public interface TestComponentInterface Provider<ITestService> getInjectedFieldProvider(); Map<String, String> getInjectedTypeLiteralField(); - }
