This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch CAMEL-26129-dfdl-null-body in repository https://gitbox.apache.org/repos/asf/camel.git
commit 6752c4a660f89cfbd1510dc3e901649d9442fe91 Author: Claus Ibsen <[email protected]> AuthorDate: Mon Nov 2 16:48:43 2026 +0100 CAMEL-26129: camel-dfdl - fail clearly on a null or Map body and give parse errors a message The dfdl endpoint read the body with getBody(Document.class) and getBody(byte[].class), so a null or Map body reached Daffodil as null and failed with a NullPointerException. It now uses getMandatoryBody, which fails with an InvalidPayloadException. DfdlParseException and DfdlUnparseException passed no message to super, so a parse error was logged as "null". The message is now built from the Daffodil diagnostics. Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Claus Ibsen <[email protected]> --- .../apache/camel/component/dfdl/DfdlEndpoint.java | 4 +-- .../camel/component/dfdl/DfdlParseException.java | 22 +++++++++++++++ .../camel/component/dfdl/DfdlUnparseException.java | 1 + .../camel/component/dfdl/DfdlComponentTest.java | 32 ++++++++++++++++++++++ .../camel/dataformat/dfdl/DfdlDataFormatTest.java | 6 ++++ 5 files changed, 63 insertions(+), 2 deletions(-) diff --git a/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlEndpoint.java b/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlEndpoint.java index a432c47e2ec7..b1d632136b39 100644 --- a/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlEndpoint.java +++ b/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlEndpoint.java @@ -113,7 +113,7 @@ public class DfdlEndpoint extends ProcessorEndpoint { @Override protected void onExchange(Exchange exchange) throws Exception { if (getParseDirection() == ParseDirection.UNPARSE) { - Document xmlDocument = exchange.getIn().getBody(Document.class); + Document xmlDocument = exchange.getIn().getMandatoryBody(Document.class); W3CDOMInfosetInputter inputter = new W3CDOMInfosetInputter(xmlDocument); ByteArrayOutputStream bos = new ByteArrayOutputStream(); UnparseResult result = this.daffodilProcessor.unparse(inputter, Channels.newChannel(bos)); @@ -123,7 +123,7 @@ public class DfdlEndpoint extends ProcessorEndpoint { } exchange.getMessage().setBody(bos); } else { - byte[] binary = exchange.getIn().getBody(byte[].class); + byte[] binary = exchange.getIn().getMandatoryBody(byte[].class); var inputStream = new InputSourceDataInputStream(binary); var outputter = new W3CDOMInfosetOutputter(); ParseResult result = this.daffodilProcessor.parse(inputStream, outputter); diff --git a/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlParseException.java b/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlParseException.java index a0e0ee9c66f7..03039884f446 100644 --- a/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlParseException.java +++ b/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlParseException.java @@ -16,16 +16,38 @@ */ package org.apache.camel.component.dfdl; +import java.util.List; +import java.util.StringJoiner; + +import org.apache.daffodil.japi.Diagnostic; import org.apache.daffodil.japi.ParseResult; +import org.apache.daffodil.japi.WithDiagnostics; public class DfdlParseException extends Exception { private final ParseResult result; public DfdlParseException(ParseResult result) { + super(diagnosticsMessage("DFDL parse failed", result)); this.result = result; } public ParseResult getParseResult() { return this.result; } + + /** + * Builds the exception message from the diagnostics of the parse or unparse result, so the error is not logged as + * null. + */ + static String diagnosticsMessage(String prefix, WithDiagnostics result) { + List<Diagnostic> diagnostics = result != null ? result.getDiagnostics() : null; + if (diagnostics == null || diagnostics.isEmpty()) { + return prefix; + } + StringJoiner joiner = new StringJoiner("; ", prefix + ": ", ""); + for (Diagnostic d : diagnostics) { + joiner.add(d.getMessage()); + } + return joiner.toString(); + } } diff --git a/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlUnparseException.java b/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlUnparseException.java index c6da63d1fc40..489a71166ae6 100644 --- a/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlUnparseException.java +++ b/components/camel-dfdl/src/main/java/org/apache/camel/component/dfdl/DfdlUnparseException.java @@ -22,6 +22,7 @@ public class DfdlUnparseException extends Exception { private final UnparseResult result; public DfdlUnparseException(UnparseResult result) { + super(DfdlParseException.diagnosticsMessage("DFDL unparse failed", result)); this.result = result; } diff --git a/components/camel-dfdl/src/test/java/org/apache/camel/component/dfdl/DfdlComponentTest.java b/components/camel-dfdl/src/test/java/org/apache/camel/component/dfdl/DfdlComponentTest.java index 787fd6ad0e92..b1336d725fad 100644 --- a/components/camel-dfdl/src/test/java/org/apache/camel/component/dfdl/DfdlComponentTest.java +++ b/components/camel-dfdl/src/test/java/org/apache/camel/component/dfdl/DfdlComponentTest.java @@ -18,6 +18,7 @@ package org.apache.camel.component.dfdl; import java.io.BufferedReader; import java.io.InputStreamReader; +import java.util.Map; import java.util.stream.Collectors; import javax.xml.transform.stream.StreamSource; @@ -25,6 +26,7 @@ import javax.xml.transform.stream.StreamSource; import org.w3c.dom.Document; import org.apache.camel.EndpointInject; +import org.apache.camel.InvalidPayloadException; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.junit6.CamelTestSupport; @@ -96,6 +98,9 @@ public class DfdlComponentTest extends CamelTestSupport { .map(Diagnostic::getMessage) .collect(Collectors.joining("\n")); assertTrue(diagString.contains("initiator 'ISA' not found")); + assertNotNull(exception.getMessage()); + assertTrue(exception.getMessage().startsWith("DFDL parse failed: "), exception.getMessage()); + assertTrue(exception.getMessage().contains("initiator 'ISA' not found"), exception.getMessage()); } @Test @@ -113,6 +118,33 @@ public class DfdlComponentTest extends CamelTestSupport { .collect(Collectors.joining("\n")); assertTrue(diagString.contains("Expected element start event for {}X12_837P")); assertTrue(diagString.contains("{}Unexpected")); + assertNotNull(exception.getMessage()); + assertTrue(exception.getMessage().startsWith("DFDL unparse failed: "), exception.getMessage()); + assertTrue(exception.getMessage().contains("Expected element start event for {}X12_837P"), exception.getMessage()); + } + + @Test + public void testParseNullBody() { + var exchange = context.createFluentProducerTemplate().to("direct:parse").withBody(null).send(); + assertInstanceOf(InvalidPayloadException.class, exchange.getException()); + } + + @Test + public void testParseMapBody() { + var exchange = context.createFluentProducerTemplate().to("direct:parse").withBody(Map.of("foo", "bar")).send(); + assertInstanceOf(InvalidPayloadException.class, exchange.getException()); + } + + @Test + public void testUnparseNullBody() { + var exchange = context.createFluentProducerTemplate().to("direct:unparse").withBody(null).send(); + assertInstanceOf(InvalidPayloadException.class, exchange.getException()); + } + + @Test + public void testUnparseMapBody() { + var exchange = context.createFluentProducerTemplate().to("direct:unparse").withBody(Map.of("foo", "bar")).send(); + assertInstanceOf(InvalidPayloadException.class, exchange.getException()); } @Override diff --git a/components/camel-dfdl/src/test/java/org/apache/camel/dataformat/dfdl/DfdlDataFormatTest.java b/components/camel-dfdl/src/test/java/org/apache/camel/dataformat/dfdl/DfdlDataFormatTest.java index 817a28890411..868e08d9c23c 100644 --- a/components/camel-dfdl/src/test/java/org/apache/camel/dataformat/dfdl/DfdlDataFormatTest.java +++ b/components/camel-dfdl/src/test/java/org/apache/camel/dataformat/dfdl/DfdlDataFormatTest.java @@ -98,6 +98,9 @@ public class DfdlDataFormatTest extends CamelTestSupport { .map(Diagnostic::getMessage) .collect(Collectors.joining("\n")); assertTrue(diagString.contains("initiator 'ISA' not found")); + assertNotNull(exception.getMessage()); + assertTrue(exception.getMessage().startsWith("DFDL parse failed: "), exception.getMessage()); + assertTrue(exception.getMessage().contains("initiator 'ISA' not found"), exception.getMessage()); } @Test @@ -115,6 +118,9 @@ public class DfdlDataFormatTest extends CamelTestSupport { .collect(Collectors.joining("\n")); assertTrue(diagString.contains("Expected element start event for {}X12_837P")); assertTrue(diagString.contains("{}Unexpected")); + assertNotNull(exception.getMessage()); + assertTrue(exception.getMessage().startsWith("DFDL unparse failed: "), exception.getMessage()); + assertTrue(exception.getMessage().contains("Expected element start event for {}X12_837P"), exception.getMessage()); } @Override
