davsclaus commented on code in PR #28500:
URL: https://github.com/apache/camel/pull/28500#discussion_r4376263352
##########
core/camel-support/src/main/java/org/apache/camel/support/BodyFacts.java:
##########
@@ -277,6 +284,42 @@ private static String unmarshalFirst(Exchange exchange,
Object body) {
};
}
+ /**
+ * When a marshal wrote the body from a Map or a List, as the message
history says: the marshal is wanted, for a
+ * later step that needs text (a file write), and the field is read after
it, too late; an unmarshal would undo it.
+ * Null when the history does not say so, as for a marshal of text, where
an unmarshal was meant.
+ */
+ private static String marshalledData(Exchange exchange, Object body) {
+ List<MessageHistory> history =
exchange.getProperty(ExchangePropertyKey.MESSAGE_HISTORY, List.class);
+ if (history == null || history.isEmpty()) {
+ return null;
+ }
+ String now = ObjectHelper.classCanonicalName(body);
+ for (int i = history.size() - 1; i >= 0; i--) {
+ MessageHistory step = history.get(i);
+ String type = step.getBodyType();
+ if (type == null || type.equals(now)) {
+ continue;
+ }
+ // the step that set the body, and the body it was reached with
+ if (step.getNode() == null ||
!"marshal".equals(step.getNode().getShortName())
+ || !isDataType(exchange.getContext(), type)) {
+ return null;
+ }
+ return "the " + step(step.getNode()) + " wrote it from data (" +
StringHelper.afterLast(type, ".", type)
+ + "): read the field before the marshal, for example into a
variable with setVariable, or keep the data"
+ + " in the body and marshal into a variable (marshal with
variableReceive, and send that variable with"
+ + " variableSend)";
+ }
+ return null;
+ }
+
+ /** Whether a class, by its name, is a Map or a collection. */
+ private static boolean isDataType(CamelContext context, String type) {
+ Class<?> clazz = context != null ?
context.getClassResolver().resolveClass(type) : null;
Review Comment:
A correction to my earlier reply: the lookup was broken, but not for the
reason raised. The message history keeps the body type as `getCanonicalName()`.
For a nested class this name has `.` where the class name has `$`, so no class
loader can find it, on any runtime. A body from `Map.of`, `List.of`,
`Arrays.asList` or `Collections.unmodifiableMap` was never recognised as data,
and got the "unmarshal it first" hint instead.
Fixed in ee83e7a5ae56 without loading any class.
`DefaultMessageHistory.captureBody` now records whether the body is a Map or a
collection when it captures the body, and `BodyFacts` reads that flag. Every
history factory (default, micrometer, metrics, opentelemetry-metrics) extends
`DefaultMessageHistory` and calls `captureBody`. `BodyFactsTest` now has
`Map.of` and `List.of` cases, which fail without the fix.
_Claude Code on behalf of davsclaus_
--
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]