This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch fix/CAMEL-24579
in repository https://gitbox.apache.org/repos/asf/camel.git

commit d8041dd812fef8d41465829ac800649c6aa4db23
Author: Claus Ibsen <[email protected]>
AuthorDate: Tue Sep 1 10:44:36 2026 +0200

    CAMEL-24579: DataFormat.marshal graph parameter should be @Nullable
    
    MarshalProcessor passes the message body straight to DataFormat.marshal
    without a null guard, and Message.getBody() is itself @Nullable. The
    graph parameter had no matching @Nullable, so under org.apache.camel.spi's
    @NullMarked contract it was implicitly non-null. Java implementations
    never noticed, but a Kotlin implementation gets a compiler-generated
    non-null assertion that throws NullPointerException whenever the body
    is legitimately null.
    
    Co-Authored-By: Claude <[email protected]>
    Signed-off-by: Claus Ibsen <[email protected]>
---
 .../src/main/java/org/apache/camel/spi/DataFormat.java      |  7 +++++--
 .../modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc     | 13 +++++++++++++
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/DataFormat.java 
b/core/camel-api/src/main/java/org/apache/camel/spi/DataFormat.java
index 013fa823fcc7..ebf732db125e 100644
--- a/core/camel-api/src/main/java/org/apache/camel/spi/DataFormat.java
+++ b/core/camel-api/src/main/java/org/apache/camel/spi/DataFormat.java
@@ -24,6 +24,7 @@ import org.apache.camel.Exchange;
 import org.apache.camel.Message;
 import org.apache.camel.Service;
 import org.apache.camel.util.IOHelper;
+import org.jspecify.annotations.Nullable;
 
 /**
  * Pluggable strategy for converting message bodies to and from a serialised 
byte-stream format, as described in the
@@ -48,11 +49,13 @@ public interface DataFormat extends Service {
      * Marshals the object to the given Stream.
      *
      * @param  exchange  the current exchange
-     * @param  graph     the object to be marshalled
+     * @param  graph     the object to be marshalled, can be <tt>null</tt> if 
the message body is null (for example on
+     *                   an error route) or if the implementation marshals 
from the exchange rather than from this
+     *                   parameter
      * @param  stream    the output stream to write the marshalled result to
      * @throws Exception can be thrown
      */
-    void marshal(Exchange exchange, Object graph, OutputStream stream) throws 
Exception;
+    void marshal(Exchange exchange, @Nullable Object graph, OutputStream 
stream) throws Exception;
 
     /**
      * Unmarshals the given stream into an object.
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 387bcd0afffb..cfb623b2e3ad 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -155,6 +155,19 @@ The component camel-threadpoolfactory-vertx was deprecated 
in 4.21. The componen
 
 `camel-zeebe` component was deprecated in 4.19 and has a straightforward 
replacement with `camel-camunda`. It is removed in 4.23.
 
+=== camel-core - DataFormat.marshal graph parameter is now @Nullable
+
+`org.apache.camel.spi.DataFormat#marshal(Exchange, Object, OutputStream)` now 
declares its `graph`
+parameter `@Nullable`, matching what `MarshalProcessor` actually passes: the 
message body, which is
+itself `@Nullable` and can be null (for example on an error route, or for a 
`DataFormat` that
+marshals from `Exchange` state rather than from `graph`).
+
+This is a contract-only correction; `MarshalProcessor`'s runtime behavior is 
unchanged. Java
+implementations are unaffected. A Kotlin implementation of `DataFormat` 
previously had to accept a
+non-null `graph`, so the Kotlin compiler emitted a non-null assertion that 
threw `NullPointerException`
+whenever a null body reached `marshal`. Kotlin implementations can now declare 
`graph: Any?` directly
+instead of working around the assertion with a Java bridge class.
+
 === camel-core - MemoryIdempotentRepository and MemoryAggregationRepository 
deprecated
 
 `MemoryIdempotentRepository` and `MemoryAggregationRepository` are deprecated 
in favor of the new

Reply via email to