This is an automated email from the ASF dual-hosted git repository.

benw pushed a commit to branch TAP5-2758
in repository https://gitbox.apache.org/repos/asf/tapestry-5.git

commit ae22eba41176babd78f3b6915f4f07a1eeecddd1
Author: Ben Weidig <[email protected]>
AuthorDate: Sun Jul 23 10:48:07 2023 +0200

    TAP5-2758: Treat @Symbol as an explicit signal for injection calculation
---
 .../tapestry5/ioc/internal/util/InternalUtils.java | 16 ++++++++++
 .../specs/ServiceBuilderMethodInvokerSpec.groovy   | 35 ++++++++++++++++++++++
 .../groovy/ioc/specs/StrategyRegistrySpec.groovy   |  2 +-
 .../test/internal/ServiceBuilderMethodFixture.java | 25 +++++++++++++---
 4 files changed, 73 insertions(+), 5 deletions(-)

diff --git 
a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
 
b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
index 2a597ba13..5f5397ff3 100644
--- 
a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
+++ 
b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/InternalUtils.java
@@ -205,6 +205,22 @@ public class InternalUtils
             return asObjectCreator(locator.getService(named.value(), 
injectionType));
         }
 
+        // TAP5-2758: An @Symbol is treated as an explicit signal that the 
injected value
+        // should not be autowired, but resolved using the 
MasterObjectProvider instead.
+        // The check needs to be done before the @Inject one, or the value is 
solely treated
+        // by its type.
+        // Without this check, if any configuration is used, no 
List/Collection/Map value as
+        // Symbol can be used without both @Inject and @Symbol, as @Symbol has 
no explicit
+        // meaning on how to inject the value, and the configuration detector 
strikes before
+        // the final fallback to the MasterObjectProvider.
+
+        Symbol symbol = provider.getAnnotation(Symbol.class);
+
+        if (symbol != null)
+        {
+            return asObjectCreator(locator.getObject(injectionType, provider));
+        }
+
         // In the absence of @InjectService, try some autowiring. First, does 
the
         // parameter type match one of the resources (the parameter defaults)?
 
diff --git 
a/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy 
b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy
index 73109e17e..f34ad02cd 100644
--- 
a/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy
+++ 
b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy
@@ -3,6 +3,7 @@ package ioc.specs
 import org.apache.tapestry5.commons.AnnotationProvider
 import org.apache.tapestry5.commons.ObjectCreator
 import org.apache.tapestry5.ioc.ServiceBuilderResources
+import org.apache.tapestry5.ioc.internal.IOCMessages
 import org.apache.tapestry5.ioc.internal.ServiceBuilderMethodInvoker
 import org.apache.tapestry5.ioc.test.internal.FieService
 import org.apache.tapestry5.ioc.test.internal.FoeService
@@ -133,6 +134,40 @@ class ServiceBuilderMethodInvokerSpec extends 
AbstractSharedRegistrySpecificatio
     1 * resources.getOrderedConfiguration(Runnable) >> configuration
   }
 
+  def "injection of ordered configuration as List and another List"() {
+
+    List<Runnable> configuration = Mock()
+
+    fixture.expectedConfiguration = configuration
+      
+    when:
+
+    def actual = invoke "buildWithOrderedConfigurationAndList"
+
+    then:
+
+    RuntimeException e = thrown()
+
+    e.message == IOCMessages.tooManyConfigurationParameters(DESCRIPTION)
+  }
+
+  def "injection of ordered configuration as List and another List as 
Symbol"() {
+
+    List<Runnable> configuration = Mock()
+
+    fixture.expectedConfiguration = configuration
+      
+    when:
+
+    def actual = invoke "buildWithOrderedConfigurationAndSymbolList"
+
+    then:
+
+    actual.is implementation
+
+    1 * resources.getOrderedConfiguration(Runnable) >> configuration
+  }
+
   def "injection of unordered collection (as Collection)"() {
 
     Collection<Runnable> configuration = Mock()
diff --git a/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy 
b/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy
index 0b0cde4b1..9bf66cd52 100644
--- a/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/StrategyRegistrySpec.groovy
@@ -42,7 +42,7 @@ class StrategyRegistrySpec extends Specification {
 
     then:
 
-    sr.types.size == 2
+    sr.types.size() == 2
     sr.types.containsAll(List, Map)
   }
 
diff --git 
a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/ServiceBuilderMethodFixture.java
 
b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/ServiceBuilderMethodFixture.java
index e4e0e7b1e..97ebe4028 100644
--- 
a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/ServiceBuilderMethodFixture.java
+++ 
b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/ServiceBuilderMethodFixture.java
@@ -14,16 +14,19 @@
 
 package org.apache.tapestry5.ioc.test.internal;
 
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.inject.Named;
+
 import org.apache.tapestry5.ioc.ServiceResources;
 import org.apache.tapestry5.ioc.annotations.InjectService;
+import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.annotations.Value;
 import org.slf4j.Logger;
 import org.testng.Assert;
 
-import javax.inject.Named;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
 
 /**
  * Used by {@link ioc.specs.ServiceBuilderMethodInvokerSpec}.
@@ -58,6 +61,20 @@ public class ServiceBuilderMethodFixture extends Assert
         return fie;
     }
 
+    public FieService buildWithOrderedConfigurationAndList(List<Runnable> 
configuration, List<Runnable> noConfiguration)
+    {
+        assertSame(configuration, expectedConfiguration);
+
+        return fie;
+    }
+
+    public FieService 
buildWithOrderedConfigurationAndSymbolList(List<Runnable> configuration, 
@Symbol("ignored") List<Runnable> noConfiguration)
+    {
+        assertSame(configuration, expectedConfiguration);
+
+        return fie;
+    }
+
     public void methodWithParameterizedList(List<Runnable> list)
     {
     }

Reply via email to