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
