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

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


The following commit(s) were added to refs/heads/master by this push:
     new 3dc068e6a TAP5-2758: Treat @Symbol as explicit injection signal
3dc068e6a is described below

commit 3dc068e6a33a4fbb9ab36d383b32f08647f50f76
Author: Ben Weidig <b...@netzgut.net>
AuthorDate: Mon Apr 14 08:33:39 2025 +0200

    TAP5-2758: Treat @Symbol as explicit injection signal
    
    The @Symbol annotation should be an explicit injection signal and not be
    autowired. That allows using @Symbol without an additional @Inject to
    force the behavior in certain scenarios.
---
 .../tapestry5/ioc/internal/util/InternalUtils.java | 19 ++++++-
 .../groovy/ioc/specs/DecorateWithSymbolSpec.groovy | 24 +++++++++
 .../specs/ServiceBuilderMethodInvokerSpec.groovy   | 20 ++++++++
 .../test/internal/DecorateWithSymbolModule.java    | 60 ++++++++++++++++++++++
 .../test/internal/ServiceBuilderMethodFixture.java | 17 +++++-
 5 files changed, 138 insertions(+), 2 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 8b7b607f9..ad5da52a2 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
@@ -1,4 +1,4 @@
-// Copyright 2006-2014 The Apache Software Foundation
+// Copyright 2006-2025 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -205,6 +205,23 @@ 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/DecorateWithSymbolSpec.groovy 
b/tapestry-ioc/src/test/groovy/ioc/specs/DecorateWithSymbolSpec.groovy
new file mode 100644
index 000000000..dd4a89e45
--- /dev/null
+++ b/tapestry-ioc/src/test/groovy/ioc/specs/DecorateWithSymbolSpec.groovy
@@ -0,0 +1,24 @@
+package ioc.specs
+
+import org.apache.tapestry5.ioc.test.internal.DecorateWithSymbolModule
+import org.apache.tapestry5.ioc.test.internal.FoeService
+
+import spock.lang.Issue
+
+@Issue("TAP5-2758")
+class DecorateWithSymbolSpec extends AbstractRegistrySpecification {
+
+
+  def "ServiceDef obtainable by service id"() {
+    given:
+    buildRegistry DecorateWithSymbolModule
+
+    when:
+
+    def service = getService "FoeService", FoeService
+
+    then:
+    service.foe() == DecorateWithSymbolModule.SYMBOL_VALUE
+    service.foe() != DecorateWithSymbolModule.ORIGINAL_VALUE
+    }
+}
diff --git 
a/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy 
b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy
index 73109e17e..3b83fd3af 100644
--- 
a/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy
+++ 
b/tapestry-ioc/src/test/groovy/ioc/specs/ServiceBuilderMethodInvokerSpec.groovy
@@ -3,11 +3,13 @@ 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
 import org.apache.tapestry5.ioc.test.internal.ServiceBuilderMethodFixture
 import org.slf4j.Logger
+import spock.lang.Issue
 
 class ServiceBuilderMethodInvokerSpec extends 
AbstractSharedRegistrySpecification {
 
@@ -150,6 +152,24 @@ class ServiceBuilderMethodInvokerSpec extends 
AbstractSharedRegistrySpecificatio
     1 * resources.getUnorderedConfiguration(Runnable) >> configuration
   }
 
+  @Issue("TAP5-2758")
+  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 "builder method returns null"() {
 
     fixture.fie = null
diff --git 
a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/DecorateWithSymbolModule.java
 
b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/DecorateWithSymbolModule.java
new file mode 100644
index 000000000..05288e82c
--- /dev/null
+++ 
b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/test/internal/DecorateWithSymbolModule.java
@@ -0,0 +1,60 @@
+// Copyright 2025 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.ioc.test.internal;
+
+import org.apache.tapestry5.commons.MappedConfiguration;
+import org.apache.tapestry5.ioc.annotations.Contribute;
+import org.apache.tapestry5.ioc.annotations.Decorate;
+import org.apache.tapestry5.ioc.annotations.Match;
+import org.apache.tapestry5.ioc.annotations.Symbol;
+import org.apache.tapestry5.ioc.services.FactoryDefaults;
+import org.apache.tapestry5.ioc.services.SymbolProvider;
+
+public class DecorateWithSymbolModule
+{
+    public static final String SYMBOL_KEY = "symbol-key";
+
+    public static final int ORIGINAL_VALUE = 23;
+    public static final int SYMBOL_VALUE = 42;
+
+    @FactoryDefaults
+    @Contribute(SymbolProvider.class)
+    public static void contributeFactoryDefaults(MappedConfiguration<String, 
Object> conf)
+    {
+        conf.add(SYMBOL_KEY, SYMBOL_VALUE);
+    }
+
+    public FoeService buildFoeService()
+    {
+        return new FoeService()
+        {
+
+            @Override
+            public int foe()
+            {
+                return ORIGINAL_VALUE;
+            }
+        };
+    }
+
+    @Decorate(serviceInterface = FoeService.class)
+    @Match(value = "FoeService")
+    public static FoeService decorateSymbolService(FoeService delegate,
+            @Symbol(SYMBOL_KEY)
+            int symbolValue)
+    {
+        return () -> symbolValue;
+    }
+}
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 1f5fd9789..e4f9945f6 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
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2010, 2012 The Apache Software Foundation
+// Copyright 2006, 2007, 2010, 2012, 2025 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,6 +16,7 @@ package org.apache.tapestry5.ioc.test.internal;
 
 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;
@@ -58,6 +59,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