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

lukaszlenart pushed a commit to branch WW-5641-json-writer-reader-override
in repository https://gitbox.apache.org/repos/asf/struts.git

commit 48c30609292c6776a64d811328a66c367fafcb23
Author: Lukasz Lenart <[email protected]>
AuthorDate: Mon Jul 6 19:27:36 2026 +0200

    WW-5641 fix: resolve JSON writer/reader from constant at runtime
    
    Restore deferred by-name resolution in JSONUtil so struts.json.writer and
    struts.json.reader overrides from an application config are honored again.
    The 7.2.x <bean-selection> alias is chosen at plugin-parse time, before the
    app config is folded in, so it locked the default StrutsJSONWriter/Reader.
    
    Co-Authored-By: Claude Opus 4.8 <[email protected]>
---
 .../java/org/apache/struts2/json/JSONUtil.java     |  9 +++-
 .../apache/struts2/json/CustomTestJSONReader.java  | 38 ++++++++++++++
 .../apache/struts2/json/CustomTestJSONWriter.java  | 50 ++++++++++++++++++
 .../struts2/json/JSONWriterOverrideTest.java       | 60 ++++++++++++++++++++++
 .../src/test/resources/struts-json-override.xml    | 12 +++++
 5 files changed, 168 insertions(+), 1 deletion(-)

diff --git a/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java 
b/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java
index 78bceaacf..541f7a1a9 100644
--- a/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java
+++ b/plugins/json/src/main/java/org/apache/struts2/json/JSONUtil.java
@@ -40,6 +40,7 @@ import java.util.Arrays;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 
+import org.apache.struts2.inject.Container;
 import org.apache.struts2.inject.Inject;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.LogManager;
