This is an automated email from the ASF dual-hosted git repository. lukaszlenart pushed a commit to branch WW-5749-6x in repository https://gitbox.apache.org/repos/asf/struts.git
commit 30c24f5c6dc4dfbc21979607fb28db3732d3ae81 Author: Lukasz Lenart <[email protected]> AuthorDate: Wed Sep 16 19:41:54 2026 +0200 WW-5749 fix(rest): write nothing from the XML handlers when there is no target RestActionInvocation hands the content-type handler a null target for a clean POST, PUT or DELETE under restrictToGet and for a bare HTTP-status result code. JacksonXmlHandler and JuneauXmlHandler dereferenced it, and the NullPointerException that invoke() caught became a 500 whose XML body was the serialised exception. Both now return early on a null target, as XStreamHandler already does, so the client gets the intended status with an empty body. (cherry picked from commit c89ee1bd8f0416eedcc3ed43ca0a430b24b095a9) Co-Authored-By: Claude Opus 5 (1M context) <[email protected]> --- .../java/org/apache/struts2/rest/handler/JacksonXmlHandler.java | 3 +++ .../java/org/apache/struts2/rest/handler/JuneauXmlHandler.java | 3 +++ .../org/apache/struts2/rest/handler/JacksonXmlHandlerTest.java | 8 ++++++++ .../org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java | 8 ++++++++ 4 files changed, 22 insertions(+) diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonXmlHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonXmlHandler.java index 66d5c2a37..0ed8bcac2 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonXmlHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JacksonXmlHandler.java @@ -45,6 +45,9 @@ public class JacksonXmlHandler extends AbstractContentTypeHandler { } public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException { + if (obj == null) { + return null; + } LOG.debug("Converting an object of {} into string", obj.getClass().getName()); mapper.writeValue(stream, obj); return null; diff --git a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JuneauXmlHandler.java b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JuneauXmlHandler.java index 379c97a82..a64bdd0a6 100644 --- a/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JuneauXmlHandler.java +++ b/plugins/rest/src/main/java/org/apache/struts2/rest/handler/JuneauXmlHandler.java @@ -57,6 +57,9 @@ public class JuneauXmlHandler extends AbstractContentTypeHandler { } public String fromObject(ActionInvocation invocation, Object obj, String resultCode, Writer stream) throws IOException { + if (obj == null) { + return null; + } LOG.debug("Converting an object of {} into string", obj.getClass().getName()); try { serializer diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JacksonXmlHandlerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JacksonXmlHandlerTest.java index 40b6ad9a4..eb9b3eeb1 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JacksonXmlHandlerTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JacksonXmlHandlerTest.java @@ -52,6 +52,14 @@ public class JacksonXmlHandlerTest extends XWorkTestCase { ai = new MockActionInvocation(); } + public void testNullTargetWritesNothing() throws Exception { + Writer stream = new StringWriter(); + + handler.fromObject(ai, null, null, stream); + + assertThat(stream.toString()).isEmpty(); + } + public void testObjectToXml() throws Exception { // given SimpleBean obj = new SimpleBean(); diff --git a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java index 55351d63d..e6f9e29fd 100644 --- a/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java +++ b/plugins/rest/src/test/java/org/apache/struts2/rest/handler/JuneauXmlHandlerTest.java @@ -55,6 +55,14 @@ public class JuneauXmlHandlerTest extends XWorkTestCase { ((MockActionInvocation) ai).setInvocationContext(context); } + public void testNullTargetWritesNothing() throws Exception { + Writer stream = new StringWriter(); + + handler.fromObject(ai, null, null, stream); + + assertThat(stream.toString()).isEmpty(); + } + public void testObjectToXml() throws Exception { // given SimpleBean obj = new SimpleBean();
