davsclaus opened a new pull request, #28914: URL: https://github.com/apache/camel/pull/28914
Fixes [CAMEL-26136](https://issues.apache.org/jira/browse/CAMEL-26136). ### 1. A failed exchange gets no reply with the default codec ### 2. A reply that is not a String is dropped and the client waits **What was wrong:** with the default codec (no `textline`, no custom `encoders`/`decoders`) the only encoder is netty's `StringEncoder`. A reply that was not a `String` (the muted `Exception` of a failed exchange, bytes, a stream, a file, a `Map`, a POJO) passed through it unencoded, the write failed, `ServerResponseFutureListener` only logged it, and the client waited (forever without `requestTimeout`). **What changed:** - `NettyConfiguration` records when it installed the default String codec (`isDefaultStringCodec()`, no new option). - `ServerChannelHandler` converts such a reply to a `String` with the type converter before writing it, the same as the textline path. A `ByteBuf` reply is passed on as before. The conversion is skipped with `transferExchange=true` and when a custom `serverInitializerFactory` builds the pipeline (camel-netty-http sets one, so it is not affected). - When the reply body cannot be built or converted, the consumer now closes the TCP channel (not the UDP server channel), so the client does not wait for a reply that never comes. The exception still goes to the consumer's exception handler. **Security:** the failed-exchange reply is the `muteException` stand-in, so the client receives `java.lang.Exception: Exchange processing failed`, exactly what textline clients already get. Only `toString()` is used (class and message), never the stack trace. The route's exception is only sent with `muteException=false`, which is an opt-in. ### 3. With useByteBuf=true a File, Map or POJO body is skipped silently **What was wrong:** `NettyPayloadHelper.getIn` used `getBody(ByteBuf.class)`, which returns null for a body that cannot be converted. The producer then logged "No payload to send" and completed the exchange without error. Also, `getOut` (used for a consumer reply set as the out message, the common case) ignored `useByteBuf` altogether. **What changed:** `getIn` and `getOut` share one helper that uses `getMandatoryBody(ByteBuf.class)` when the body is not null. The exchange now fails with `InvalidPayloadException`. A null body still means "no payload", as before. Both methods now declare `InvalidPayloadException`. The only callers are in camel-netty. ### 4. With sync=false the producer still sets the server's reply on the exchange **What was wrong:** with `sync=false`, `NettyProducer` calls the callback once the request is written, but `ClientChannelHandler.channelRead0` still set a reply that came later on that exchange. It then also called `state.callbackDoneOnce`, which ran the producer callback a second time. Before the fix, the test log shows `Error returning channel to pool ... Object has already been returned to this pool`. **What changed:** `ClientChannelHandler.channelRead0` ignores received messages (logged at DEBUG) when the producer is not `sync`. ### Tests - `NettyDefaultCodecReplyTest`: failed exchange (muted and `muteException=false`), `Map` reply and `byte[]` reply over the default codec. All 4 failed before the fix with `ReadTimeoutException`. - `NettyUseByteBufTest`: a POJO body fails the producer exchange (before the fix: nothing thrown). A consumer reply that cannot be converted closes the channel, so the client gets "No response received" at once (before the fix: `ReadTimeoutException` after 5s). A String body is still sent. - `NettyProducerSyncFalseReplyTest`: the body after a `sync=false` producer stays the request (before the fix: `Bye World`, the server's reply). - Full camel-netty suite: 146 tests, 0 failures (9 skipped, as on main). The camel-netty-http suite (359 tests) also passes against this change. No camel-netty-http file is changed. ### Docs - `netty-component.adoc` (and its catalog copy): default-codec reply conversion, `useByteBuf` failure, `sync=false` ignoring replies. - Upgrade guide 4.24: new section "camel-netty - replies with the default codec, useByteBuf and sync=false", next to the existing camel-netty section. - No option, header or generated configurer changed. ### Not changed - `ServerResponseFutureListener` still only logs a failed write and does not close the channel. camel-netty-http shares it, and with the conversion above the default codec no longer fails the write. - The producer side with the default codec and a non-String request already fails the exchange on the failed write. It is not silent, so it is left as is. _Claude Code on behalf of Claus Ibsen (davsclaus)_ 🤖 Generated with [Claude Code](https://claude.com/claude-code) -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
