From 7490add2585f42391b07d44a19b7cb7f788796ed Mon Sep 17 00:00:00 2001 From: Kamil Krzywannski Date: Sat, 11 Jul 2026 21:36:53 +0200 Subject: [PATCH] Include free-form message when encoding StructuredDataMessage to XML StructuredDataMessage.asXml omitted the constructor message field. Encode it as a distinct element so it is not conflated with a map entry keyed "message". Fixes #4141. --- .../message/StructuredDataMessageTest.java | 38 ++++++++++++++++++- .../log4j/message/StructuredDataMessage.java | 9 +++++ .../fix-StructuredDataMessage-XML-message.xml | 12 ++++++ 3 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/changelog/.2.x.x/fix-StructuredDataMessage-XML-message.xml diff --git a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java index 3d3f403bef7..4d1a1d416d6 100644 --- a/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java +++ b/log4j-api-test/src/test/java/org/apache/logging/log4j/message/StructuredDataMessageTest.java @@ -64,6 +64,7 @@ void testMsgXml() { final String expected = "\n" + "Alert\n" + "MsgId@12345\n" + + "Test message {}\n" + "\n" + " This is a very long test memo to prevent regression of LOG4J2-114\n" + " Test message {}\n" @@ -73,12 +74,45 @@ void testMsgXml() { assertEquals(expected, result); } + @Test + void testMsgXmlIncludesConstructorMessage() { + // #4141: constructor message must appear (and be escaped) even when not put into the map + final StructuredDataMessage msg = new StructuredDataMessage("an id", "a & more", "a type"); + final String result = msg.getFormattedMessage(new String[] {"XML"}); + final String expected = "\n" + + "a type\n" + + "an id\n" + + "a <msg> & more\n" + + "\n" + + "\n" + + "\n"; + assertEquals(expected, result); + } + + @Test + void testMsgXmlDistinguishesConstructorMessageFromMapEntry() { + // #4141: free-form message and a map entry keyed "message" are independent + final StructuredDataMessage msg = new StructuredDataMessage("an id", "a message", "a type"); + msg.put("message", "foo"); + final String result = msg.getFormattedMessage(new String[] {"XML"}); + final String expected = "\n" + + "a type\n" + + "an id\n" + + "a message\n" + + "\n" + + " foo\n" + + "\n" + + "\n"; + assertEquals(expected, result); + } + @Test void testXmlEncodingOfIdAndType1() { final String id = "i<&d>" + XmlFixture.TEXT; final String type = "t>yp) final String actualXml = - new StructuredDataMessage(id, "discarded message", type).getFormattedMessage(new String[] {"XML"}); + new StructuredDataMessage(id, null, type).getFormattedMessage(new String[] {"XML"}); final String expectedXml = "\n" + "t>yp<e&" + XmlFixture.ENCODED_TEXT + "\n" @@ -101,7 +135,7 @@ void testXmlEncodingOfIdAndType2() { final StructuredDataId id = new StructuredDataId(idName, idEnterpriseNumber, idRequired, idOptional, Integer.MAX_VALUE); final String actualXml = - new StructuredDataMessage(id, "discarded message", type).getFormattedMessage(new String[] {"XML"}); + new StructuredDataMessage(id, null, type).getFormattedMessage(new String[] {"XML"}); final String expectedXml = "\n" + "t>yp<e&" + XmlFixture.ENCODED_TEXT + "\n" diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java b/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java index 69fa3fb8cbe..748c975c5ac 100644 --- a/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java +++ b/log4j-api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java @@ -373,6 +373,15 @@ private void asXml(final StructuredDataId structuredDataId, final StringBuilder StringBuilders.escapeXml(sb, start); sb.append("\n"); + // Encode message as its own element (distinct from a map entry keyed "message") + if (message != null) { + sb.append(""); + start = sb.length(); + sb.append(message); + StringBuilders.escapeXml(sb, start); + sb.append("\n"); + } + // Encode the rest super.asXml(sb); diff --git a/src/changelog/.2.x.x/fix-StructuredDataMessage-XML-message.xml b/src/changelog/.2.x.x/fix-StructuredDataMessage-XML-message.xml new file mode 100644 index 00000000000..dbe0c90340d --- /dev/null +++ b/src/changelog/.2.x.x/fix-StructuredDataMessage-XML-message.xml @@ -0,0 +1,12 @@ + + + + + Include the free-form `message` field when encoding `StructuredDataMessage` to XML + +