This is an automated email from the ASF dual-hosted git repository.

davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 019d995fc32 CAMEL-21176: DefaultExchangeHolder - Also store exchange 
variables together with exchange properties (#15437)
019d995fc32 is described below

commit 019d995fc32f81181e5bf85018d873bb7508cb01
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Sep 5 06:35:17 2024 +0200

    CAMEL-21176: DefaultExchangeHolder - Also store exchange variables together 
with exchange properties (#15437)
---
 .../camel/impl/DefaultExchangeHolderTest.java      |   8 +-
 .../camel/support/DefaultExchangeHolder.java       | 121 ++++++++++++++-------
 .../ROOT/pages/camel-4x-upgrade-guide-4_8.adoc     |   3 +
 3 files changed, 90 insertions(+), 42 deletions(-)

diff --git 
a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java
index 409b421196f..824d6416959 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/impl/DefaultExchangeHolderTest.java
@@ -57,6 +57,8 @@ public class DefaultExchangeHolderTest extends 
ContextTestSupport {
         assertEquals("Bye World", exchange.getOut().getBody());
         assertEquals(123, exchange.getIn().getHeader("foo"));
         assertNull(exchange.getProperty("bar"));
+        assertNull(exchange.getProperty("myVar"));
+        assertNull(exchange.getProperty("myOtherVar"));
     }
 
     @Test
@@ -71,6 +73,8 @@ public class DefaultExchangeHolderTest extends 
ContextTestSupport {
         assertEquals("Hi Camel", exchange.getIn().getHeader("CamelFoo"));
         assertEquals(444, exchange.getProperty("bar"));
         assertEquals(555, exchange.getProperty("CamelBar"));
+        assertEquals(666, exchange.getVariable("myVar"));
+        assertEquals("cheese", exchange.getVariable("myOtherVar"));
         assertEquals(id, exchange.getExchangeId());
     }
 
@@ -184,8 +188,10 @@ public class DefaultExchangeHolderTest extends 
ContextTestSupport {
         exchange.getIn().setHeader("CamelFoo", "Hi Camel");
         exchange.setProperty("bar", 444);
         exchange.setProperty("CamelBar", 555);
+        exchange.setVariable("myVar", 666);
+        exchange.setVariable("myOtherVar", "cheese");
         exchange.getOut().setBody("Bye World");
-        return DefaultExchangeHolder.marshal(exchange, includeProperties);
+        return DefaultExchangeHolder.marshal(exchange, includeProperties, 
false);
     }
 
     private static final class MyFoo {
diff --git 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchangeHolder.java
 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchangeHolder.java
index 80577d0c3e7..768c09c18b4 100644
--- 
a/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchangeHolder.java
+++ 
b/core/camel-support/src/main/java/org/apache/camel/support/DefaultExchangeHolder.java
@@ -43,7 +43,6 @@ import org.slf4j.LoggerFactory;
  * <li>exchangeId</li>
  * <li>in body</li>
  * <li>out body</li>
- * <li>fault body</li>
  * <li>exception</li>
  * </ul>
  * <br/>
@@ -53,12 +52,12 @@ import org.slf4j.LoggerFactory;
  * <ul>
  * <li>in headers</li>
  * <li>out headers</li>
- * <li>fault headers</li>
  * </ul>
- * The body is serialized and stored as serialized bytes. The header and 
exchange properties only include primitive,
- * String, and Number types (and Exception types for exchange properties). Any 
other type is skipped. Any message body
- * object that is not serializable will be skipped and Camel will log this at 
<tt>WARN</tt> level. And any message
- * header values that is not a primitive value will be skipped and Camel will 
log this at <tt>DEBUG</tt> level.
+ * The body is serialized and stored as serialized bytes. The header and 
exchange properties, exchange variables are
+ * only include primitive, String, and Number types (and Exception types for 
exchange properties). Any other type is
+ * skipped. Any message body object that is not serializable will be skipped 
and Camel will log this at <tt>WARN</tt>
+ * level. And any message header values that is not a primitive value will be 
skipped and Camel will log this at
+ * <tt>DEBUG</tt> level.
  */
 public class DefaultExchangeHolder implements Serializable {
 
@@ -71,11 +70,14 @@ public class DefaultExchangeHolder implements Serializable {
     private Map<String, Object> inHeaders;
     private Map<String, Object> outHeaders;
     private Map<String, Object> properties;
+    private Map<String, Object> variables;
     private Exception exception;
 
     /**
      * Creates a payload object with the information from the given exchange.
      *
+     * Exchange properties and variables is included. Serialized values are 
skipped.
+     *
      * @param  exchange the exchange, must <b>not</b> be <tt>null</tt>
      * @return          the holder object with information copied form the 
exchange
      */
@@ -84,10 +86,10 @@ public class DefaultExchangeHolder implements Serializable {
     }
 
     /**
-     * Creates a payload object with the information from the given exchange.
+     * Creates a payload object with the information from the given exchange. 
Serialized values are skipped.
      *
      * @param  exchange          the exchange, must <b>not</b> be <tt>null</tt>
-     * @param  includeProperties whether or not to include exchange properties
+     * @param  includeProperties whether or not to include exchange properties 
and variables
      * @return                   the holder object with information copied 
form the exchange
      */
     public static DefaultExchangeHolder marshal(Exchange exchange, boolean 
includeProperties) {
@@ -97,27 +99,27 @@ public class DefaultExchangeHolder implements Serializable {
     /**
      * Creates a payload object with the information from the given exchange.
      *
-     * @param  exchange               the exchange, must <b>not</b> be 
<tt>null</tt>
-     * @param  includeProperties      whether or not to include exchange 
properties
-     * @param  allowSerializedHeaders whether or not to include serialized 
headers
-     * @return                        the holder object with information 
copied form the exchange
+     * @param  exchange              the exchange, must <b>not</b> be 
<tt>null</tt>
+     * @param  includeProperties     whether or not to include exchange 
properties and variables
+     * @param  allowSerializedValues whether or not to include serialized 
values
+     * @return                       the holder object with information copied 
form the exchange
      */
-    public static DefaultExchangeHolder marshal(Exchange exchange, boolean 
includeProperties, boolean allowSerializedHeaders) {
-        return marshal(exchange, includeProperties, allowSerializedHeaders, 
true);
+    public static DefaultExchangeHolder marshal(Exchange exchange, boolean 
includeProperties, boolean allowSerializedValues) {
+        return marshal(exchange, includeProperties, allowSerializedValues, 
true);
     }
 
     /**
      * Creates a payload object with the information from the given exchange.
      *
-     * @param  exchange               the exchange, must <b>not</b> be 
<tt>null</tt>
-     * @param  includeProperties      whether or not to include exchange 
properties
-     * @param  allowSerializedHeaders whether or not to include serialized 
headers
-     * @param  preserveExchangeId     whether to preserve exchange id
-     * @return                        the holder object with information 
copied form the exchange
+     * @param  exchange              the exchange, must <b>not</b> be 
<tt>null</tt>
+     * @param  includeProperties     whether or not to include exchange 
properties and variables
+     * @param  allowSerializedValues whether or not to include serialized 
headers
+     * @param  preserveExchangeId    whether to preserve exchange id
+     * @return                       the holder object with information copied 
form the exchange
      */
     public static DefaultExchangeHolder marshal(
             Exchange exchange, boolean includeProperties,
-            boolean allowSerializedHeaders, boolean preserveExchangeId) {
+            boolean allowSerializedValues, boolean preserveExchangeId) {
         ObjectHelper.notNull(exchange, "exchange");
 
         // we do not support files
@@ -134,13 +136,14 @@ public class DefaultExchangeHolder implements 
Serializable {
             payload.exchangeId = exchange.getExchangeId();
         }
         payload.inBody = checkSerializableBody("in body", exchange, 
exchange.getIn().getBody());
-        payload.safeSetInHeaders(exchange, allowSerializedHeaders);
+        payload.safeSetInHeaders(exchange, allowSerializedValues);
         if (exchange.hasOut()) {
             payload.outBody = checkSerializableBody("out body", exchange, 
exchange.getOut().getBody());
-            payload.safeSetOutHeaders(exchange, allowSerializedHeaders);
+            payload.safeSetOutHeaders(exchange, allowSerializedValues);
         }
         if (includeProperties) {
-            payload.safeSetProperties(exchange, allowSerializedHeaders);
+            payload.safeSetProperties(exchange, allowSerializedValues);
+            payload.safeSetVariables(exchange, allowSerializedValues);
         }
         payload.exception = exchange.getException();
 
@@ -175,6 +178,11 @@ public class DefaultExchangeHolder implements Serializable 
{
                 exchange.setProperty(entry.getKey(), entry.getValue());
             }
         }
+        if (payload.variables != null) {
+            for (Map.Entry<String, Object> entry : 
payload.variables.entrySet()) {
+                exchange.setVariable(entry.getKey(), entry.getValue());
+            }
+        }
         exchange.setException(payload.exception);
     }
 
@@ -198,12 +206,33 @@ public class DefaultExchangeHolder implements 
Serializable {
         payload.properties.put(key, property);
     }
 
+    /**
+     * Adds a variable to the payload.
+     * <p/>
+     * This can be done in special situations where additional information 
must be added which was not provided from the
+     * source.
+     *
+     * @param payload  the serialized payload
+     * @param key      the variable key to add
+     * @param variable the variable value to add
+     */
+    public static void addVariable(DefaultExchangeHolder payload, String key, 
Serializable variable) {
+        if (key == null || variable == null) {
+            return;
+        }
+        if (payload.variables == null) {
+            payload.variables = new LinkedHashMap<>();
+        }
+        payload.variables.put(key, variable);
+    }
+
     @Override
     public String toString() {
         StringBuilder sb = new 
StringBuilder("DefaultExchangeHolder[exchangeId=").append(exchangeId);
         sb.append("inBody=").append(inBody).append(", 
outBody=").append(outBody);
         sb.append(", inHeaders=").append(inHeaders).append(", 
outHeaders=").append(outHeaders);
-        sb.append(", properties=").append(properties).append(", 
exception=").append(exception);
+        sb.append(", properties=").append(properties).append(", 
variables=").append(variables);
+        sb.append(", exception=").append(exception);
         return sb.append(']').toString();
     }
 
@@ -219,10 +248,10 @@ public class DefaultExchangeHolder implements 
Serializable {
     }
 
     @Deprecated(since = "3.0.0")
-    private Map<String, Object> safeSetOutHeaders(Exchange exchange, boolean 
allowSerializedHeaders) {
+    private Map<String, Object> safeSetOutHeaders(Exchange exchange, boolean 
allowSerializedValues) {
         if (exchange.hasOut() && exchange.getOut().hasHeaders()) {
             Map<String, Object> map
-                    = checkValidHeaderObjects("out headers", exchange, 
exchange.getOut().getHeaders(), allowSerializedHeaders);
+                    = checkValidHeaderObjects("out headers", exchange, 
exchange.getOut().getHeaders(), allowSerializedValues);
             if (map != null && !map.isEmpty()) {
                 outHeaders = new LinkedHashMap<>(map);
             }
@@ -230,16 +259,25 @@ public class DefaultExchangeHolder implements 
Serializable {
         return null;
     }
 
-    private Map<String, Object> safeSetProperties(Exchange exchange, boolean 
allowSerializedHeaders) {
+    private Map<String, Object> safeSetProperties(Exchange exchange, boolean 
allowSerializedValues) {
         // also include the internal properties
         Map<String, Object> map = 
checkValidExchangePropertyObjects("properties", exchange, 
exchange.getAllProperties(),
-                allowSerializedHeaders);
+                allowSerializedValues);
         if (map != null && !map.isEmpty()) {
             properties = new LinkedHashMap<>(map);
         }
         return null;
     }
 
+    private Map<String, Object> safeSetVariables(Exchange exchange, boolean 
allowSerializedValues) {
+        Map<String, Object> map = 
checkValidExchangePropertyObjects("variables", exchange, 
exchange.getVariables(),
+                allowSerializedValues);
+        if (map != null && !map.isEmpty()) {
+            variables = new LinkedHashMap<>(map);
+        }
+        return null;
+    }
+
     private static Object checkSerializableBody(String type, Exchange 
exchange, Object object) {
         if (object == null) {
             return null;
@@ -287,7 +325,7 @@ public class DefaultExchangeHolder implements Serializable {
     }
 
     private static Map<String, Object> checkValidExchangePropertyObjects(
-            String type, Exchange exchange, Map<String, Object> map, boolean 
allowSerializedHeaders) {
+            String type, Exchange exchange, Map<String, Object> map, boolean 
allowSerializedValues) {
         if (map == null) {
             return null;
         }
@@ -300,7 +338,7 @@ public class DefaultExchangeHolder implements Serializable {
                 continue;
             }
 
-            Object value = getValidExchangePropertyValue(entry.getKey(), 
entry.getValue(), allowSerializedHeaders);
+            Object value = getValidExchangePropertyValue(entry.getKey(), 
entry.getValue(), allowSerializedValues);
             if (value != null) {
                 Serializable converted
                         = 
exchange.getContext().getTypeConverter().convertTo(Serializable.class, 
exchange, value);
@@ -331,12 +369,12 @@ public class DefaultExchangeHolder implements 
Serializable {
      *
      * We make possible store serialized headers by the boolean field 
allowSerializedHeaders
      *
-     * @param  headerName             the header name
-     * @param  headerValue            the header value
-     * @param  allowSerializedHeaders the header value
-     * @return                        the value to use, <tt>null</tt> to 
ignore this header
+     * @param  headerName            the header name
+     * @param  headerValue           the header value
+     * @param  allowSerializedValues whether to include serialized values
+     * @return                       the value to use, <tt>null</tt> to ignore 
this header
      */
-    protected static Object getValidHeaderValue(String headerName, Object 
headerValue, boolean allowSerializedHeaders) {
+    protected static Object getValidHeaderValue(String headerName, Object 
headerValue, boolean allowSerializedValues) {
         if (headerValue instanceof String) {
             return headerValue;
         } else if (headerValue instanceof BigInteger) {
@@ -353,7 +391,7 @@ public class DefaultExchangeHolder implements Serializable {
             return headerValue;
         } else if (headerValue instanceof Date) {
             return headerValue;
-        } else if (allowSerializedHeaders) {
+        } else if (allowSerializedValues) {
             if (headerValue instanceof Serializable) {
                 return headerValue;
             }
@@ -368,17 +406,18 @@ public class DefaultExchangeHolder implements 
Serializable {
      * This default implementation will allow the same values as {@link 
#getValidHeaderValue(String, Object, boolean)}
      * and in addition any value of type {@link Throwable}.
      *
-     * @param  propertyName  the property name
-     * @param  propertyValue the property value
-     * @return               the value to use, <tt>null</tt> to ignore this 
header
+     * @param  propertyName          the property name
+     * @param  propertyValue         the property value
+     * @param  allowSerializedValues whether to include serialized values
+     * @return                       the value to use, <tt>null</tt> to ignore 
this header
      */
     protected static Object getValidExchangePropertyValue(
-            String propertyName, Object propertyValue, boolean 
allowSerializedHeaders) {
+            String propertyName, Object propertyValue, boolean 
allowSerializedValues) {
         // for exchange properties we also allow exception to be transferred 
so people can store caught exception
         if (propertyValue instanceof Throwable) {
             return propertyValue;
         }
-        return getValidHeaderValue(propertyName, propertyValue, 
allowSerializedHeaders);
+        return getValidHeaderValue(propertyName, propertyValue, 
allowSerializedValues);
     }
 
     private static void logCannotSerializeObject(String type, String key, 
Object value) {
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc
index 48a4f932f16..1df7e49bce5 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_8.adoc
@@ -25,6 +25,9 @@ performing these copies has increased from 4096 bytes to 
16384 bytes (the defaul
 The tracer (`BacklogTracer`) has changed the `backlogSize` default value from 
`1000` to `100`, and `maxBodySize` from `128kb` to `32kb`.
 This reduces the amount of data captured and stored and helps reduce the 
tracing overhead.
 
+The `org.apache.camel.support.DefaultExchangeHolder` will now include both 
exchange variables and properties,
+if the parameter `includeProperties` is set to true.
+
 === camel-jbang
 
 The `camel trace` command has changed to show tracing status (by default). To 
dump traced messages use `camel trace --action=dump`.

Reply via email to