mirror of
https://github.com/apache/struts.git
synced 2026-08-31 19:35:40 +00:00
WW-5641 Restore struts.json.writer / struts.json.reader override in JSON plugin (#1766)
* WW-5641 docs: design spec for JSON writer/reader override regression Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WW-5641 docs: implementation plan for JSON writer/reader override fix Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * WW-5641 fix: run JSON bean-selection from struts-deferred.xml The JSON plugin declared <bean-selection> in struts-plugin.xml, which runs at plugin-parse time, before the application struts.xml is folded in. That froze the JSONWriter/JSONReader default binding to StrutsJSONWriter/Reader, so struts.json.writer / struts.json.reader overrides were ignored. Move the element to struts-deferred.xml, which Dispatcher loads last (after the app config and core's StrutsBeanSelectionProvider), so the alias honors the override. Mirrors the velocity plugin. JSONUtil is unchanged from main. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
|
||||
"https://struts.apache.org/dtds/struts-6.0.dtd">
|
||||
|
||||
<struts>
|
||||
|
||||
<bean-selection name="jsonBeans" class="org.apache.struts2.json.JSONBeanSelectionProvider"/>
|
||||
|
||||
</struts>
|
||||
@@ -64,6 +64,4 @@
|
||||
</interceptors>
|
||||
|
||||
</package>
|
||||
|
||||
<bean-selection name="jsonBeans" class="org.apache.struts2.json.JSONBeanSelectionProvider"/>
|
||||
</struts>
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
// Limit setters are intentionally ignored: this marker always returns SENTINEL.
|
||||
@Override public void setMaxElements(int maxElements) { /* no-op marker */ }
|
||||
@Override public void setMaxDepth(int maxDepth) { /* no-op marker */ }
|
||||
@Override public void setMaxStringLength(int maxStringLength) { /* no-op marker */ }
|
||||
@Override public void setMaxKeyLength(int maxKeyLength) { /* no-op marker */ }
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
// Configuration setters are intentionally ignored: this marker always emits SENTINEL.
|
||||
@Override public void setIgnoreHierarchy(boolean ignoreHierarchy) { /* no-op marker */ }
|
||||
@Override public void setEnumAsBean(boolean enumAsBean) { /* no-op marker */ }
|
||||
@Override public void setDateFormatter(String defaultDateFormat) { /* no-op marker */ }
|
||||
@Override public void setCacheBeanInfo(boolean cacheBeanInfo) { /* no-op marker */ }
|
||||
@Override public void setExcludeProxyProperties(boolean excludeProxyProperties) { /* no-op marker */ }
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 because the JSON
|
||||
* plugin's {@code <bean-selection>} ran at plugin-parse time, before the app config.
|
||||
* Moving it to {@code struts-deferred.xml} makes it run last, so the override wins.
|
||||
*
|
||||
* <p>Boots the real Dispatcher chain. {@code struts-deferred.xml} is loaded unconditionally
|
||||
* by {@code Dispatcher.init()} after the {@code config} chain, so it is intentionally omitted
|
||||
* from the config init param below.</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 default JSONWriter binding must resolve to the app override, not StrutsJSONWriter.
|
||||
*/
|
||||
public void testCustomWriterWinsAsDefaultBinding() {
|
||||
JSONWriter writer = container.getInstance(JSONWriter.class);
|
||||
assertEquals("struts.json.writer override was ignored; default StrutsJSONWriter was used",
|
||||
CustomTestJSONWriter.class, writer.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* The default JSONReader binding must resolve to the app override, not StrutsJSONReader.
|
||||
*/
|
||||
public void testCustomReaderWinsAsDefaultBinding() {
|
||||
JSONReader reader = container.getInstance(JSONReader.class);
|
||||
assertEquals("struts.json.reader override was ignored; default StrutsJSONReader was used",
|
||||
CustomTestJSONReader.class, reader.getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* End-to-end: the writer JSONUtil actually serializes with must be the override.
|
||||
*/
|
||||
public void testJSONUtilUsesCustomWriter() throws Exception {
|
||||
JSONUtil jsonUtil = container.getInstance(JSONUtil.class);
|
||||
assertEquals(CustomTestJSONWriter.SENTINEL, jsonUtil.serialize(new Object(), false));
|
||||
}
|
||||
|
||||
/**
|
||||
* End-to-end: the reader JSONUtil exposes must be the override.
|
||||
*/
|
||||
public void testJSONUtilUsesCustomReader() {
|
||||
JSONUtil jsonUtil = container.getInstance(JSONUtil.class);
|
||||
assertEquals(CustomTestJSONReader.class, jsonUtil.getReader().getClass());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
-->
|
||||
<!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>
|
||||
Reference in New Issue
Block a user