@@ -63,6 +64,13 @@ public class JSONUtil {
     private JSONWriter writer;
 
     @Inject
+    public void setContainer(Container container) {
+        setWriter(container.getInstance(JSONWriter.class,
+                container.getInstance(String.class, 
JSONConstants.JSON_WRITER)));
+        setReader(container.getInstance(JSONReader.class,
+                container.getInstance(String.class, 
JSONConstants.JSON_READER)));
+    }
+
     public void setReader(JSONReader reader) {
         this.reader = reader;
     }
@@ -71,7 +79,6 @@ public class JSONUtil {
         return reader;
     }
 
-    @Inject
     public void setWriter(JSONWriter writer) {
         this.writer = writer;
     }
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/CustomTestJSONReader.java 
b/plugins/json/src/test/java/org/apache/struts2/json/CustomTestJSONReader.java
new file mode 100644
index 000000000..4a5482357
--- /dev/null
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/CustomTestJSONReader.java
@@ -0,0 +1,38 @@
+/*
+ * 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.struts2.json;
+
+/**
+ * Marker reader proving that a user-configured {@code struts.json.reader} 
override
+ * wins over the default {@link StrutsJSONReader}.
+ */
+public class CustomTestJSONReader implements JSONReader {
+
+    public static final String SENTINEL = "__customReader__";
+
+    @Override
+    public Object read(String string) throws JSONException {
+        return SENTINEL;
+    }
+
+    @Override public void setMaxElements(int maxElements) {}
+    @Override public void setMaxDepth(int maxDepth) {}
+    @Override public void setMaxStringLength(int maxStringLength) {}
+    @Override public void setMaxKeyLength(int maxKeyLength) {}
+}
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/CustomTestJSONWriter.java 
b/plugins/json/src/test/java/org/apache/struts2/json/CustomTestJSONWriter.java
new file mode 100644
index 000000000..9f252ffec
--- /dev/null
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/CustomTestJSONWriter.java
@@ -0,0 +1,50 @@
+/*
+ * 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.struts2.json;
+
+import java.util.Collection;
+import java.util.regex.Pattern;
+
+/**
+ * Marker writer proving that a user-configured {@code struts.json.writer} 
override
+ * wins over the default {@link StrutsJSONWriter}. Emits a sentinel so 
output-level
+ * assertions are unambiguous.
+ */
+public class CustomTestJSONWriter implements JSONWriter {
+
+    public static final String SENTINEL = "{\"__customWriter__\":true}";
+
+    @Override
+    public String write(Object object) throws JSONException {
+        return SENTINEL;
+    }
+
+    @Override
+    public String write(Object object, Collection<Pattern> excludeProperties,
+                        Collection<Pattern> includeProperties,
+                        boolean excludeNullProperties) throws JSONException {
+        return SENTINEL;
+    }
+
+    @Override public void setIgnoreHierarchy(boolean ignoreHierarchy) {}
+    @Override public void setEnumAsBean(boolean enumAsBean) {}
+    @Override public void setDateFormatter(String defaultDateFormat) {}
+    @Override public void setCacheBeanInfo(boolean cacheBeanInfo) {}
+    @Override public void setExcludeProxyProperties(boolean 
excludeProxyProperties) {}
+}
diff --git 
a/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterOverrideTest.java
 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterOverrideTest.java
new file mode 100644
index 000000000..fd36d68b2
--- /dev/null
+++ 
b/plugins/json/src/test/java/org/apache/struts2/json/JSONWriterOverrideTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.struts2.json;
+
+import org.apache.struts2.junit.StrutsTestCase;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Regression test for WW-5641: {@code struts.json.writer} / {@code 
struts.json.reader}
+ * overrides from an application config were ignored on the 7.2.x line.
+ *
+ * <p>Boots the real Dispatcher config chain so the provider ordering that 
causes the bug
+ * (JSON plugin {@code <bean-selection>} running before the app override) is 
reproduced.</p>
+ */
+public class JSONWriterOverrideTest extends StrutsTestCase {
+
+    @Override
+    protected void setupBeforeInitDispatcher() throws Exception {
+        Map<String, String> params = new HashMap<>();
+        params.put("config", 
"struts-default.xml,struts-plugin.xml,struts-json-override.xml");
+        dispatcherInitParams = params;
+    }
+
+    /**
+     * The effective writer used by JSONUtil must be the override, not 
StrutsJSONWriter.
+     */
+    public void testCustomWriterIsUsedBySerialize() throws Exception {
+        JSONUtil jsonUtil = container.getInstance(JSONUtil.class);
+        String output = jsonUtil.serialize(new Object(), false);
+        assertEquals("struts.json.writer override was ignored; default 
StrutsJSONWriter was used",
+                CustomTestJSONWriter.SENTINEL, output);
+    }
+
+    /**
+     * The effective reader used by JSONUtil must be the override, not 
StrutsJSONReader.
+     */
+    public void testCustomReaderIsUsed() {
+        JSONUtil jsonUtil = container.getInstance(JSONUtil.class);
+        assertEquals("struts.json.reader override was ignored; default 
StrutsJSONReader was used",
+                CustomTestJSONReader.class, jsonUtil.getReader().getClass());
+    }
+}
diff --git a/plugins/json/src/test/resources/struts-json-override.xml 
b/plugins/json/src/test/resources/struts-json-override.xml
new file mode 100644
index 000000000..e1ab475da
--- /dev/null
+++ b/plugins/json/src/test/resources/struts-json-override.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE struts PUBLIC
+    "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+    "https://struts.apache.org/dtds/struts-6.0.dtd";>
+<struts>
+    <bean type="org.apache.struts2.json.JSONWriter" name="customTestWriter"
+          class="org.apache.struts2.json.CustomTestJSONWriter" 
scope="prototype"/>
+    <bean type="org.apache.struts2.json.JSONReader" name="customTestReader"
+          class="org.apache.struts2.json.CustomTestJSONReader" 
scope="prototype"/>
+    <constant name="struts.json.writer" value="customTestWriter"/>
+    <constant name="struts.json.reader" value="customTestReader"/>
+</struts>

Reply via email to