gnodet commented on code in PR #22358:
URL: https://github.com/apache/camel/pull/22358#discussion_r3049972847
##########
components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java:
##########
@@ -395,16 +395,12 @@ public AccessibleObject getStaticPart() {
private void fillResult(Exchange exchange, Object result) {
LOG.trace("Setting bean invocation result : {}", result);
- // the bean component forces OUT if the MEP is OUT capable
- boolean out = exchange.hasOut() ||
ExchangeHelper.isOutCapable(exchange);
- Message old;
- if (out) {
- old = exchange.getOut();
- // propagate headers
-
exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders());
- } else {
- old = exchange.getIn();
+ // the bean component forces OUT if the MEP is OUT capable;
+ // in.copy() both creates the OUT and propagates headers in one step
+ if (ExchangeHelper.isOutCapable(exchange) &&
!ExchangeHelper.hasResponse(exchange)) {
+ ExchangeHelper.setResponse(exchange, exchange.getIn().copy());
Review Comment:
**Pattern B: `in.copy()` replaces `getOut()` + manual header propagation**
The old code did:
```java
old = exchange.getOut();
exchange.getOut().getHeaders().putAll(exchange.getIn().getHeaders());
```
`in.copy()` achieves both in one step — creates the OUT and propagates all
IN headers/body.
##########
core/camel-support/src/main/java/org/apache/camel/support/DefaultExchangeHolder.java:
##########
@@ -168,9 +169,13 @@ public static void unmarshal(Exchange exchange,
DefaultExchangeHolder payload) {
exchange.getIn().setHeaders(payload.inHeaders);
}
if (payload.outBody != null) {
- exchange.getOut().setBody(payload.outBody);
+ // reuse existing response message to preserve its type (e.g.
JmsMessage)
+ if (!ExchangeHelper.hasResponse(exchange)) {
Review Comment:
**Reuse existing response message to preserve its type**
When unmarshalling a `transferExchange` payload, the OUT message may already
be a specialized type (e.g., `JmsMessage`). The old code unconditionally
replaced it with a `DefaultMessage`, losing the type. Now we only create a new
one if none exists.
##########
core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java:
##########
@@ -1303,4 +1307,36 @@ public static <T> T getBodyAndResetStreamCache(Exchange
exchange, Class<T> type)
return exchange.getMessage().getBody(type);
}
+ /**
+ * Returns true if a response message has been explicitly set on this
exchange.
+ * <p>
+ * This is a non-deprecated equivalent of {@link Exchange#hasOut()},
provided as a utility until a proper
+ * {@code hasResponse()} method is added to the {@link Exchange} API.
+ */
+ public static boolean hasResponse(Exchange exchange) {
+ return exchange.getIn() != exchange.getMessage();
+ }
+
+ /**
Review Comment:
**Foundation: three new utility methods**
These three methods (`hasResponse`, `getResponse`, `setResponse`) centralize
all deprecated `Exchange.hasOut()`/`getOut()`/`setOut()` usage into a single
`@SuppressWarnings("deprecation")` call site.
Key semantic difference from the old API:
- `getResponse()` returns **null** when no OUT exists (unlike `getOut()`
which lazily creates an empty message)
- `hasResponse()` uses identity check (`getIn() != getMessage()`) which is
equivalent to `hasOut()`
- `setResponse()` is a direct wrapper around `setOut()`
##########
core/camel-support/src/main/java/org/apache/camel/support/processor/MarshalProcessor.java:
##########
@@ -68,8 +68,8 @@ public boolean process(Exchange exchange, AsyncCallback
callback) {
// lets setup the out message before we invoke the dataFormat
// so that it can mutate it if necessary
- Message out = exchange.getOut();
- out.copyFrom(in);
+ ExchangeHelper.setResponse(exchange, in.copy());
Review Comment:
**Pattern B: `setResponse(in.copy())` replaces `getOut().copyFrom(in)`**
Mechanically equivalent. The same pattern is used in `UnmarshalProcessor`,
`Enricher.prepareResult()`, `PollEnricher.prepareResult()`, `CamelConverter`,
and `ExchangeHelper.setInOutBodyPatternAware()`.
##########
components/camel-jcr/src/main/java/org/apache/camel/component/jcr/JcrProducer.java:
##########
@@ -66,7 +68,8 @@ public void process(Exchange exchange) throws Exception {
}
}
node.addMixin("mix:referenceable");
- exchange.getOut().setBody(node.getIdentifier());
+ ExchangeHelper.setResponse(exchange, new
DefaultMessage(exchange.getContext()));
Review Comment:
**Pattern D: explicit response creation replaces `getOut().setBody()`**
The old `getOut().setBody(id)` lazily created an empty OUT and set the body.
Now we explicitly create the response. Uses `new DefaultMessage()` (not
`in.copy()`) because the response body (node UUID) is unrelated to the request
body. Same pattern in `CxfRsInvoker`.
##########
components/camel-xpath/src/main/java/org/apache/camel/language/xpath/XPathBuilder.java:
##########
@@ -679,14 +682,19 @@ private XPathFunction createOutBodyFunction() {
return new XPathFunction() {
@SuppressWarnings("rawtypes")
public Object evaluate(List list) throws XPathFunctionException {
- if (exchange.get() != null && exchange.get().hasOut()) {
- return exchange.get().getOut().getBody();
+ if (exchange.get() != null) {
+ Message response =
ExchangeHelper.getResponse(exchange.get());
Review Comment:
**Pattern E + deprecated: `out:body()` / `out:header()` now null-safe**
The old `getOut().getBody()` would lazily create an empty OUT (side effect).
Now `getResponse()` returns null when no OUT exists, and we return null
instead. The getter/setter methods for these functions are also marked
`@Deprecated`.
##########
components/camel-bean/src/main/java/org/apache/camel/language/bean/BeanExpression.java:
##########
@@ -368,15 +369,17 @@ private static Object invokeBean(BeanHolder beanHolder,
String beanName, String
// force to use InOut to retrieve the result on the OUT message
resultExchange.setPattern(ExchangePattern.InOut);
processor.process(resultExchange);
- // the response is always stored in OUT
- result = resultExchange.hasOut() ?
resultExchange.getOut().getBody() : null;
+ // the bean component creates an OUT for non-void methods on
OUT-capable exchanges,
+ // so getResponse() returns null for void methods (no result) and
the OUT for non-void
+ Message response = ExchangeHelper.getResponse(resultExchange);
Review Comment:
**Pattern E: `getResponse()` returns null for void methods**
The bean component only creates an OUT for non-void methods on OUT-capable
exchanges. `getResponse()` returns null when no OUT exists (void method case),
unlike `getOut()` which would have lazily created an empty one. The null check
below handles this correctly.
##########
components/camel-http/src/main/java/org/apache/camel/component/http/HttpProducer.java:
##########
@@ -354,7 +355,9 @@ protected void populateResponse(
HeaderFilterStrategy strategy, int responseCode)
throws IOException, ClassNotFoundException {
- Message answer = exchange.getOut();
+ // separate response from request so response headers don't mix with
request headers
+ ExchangeHelper.setResponse(exchange, new
DefaultMessage(exchange.getContext()));
Review Comment:
**Pattern D: explicit `new DefaultMessage()` to isolate response from
request**
Uses an empty message (not `in.copy()`) so that HTTP response headers don't
mix with request headers. This preserves the old `getOut()` behavior which also
created an empty message.
##########
components/camel-netty/src/main/java/org/apache/camel/component/netty/handlers/ClientChannelHandler.java:
##########
@@ -257,10 +254,14 @@ protected Message getResponseMessage(Exchange exchange,
ChannelHandlerContext ct
// set the result on either IN or OUT on the original exchange
depending on its pattern
if (ExchangeHelper.isOutCapable(exchange)) {
- NettyPayloadHelper.setOut(exchange, body);
- return exchange.getOut();
+ // DefaultExchangeHolder unmarshals its own OUT, so only
pre-create one for normal payloads
+ if (!(body instanceof DefaultExchangeHolder)) {
Review Comment:
**Pattern D with guard: skip pre-creation for `DefaultExchangeHolder`**
When `transferExchange=true`, the body is a `DefaultExchangeHolder` whose
`unmarshal()` sets up its own OUT message. Pre-creating one here would be
overwritten. For normal payloads, we create OUT from `in.copy()` so
`setPayload()` populates the response via `getMessage()`.
##########
components/camel-xslt/src/main/java/org/apache/camel/component/xslt/XsltBuilder.java:
##########
@@ -489,7 +490,11 @@ protected void configureTransformer(Transformer
transformer, Exchange exchange)
addParameters(transformer, getParameters());
transformer.setParameter("exchange", exchange);
transformer.setParameter("in", exchange.getIn());
- transformer.setParameter("out", exchange.getOut());
+ // only set "out" param if a response exists; avoids creating an empty
OUT as side effect
+ Message response = ExchangeHelper.getResponse(exchange);
Review Comment:
**Pattern E: conditional parameter avoids side-effect OUT creation**
The old code always called `exchange.getOut()` which lazily created an empty
OUT as a side effect. Now we only set the `"out"` transformer parameter if a
response actually exists.
##########
core/camel-support/src/main/java/org/apache/camel/support/ExchangeHelper.java:
##########
@@ -442,7 +442,11 @@ private static void copyFromOutMessage(Exchange result,
Exchange source, boolean
*/
public static Message getResultMessage(Exchange exchange) {
if (exchange.getPattern().isOutCapable()) {
- return exchange.getOut();
+ // explicitly create response if none exists (preserves old
getOut() lazy-creation semantics)
+ if (!hasResponse(exchange)) {
Review Comment:
**Explicit response creation preserves `getOut()` lazy-creation semantics**
`getResultMessage()` is the one place where we intentionally want
lazy-creation behavior (callers expect a non-null writable message). We
preserve this by explicitly creating a response if none exists.
##########
components/camel-jms/src/main/java/org/apache/camel/component/jms/JmsProducer.java:
##########
@@ -474,10 +475,9 @@ protected Destination resolveOrCreateDestination(String
destinationName, Session
}
protected void setMessageId(Exchange exchange) {
- if (exchange.hasOut()) {
- JmsMessage out = exchange.getOut(JmsMessage.class);
+ if (ExchangeHelper.getResponse(exchange) instanceof JmsMessage out) {
Review Comment:
**Pattern E: `instanceof` replaces `hasOut()` + `getOut(Class)`**
`getResponse()` returns null when no OUT exists, and `instanceof` naturally
handles null (evaluates to false). This is more concise than the old `hasOut()`
guard + cast. Same pattern in `SjmsProducer.setMessageId()`.
--
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]