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

veithen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ws-axiom.git


The following commit(s) were added to refs/heads/master by this push:
     new be43ad34e Use @Named binding in ParameterFanOutNode
be43ad34e is described below

commit be43ad34e5c515a946fe1ec3c3c3cb7f79155d9e
Author: Andreas Veithen-Knowles <[email protected]>
AuthorDate: Sun Mar 8 08:37:04 2026 +0000

    Use @Named binding in ParameterFanOutNode
    
    Extract createBindingModule() hook in AbstractFanOutNode so that
    subclasses can customise the Guice binding. ParameterFanOutNode now
    overrides it to bind with @Named(parameterName) instead of a plain
    type binding.
    
    Update SAAJTestCase to use @Inject @Named("spec") on the SOAPSpec
    field, and update README.md and migration.md accordingly.
---
 testing/matrix-testsuite/README.md                 | 11 +++++--
 testing/matrix-testsuite/migration.md              | 19 +++++++----
 .../axiom/testutils/suite/AbstractFanOutNode.java  | 37 +++++++++++++++-------
 .../axiom/testutils/suite/ParameterFanOutNode.java | 13 ++++++++
 .../org/apache/axiom/ts/saaj/SAAJTestCase.java     |  6 +++-
 5 files changed, 65 insertions(+), 21 deletions(-)

diff --git a/testing/matrix-testsuite/README.md 
b/testing/matrix-testsuite/README.md
index 31750d8fd..9ef716cec 100644
--- a/testing/matrix-testsuite/README.md
+++ b/testing/matrix-testsuite/README.md
@@ -93,10 +93,13 @@ Subclasses:
 
 - **`DimensionFanOutNode<D extends Dimension>`** — for types that implement the
   `Dimension` interface. Parameters are extracted via
-  `Dimension.addTestParameters()`.
+  `Dimension.addTestParameters()`. The value is bound as a plain (unannotated)
+  type binding.
 
 - **`ParameterFanOutNode<T>`** — for arbitrary types. The caller supplies a
   parameter name and a `Function<T, String>` to extract the parameter value.
+  The value is bound with a `@Named` annotation whose value is the parameter
+  name; injection sites must use `@Inject @Named("paramName")`.
 
 ### `MatrixTest`
 
@@ -130,10 +133,14 @@ override `runTest()`. Dependencies are declared with 
`@Inject` — either on fie
 or via constructor. The test case does **not** receive parameters through its
 constructor and does **not** call `addTestParameter()`.
 
