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]

Reply via email to