davsclaus opened a new pull request, #28985: URL: https://github.com/apache/camel/pull/28985
Fixes [CAMEL-26504](https://issues.apache.org/jira/browse/CAMEL-26504). Follow-up of #28914 (CAMEL-26136), which fixed the plain netty consumer hanging when no reply can be built. ### 1. camel-netty-http - no response when the response cannot be built **Was:** `HttpServerChannelHandler.getResponseBody` calls `NettyHttpBinding.toNettyResponse`. When that throws (for example a reply body that cannot be converted), `ServerChannelHandler.sendResponse` rethrows. Its close-on-failure from #28914 only applies to `protocol=tcp`, and netty-http uses `http`/`https`. So nothing was written, the connection stayed open, and the HTTP client waited until it timed out. **Now:** the failure is passed to the consumer's exception handler (logged at WARN, as before), and the consumer answers with HTTP Status 500, `Connection: close`, `text/plain`. As for a failed exchange, the body is empty with `muteException=true` (the default) and is the stack trace with `muteException=false`. The channel is closed once the response is written. If writing fails, item 2 closes it. **Test:** `NettyHttpResponseCannotBeBuiltTest`: a reply body whose `toString()` throws. Muted: 500, empty body, `Connection: close`. Not muted: 500, and the body has the exception message. Before the fix both tests failed with `SocketTimeoutException: Read timed out` (10s client timeout). ### 2. camel-netty - a failed reply write leaves the channel open **Was:** `ServerResponseFutureListener` only passed the failed write to the exception handler. The channel stayed open unless `disconnect` or the `CamelNettyCloseChannelWhenComplete` header/property said otherwise, so the client waited for a reply that never came. **Now:** on a failed write the channel is closed, except for UDP, where the channel is the consumer's own bound channel (closing it would stop the consumer). The success path (disconnect vs. keep-alive) is unchanged. **Test:** `NettyReplyWriteFailureTest`: a consumer with an object encoder returns a body that is not `Serializable`, so the write fails (`unsupported message type`). The producer (`requestTimeout=10000`) now fails at once with `CamelExchangeException: No response received from remote server`. Before the fix it got `ReadTimeoutException` after the request timeout. ### 3. camel-netty - allowSerializedHeaders ignored on an out-message reply **Was:** with `transferExchange=true`, `NettyPayloadHelper.getIn` marshals with `allowSerializedHeaders`, but `getOut` used `DefaultExchangeHolder.marshal(exchange)`, which never includes serialized values. So a reply set as the out message dropped serializable non-primitive headers, properties and variables, even with `allowSerializedHeaders=true`. A reply set on the in message (`exchange.getMessage()` without an out) already honoured the option. **Now:** `getOut` passes `allowSerializedHeaders` as `getIn` does. **Test:** `NettyTransferExchangeAllowSerializedHeadersTest`: the server sets an `ArrayList` header on the out message. With `allowSerializedHeaders=true` it reaches the producer; with `false` it is still dropped (a String header gets through in both cases). Before the fix the "allowed" test failed (header `null`). ### Docs / upgrade guide - No option or header changed, so no generated files. The `allowSerializedHeaders` description says "headers and properties" without limiting it to the request, so it was left as is. - Upgrade guide 4.24: one new section for camel-netty (close on a failed write; `allowSerializedHeaders` on the out-message reply) and one for camel-netty-http (500 instead of no response). ### Not changed - The 500 fallback writes the stack trace as text even with `transferException=true`. It does not serialize the exception: the response could not be built from the exchange, so the fallback stays minimal. - With `transferExchange=true` and `allowSerializedHeaders=true`, the consumer's own `CamelNettyRemoteAddress` / `CamelNettyLocalAddress` headers (`InetSocketAddress`) are part of the reply. The default deserialization filter of camel-netty's `ObjectDecoder` rejects `java.net` classes, so the client fails to decode such a reply unless the route removes those headers or the filter allows them. This was already true for a reply on the in message. Whether to drop these transport headers from the marshalled exchange is a separate decision; the new test removes them in the route, and the upgrade guide mentions it. ### Test results - camel-netty: `mvn clean install -Psourcecheck`: 149 tests, 0 failures, 9 skipped. - camel-netty-http: `mvn clean install -Psourcecheck`: 361 tests, 0 failures, 10 skipped. _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]
