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

Reply via email to