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

lukaszlenart pushed a commit to branch feature/WW-5512-optional-inject
in repository https://gitbox.apache.org/repos/asf/struts.git

commit a33c162f53f96879f98f43eab8bea45b61ba03c7
Author: Lukasz Lenart <lukaszlen...@apache.org>
AuthorDate: Sun Jan 5 17:45:11 2025 +0100

    WW-5512 Extends the container to support injecting optional parameters into 
constructor
---
 .../opensymphony/xwork2/inject/ContainerImpl.java  |  8 ++-
 .../xwork2/inject/ContainerImplTest.java           | 83 ++++++++++++++++------
 2 files changed, 67 insertions(+), 24 deletions(-)

diff --git 
a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java 
b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
index 455f8a449..1596077ab 100644
--- a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
+++ b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java
@@ -419,8 +419,12 @@ class ContainerImpl implements Container {
                 // First time through...
                 constructionContext.startConstruction();
                 try {
-                    final Object[] parameters = getParameters(constructor, 
context, parameterInjectors);
-                    t = constructor.newInstance(parameters);
+                    if (constructor.getParameterCount() > 0 && 
parameterInjectors == null) {
+                        t = constructor.newInstance(new 
Object[constructor.getParameterCount()]);
+                    } else {
+                        final Object[] parameters = getParameters(constructor, 
context, parameterInjectors);
+                        t = constructor.newInstance(parameters);
+                    }
                     constructionContext.setProxyDelegates(t);
                 } finally {
                     constructionContext.finishConstruction();
diff --git 
a/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java 
b/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java
index 85ef9ace8..d3e479d19 100644
--- a/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java
+++ b/core/src/test/java/com/opensymphony/xwork2/inject/ContainerImplTest.java
@@ -29,6 +29,7 @@ import java.util.concurrent.Callable;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeTrue;
@@ -49,6 +50,7 @@ public class ContainerImplTest {
         ContainerBuilder cb = new ContainerBuilder();
         cb.constant("methodCheck.name", "Lukasz");
         cb.constant("fieldCheck.name", "Lukasz");
+        cb.constant("constructorCheck.name", "Lukasz");
         cb.factory(EarlyInitializable.class, EarlyInitializableBean.class, 
Scope.SINGLETON);
         cb.factory(Initializable.class, InitializableBean.class, 
Scope.SINGLETON);
         cb.factory(EarlyInitializable.class, "prototypeEarlyInitializable", 
EarlyInitializableBean.class, Scope.PROTOTYPE);
@@ -65,15 +67,29 @@ public class ContainerImplTest {
     }
 
     @Test
-    public void fieldInjector() throws Exception {
+    public void fieldInjector() {
         FieldCheck fieldCheck = new FieldCheck();
         c.inject(fieldCheck);
-        assertEquals(fieldCheck.getName(), "Lukasz");
+        assertEquals("Lukasz", fieldCheck.getName());
     }
 
     @Test
-    public void methodInjector() throws Exception {
-        c.inject(new MethodCheck());
+    public void methodInjector() {
+        MethodCheck methodCheck = new MethodCheck();
+        c.inject(methodCheck);
+        assertEquals("Lukasz", methodCheck.getName());
+    }
+
+    @Test
+    public void constructorInjector() {
+        ConstructorCheck constructorCheck = c.inject(ConstructorCheck.class);
+        assertEquals("Lukasz", constructorCheck.getName());
+    }
+
+    @Test
+    public void optionalConstructorInjector() {
+        OptionalConstructorCheck constructorCheck = 
c.inject(OptionalConstructorCheck.class);
+        assertNull(constructorCheck.getName());
     }
 
     /**
@@ -92,7 +108,7 @@ public class ContainerImplTest {
      * Inject values into method under SecurityManager
      */
     @Test
-    public void testMethodInjectorWithSecurityEnabled() throws Exception {
+    public void testMethodInjectorWithSecurityEnabled() {
         assumeTrue(SystemUtils.isJavaVersionAtMost(JavaVersion.JAVA_20));
         System.setSecurityManager(new TestSecurityManager());
         assertThrows(DependencyException.class, () -> c.inject(new 
MethodCheck()));
@@ -101,7 +117,7 @@ public class ContainerImplTest {
     }
 
     @Test
-    public void testEarlyInitializable() throws Exception {
+    public void testEarlyInitializable() {
         assertTrue("should being initialized already", 
EarlyInitializableBean.initializedEarly);
 
         EarlyInitializableCheck earlyInitializableCheck = new 
EarlyInitializableCheck();
@@ -148,22 +164,19 @@ public class ContainerImplTest {
 
         final InitializableCheck initializableCheck3 = new 
InitializableCheck();
         final TestScopeStrategy testScopeStrategy = new TestScopeStrategy();
-        Thread thread = new Thread(new Runnable() {
-            @Override
-            public void run() {
-                ContainerBuilder cb2 = new ContainerBuilder();
-                cb2.factory(EarlyInitializable.class, 
EarlyInitializableBean.class, Scope.SINGLETON);
-                cb2.factory(Initializable.class, InitializableBean.class, 
Scope.SINGLETON);
-                cb2.factory(EarlyInitializable.class, 
"prototypeEarlyInitializable", EarlyInitializableBean.class, Scope.PROTOTYPE);
-                cb2.factory(Initializable.class, "prototypeInitializable", 
InitializableBean.class, Scope.PROTOTYPE);
-                cb2.factory(Initializable.class, "requestInitializable", 
InitializableBean.class, Scope.REQUEST);
-                cb2.factory(Initializable.class, "sessionInitializable", 
InitializableBean.class, Scope.SESSION);
-                cb2.factory(Initializable.class, "threadInitializable", 
InitializableBean.class, Scope.THREAD);
-                cb2.factory(Initializable.class, "wizardInitializable", 
InitializableBean.class, Scope.WIZARD);
-                Container c2 = cb2.create(false);
-                c2.setScopeStrategy(testScopeStrategy);
-                c2.inject(initializableCheck3);
-            }
+        Thread thread = new Thread(() -> {
+            ContainerBuilder cb2 = new ContainerBuilder();
+            cb2.factory(EarlyInitializable.class, 
EarlyInitializableBean.class, Scope.SINGLETON);
+            cb2.factory(Initializable.class, InitializableBean.class, 
Scope.SINGLETON);
+            cb2.factory(EarlyInitializable.class, 
"prototypeEarlyInitializable", EarlyInitializableBean.class, Scope.PROTOTYPE);
+            cb2.factory(Initializable.class, "prototypeInitializable", 
InitializableBean.class, Scope.PROTOTYPE);
+            cb2.factory(Initializable.class, "requestInitializable", 
InitializableBean.class, Scope.REQUEST);
+            cb2.factory(Initializable.class, "sessionInitializable", 
InitializableBean.class, Scope.SESSION);
+            cb2.factory(Initializable.class, "threadInitializable", 
InitializableBean.class, Scope.THREAD);
+            cb2.factory(Initializable.class, "wizardInitializable", 
InitializableBean.class, Scope.WIZARD);
+            Container c2 = cb2.create(false);
+            c2.setScopeStrategy(testScopeStrategy);
+            c2.inject(initializableCheck3);
         });
         thread.run();
         thread.join();
@@ -205,6 +218,32 @@ public class ContainerImplTest {
 
     }
 
+    public static class ConstructorCheck {
+        private String name;
+
+        @Inject("constructorCheck.name")
+        public ConstructorCheck(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
+    public static class OptionalConstructorCheck {
+        private String name;
+
+        @Inject(value = "nonExistingConstant", required = false)
+        public OptionalConstructorCheck(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+
     class InitializableCheck {
 
         private Initializable initializable;

Reply via email to