+For values bound by `DimensionFanOutNode`, use a plain `@Inject`. For values
+bound by `ParameterFanOutNode`, add `@Named("paramName")` matching the
+parameter name passed to the fan-out node.
+
 ```java
 public abstract class MyTestCase extends TestCase {
     @Inject protected SomeImplementation impl;
-    @Inject protected SomeDimension dimension;
+    @Inject @Named("dimension") protected SomeDimension dimension;
 
     // convenience methods using impl and dimension ...
 }
diff --git a/testing/matrix-testsuite/migration.md 
b/testing/matrix-testsuite/migration.md
index 37fb81bb2..cea757332 100644
--- a/testing/matrix-testsuite/migration.md
+++ b/testing/matrix-testsuite/migration.md
@@ -97,7 +97,7 @@ public abstract class SAAJTestCase extends MatrixTestCase {
 ```java
 public abstract class SAAJTestCase extends TestCase {
     @Inject protected SAAJImplementation saajImplementation;
-    @Inject protected SOAPSpec spec;
+    @Inject @Named("spec") protected SOAPSpec spec;
 
     protected final MessageFactory newMessageFactory() throws SOAPException {
         return 
spec.getAdapter(FactorySelector.class).newMessageFactory(saajImplementation);
@@ -105,6 +105,9 @@ public abstract class SAAJTestCase extends TestCase {
 }
 ```
 
+Note: the `@Named("spec")` annotation is required because `ParameterFanOutNode`
+binds values with `@Named` using the parameter name. Use 
`com.google.inject.name.Named`.
+
 ### 2. Update each test case class
 
 Each test case class currently accepts constructor parameters and forwards them
@@ -158,10 +161,12 @@ The old `*TestSuiteBuilder` class extends 
`MatrixTestSuiteBuilder` and overrides
    time.
 
 Use `ParameterFanOutNode` for types that don't implement `Dimension` 
(supplying a
-parameter name and a function to extract the display value). Use
-`DimensionFanOutNode` for types that implement `Dimension`. Both fan-out nodes
-also accept a single `MatrixTestNode` child directly (convenience constructor)
-instead of an `ImmutableList<MatrixTestNode>`.
+parameter name and a function to extract the display value); the value is bound
+with `@Named(parameterName)`, so injection sites must use
+`@Inject @Named("...")`. Use `DimensionFanOutNode` for types that implement
+`Dimension` (plain unannotated binding). Both fan-out nodes also accept a 
single
+`MatrixTestNode` child directly (convenience constructor) instead of an
+`ImmutableList<MatrixTestNode>`.
 
 **Before:**
 
@@ -347,8 +352,8 @@ public class StAXPivotTransformerTest extends 
MatrixTestCase {
 
 ```java
 public class StAXPivotTransformerTest extends TestCase {
-    @Inject private XSLTImplementation xsltImplementation;
-    @Inject private XMLSample sample;
+    @Inject @Named("xslt") private XSLTImplementation xsltImplementation;
+    @Inject @Named("sample") private XMLSample sample;
 
     @Override
     protected void runTest() throws Throwable {
diff --git 
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/AbstractFanOutNode.java
 
b/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/AbstractFanOutNode.java
index fed282128..2784580fc 100644
--- 
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/AbstractFanOutNode.java
+++ 
b/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/AbstractFanOutNode.java
@@ -30,26 +30,31 @@ import org.junit.jupiter.api.DynamicNode;
 import com.google.common.collect.ImmutableList;
 import com.google.inject.AbstractModule;
 import com.google.inject.Injector;
+import com.google.inject.Module;
 
 /**
  * Abstract base class for fan-out nodes that iterate over a list of values, 
creating one {@link
  * DynamicContainer} per value. For each value, a child Guice injector is 
created that binds the
- * value type to the specific instance.
+ * value type to the specific instance. The binding is created by {@link
+ * #createBindingModule(Object)}, which subclasses may override (e.g. {@link 
ParameterFanOutNode}
+ * adds a {@code @Named} annotation).
  *
  * <p>Subclasses define how test parameters (used for display names and LDAP 
filter matching) are
  * extracted from each value:
  *
  * <ul>
  *   <li>{@link DimensionFanOutNode} — for types that implement {@link 
Dimension}, using {@link
- *       Dimension#addTestParameters}.
+ *       Dimension#addTestParameters}. The value is bound as a plain 
(unannotated) type binding.
  *   <li>{@link ParameterFanOutNode} — for arbitrary types, using a 
caller-supplied parameter name
- *       and {@link java.util.function.Function}.
+ *       and {@link java.util.function.Function}. The value is bound with a 
{@code @Named}
+ *       annotation whose value is the parameter name; injection sites must use
+ *       {@code @Inject @Named("paramName")}.
  * </ul>
  *
  * @param <T> the value type
  */
 public abstract class AbstractFanOutNode<T> extends ParentNode {
-    private final Class<T> type;
+    protected final Class<T> type;
     private final ImmutableList<T> values;
 
     protected AbstractFanOutNode(
@@ -65,6 +70,22 @@ public abstract class AbstractFanOutNode<T> extends 
ParentNode {
      */
     protected abstract Map<String, String> extractParameters(T value);
 
+    /**
+     * Creates the Guice module that binds the value for a given fan-out 
iteration. Subclasses may
+     * override this to customise the binding (e.g. adding a binding 
annotation).
+     *
+     * @param value the current iteration value
+     * @return a module that provides the binding for {@code value}
+     */
+    protected Module createBindingModule(T value) {
+        return new AbstractModule() {
+            @Override
+            protected void configure() {
+                bind(type).toInstance(value);
+            }
+        };
+    }
+
     @Override
     Stream<DynamicNode> toDynamicNodes(
             Injector parentInjector,
@@ -74,13 +95,7 @@ public abstract class AbstractFanOutNode<T> extends 
ParentNode {
                 .map(
                         value -> {
                             Injector childInjector =
-                                    parentInjector.createChildInjector(
-                                            new AbstractModule() {
-                                                @Override
-                                                protected void configure() {
-                                                    
bind(type).toInstance(value);
-                                                }
-                                            });
+                                    
parentInjector.createChildInjector(createBindingModule(value));
 
                             Map<String, String> parameters = 
extractParameters(value);
                             HashMap<String, String> params = new 
HashMap<>(inheritedParameters);
diff --git 
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/ParameterFanOutNode.java
 
b/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/ParameterFanOutNode.java
index b57e80b87..8dcb5cbeb 100644
--- 
a/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/ParameterFanOutNode.java
+++ 
b/testing/matrix-testsuite/src/main/java/org/apache/axiom/testutils/suite/ParameterFanOutNode.java
@@ -22,6 +22,9 @@ import java.util.Map;
 import java.util.function.Function;
 
 import com.google.common.collect.ImmutableList;
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.name.Names;
 
 /**
  * Fan-out node for arbitrary value types that do not implement {@link 
Dimension}. The caller
@@ -63,6 +66,16 @@ public class ParameterFanOutNode<T> extends 
AbstractFanOutNode<T> {
         this(type, values, parameterName, parameterValueFunction, 
ImmutableList.of(child));
     }
 
+    @Override
+    protected Module createBindingModule(T value) {
+        return new AbstractModule() {
+            @Override
+            protected void configure() {
+                
bind(type).annotatedWith(Names.named(parameterName)).toInstance(value);
+            }
+        };
+    }
+
     @Override
     protected Map<String, String> extractParameters(T value) {
         return Map.of(parameterName, parameterValueFunction.apply(value));
diff --git 
a/testing/saaj-testsuite/src/main/java/org/apache/axiom/ts/saaj/SAAJTestCase.java
 
b/testing/saaj-testsuite/src/main/java/org/apache/axiom/ts/saaj/SAAJTestCase.java
index 190bbcdd1..e62375893 100644
--- 
a/testing/saaj-testsuite/src/main/java/org/apache/axiom/ts/saaj/SAAJTestCase.java
+++ 
b/testing/saaj-testsuite/src/main/java/org/apache/axiom/ts/saaj/SAAJTestCase.java
@@ -25,12 +25,16 @@ import jakarta.xml.soap.SOAPFactory;
 import org.apache.axiom.ts.soap.SOAPSpec;
 
 import com.google.inject.Inject;
+import com.google.inject.name.Named;
 
 import junit.framework.TestCase;
 
 public abstract class SAAJTestCase extends TestCase {
     @Inject protected SAAJImplementation saajImplementation;
-    @Inject protected SOAPSpec spec;
+
+    @Inject
+    @Named("spec")
+    protected SOAPSpec spec;
 
     protected final MessageFactory newMessageFactory() throws SOAPException {
         return 
spec.getAdapter(FactorySelector.class).newMessageFactory(saajImplementation);

Reply via email to