shashank created CAMEL-25249:
--------------------------------

             Summary: camel-vertx - a request/reply over the event bus gets a 
successful reply (usually its own request) when the consumer route fails, and 
no reply at all when the route ends without a body
                 Key: CAMEL-25249
                 URL: https://issues.apache.org/jira/browse/CAMEL-25249
             Project: Camel
          Issue Type: Bug
          Components: camel-vertx
            Reporter: shashank


{{VertxConsumer}} handles an event bus message that expects a reply 
({{replyAddress() != null}}) as an {{InOut}} exchange and, when the exchange is 
done, does:

{code:java}
if (reply) {
    Object body = exchange.getMessage().getBody();
    if (body != null) {
        event.reply(body);
    }
}
{code}

Two consequences:

# *A failed route answers with a successful reply.* The exception of the 
exchange is ignored, and the reply carries whatever the message body is at that 
point; when the route fails before changing the body, the sender gets its own 
request back as the answer. A Camel sender ({{to("vertx:address")}} with 
{{InOut}}) sees no exception at all; a Vert.x verticle using 
{{eventBus.request(...)}} gets a {{succeeded()}} result. Errors are silently 
turned into wrong answers.
# *No body, no reply.* When the route ends with a {{null}} body, nothing is 
sent and the sender waits until its reply timeout (30 seconds by default, 
{{ReplyException(TIMEOUT)}}), although the route completed.

Vert.x has {{Message.fail(failureCode, message)}} for the first case (the 
sender gets a {{ReplyException}} with {{ReplyFailure.RECIPIENT_FAILURE}}), and 
a {{null}} body is a valid reply. The code has been like this since 
request/reply support was added (CAMEL-7176, 2014); nothing in the history or 
the docs says the failure case is intended.

h3. Reproduction

{code:java}
from("direct:fail").to("vertx:foo.fail");
from("vertx:foo.fail").throwException(new IllegalArgumentException("Forced"));

from("direct:empty").to("vertx:foo.empty");
from("vertx:foo.empty").setBody(constant(null));
{code}

{{template.request("direct:fail", ...)}} returns an exchange without exception 
(the body is the request); {{template.request("direct:empty", ...)}} fails 
after 30 seconds with {{(TIMEOUT,-1) Timed out after waiting 30000(ms) for a 
reply}}. A unit test with both fails on main.

h3. Proposed fix

When the exchange failed, reply with {{event.fail(500, "Exchange processing 
failed")}}: the exception of the route is not sent to the sender (the security 
model's rule for consumers that reply, see {{muteException}} in 
CAMEL-24476/24477/24478/25087), it stays with the route's error handler. 
Otherwise always reply with the body, also when it is {{null}}. An exception 
handled by {{onException(...).handled(true)}} is not an exchange failure, so 
its response is replied as before. The camel-vertx suite passes (31 tests). The 
behaviour seen by senders changes, so the change gets an upgrade guide note.

Affected: 4.14.x, 4.18.x and main (same code).

Duplicate check (2026-10-01): JIRA component camel-vertx (all 25 issues) and 
text "vertx" with "reply": nothing about failed or empty replies (CAMEL-7176 
added the feature). GitHub pull requests "vertx reply": none.

_Filed with Claude Code on behalf of allthingssecurity._




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to