This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch holder in repository https://gitbox.apache.org/repos/asf/camel.git
commit 67e623ac7d5beab539670e5a6e2af8998e54462f Author: Claus Ibsen <[email protected]> AuthorDate: Wed Sep 4 21:31:38 2024 +0200 CAMEL-21176: DefaultExchangeHolder - Also store exchange variables together with exchange properties --- .../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`.
