You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/10/03 08:16:54 UTC

(camel) branch main updated: CAMEL-25279: camel-knative - a consumer without reply must not answer 204 when the exchange failed (#27308)

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

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 91bae2d98372 CAMEL-25279: camel-knative - a consumer without reply must not answer 204 when the exchange failed (#27308)
91bae2d98372 is described below

commit 91bae2d983729a5018aeb4830d6bd332325af969
Author: allthingssecurity <49...@users.noreply.github.com>
AuthorDate: Sat Oct 3 13:46:47 2026 +0530

    CAMEL-25279: camel-knative - a consumer without reply must not answer 204 when the exchange failed (#27308)
    
    With `reply=false` the Knative HTTP consumer never has a response body, and without a body it always set `204 No Content`, overwriting the 500 it had just computed for a failed exchange. Knative takes a 2xx answer as a delivered event, so an event whose route failed was not retried (nor sent to a dead letter sink). CAMEL-24428 fixed the same overwrite for `muteException` with `reply=true`.
    This change: without a body the consumer sets 204 only when the exchange did not fail; a failed exchange keeps its error status, with an empty body. The upgrade guide for 4.23 gets a short note.
    
    Co-Authored-By: Claude Opus 5.5 <no...@anthropic.com>
---
 .../knative/http/KnativeHttpConsumer.java          |  6 +++-
 .../component/knative/http/KnativeHttpTest.java    | 39 ++++++++++++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc    |  6 ++++
 3 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
index 2688d5ebd18c..47edde4d5c75 100644
--- a/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
+++ b/components/camel-knative/camel-knative-http/src/main/java/org/apache/camel/component/knative/http/KnativeHttpConsumer.java
@@ -261,7 +261,11 @@ public class KnativeHttpConsumer extends DefaultConsumer {
                                 if (body != null) {
                                     request.response().end(body);
                                 } else {
-                                    request.response().setStatusCode(204);
+                                    // 204 tells the caller that the event has been delivered: a failed exchange
+                                    // without reply keeps its error status, so that the event is sent again
+                                    if (!exchange.isFailed()) {
+                                        request.response().setStatusCode(204);
+                                    }
                                     request.response().end();
                                 }
                             } catch (Exception e) {
diff --git a/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java b/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
index c9080f3c5893..16b049875743 100644
--- a/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
+++ b/components/camel-knative/camel-knative-http/src/test/java/org/apache/camel/component/knative/http/KnativeHttpTest.java
@@ -1399,6 +1399,45 @@ public class KnativeHttpTest {
                 .body(is(emptyOrNullString()));
     }
 
+    /**
+     * Without a reply the consumer answers 204 No Content, which tells Knative that the event has been delivered: a
+     * failed exchange must keep its error status, or the event is lost.
+     */
+    @ParameterizedTest
+    @EnumSource(CloudEvents.class)
+    void testNoReplyFailure(CloudEvent ce) throws Exception {
+        configureKnativeComponent(
+                context,
+                ce,
+                sourceChannel(
+                        "channel",
+                        Map.of(
+                                Knative.KNATIVE_CLOUD_EVENT_TYPE, "org.apache.camel.event",
+                                Knative.CONTENT_TYPE, "text/plain")));
+
+        RouteBuilder.addRoutes(context, b -> {
+            b.from("knative:channel/channel?reply=false")
+                    .throwException(new IllegalStateException("Forced"));
+        });
+
+        context.start();
+
+        given()
+                .body("test")
+                .header(Exchange.CONTENT_TYPE, "text/plain")
+                .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_VERSION), ce.version())
+                .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TYPE), "org.apache.camel.event")
+                .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_ID), "myEventID")
+                .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_TIME),
+                        DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now()))
+                .header(httpAttribute(ce, CloudEvent.CAMEL_CLOUD_EVENT_SOURCE), "/somewhere")
+                .when()
+                .post()
+                .then()
+                .statusCode(500)
+                .body(is(emptyOrNullString()));
+    }
+
     @ParameterizedTest
     @EnumSource(CloudEvents.class)
     void testNoReplyMeta(CloudEvent ce) throws Exception {
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 de469765b4f5..c1a368e51a05 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
@@ -2156,6 +2156,12 @@ Deployments that relied on the previous behaviour — a development cluster with
 certificate, for example — must either configure a truststore or set `camel.knative.client.ssl.trust.all`
 explicitly. `KnativeOidcClientOptions` extends this class and is affected the same way.
 
+A Knative consumer with `reply=false` now answers a failed exchange with its error status instead of `204 No Content`.
+
+Such a consumer answered `204 No Content` to every request, also when the route failed, so Knative took the event as
+delivered and did not send it again. A failed exchange now keeps its status (500, or the `CamelHttpResponseCode`
+header the route set) with an empty body, as with `reply=true`. Successful exchanges still get `204 No Content`.
+
 === camel-paho
 
 When `automaticReconnect=true` and the MQTT broker reconnects, the consumer now restarts the route