This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch att in repository https://gitbox.apache.org/repos/asf/camel.git
commit 349043f69d0a2070d1651baa430a845aaef5d009 Author: Claus Ibsen <[email protected]> AuthorDate: Mon Feb 24 11:53:46 2025 +0100 CAMEL-21755: Adjust attachments API on Message to avoid issue during routing --- .../camel/attachment/AttachmentConverter.java | 2 - .../attachment/AttachmentExpressionBuilder.java | 115 ++++++++++----------- .../apache/camel/attachment/AttachmentMessage.java | 21 ++-- .../camel/attachment/CSimpleAttachmentHelper.java | 44 ++++---- .../camel/attachment/DefaultAttachmentMessage.java | 28 +++-- .../component/jetty12/AttachmentHttpBinding.java | 7 +- .../apache/camel/component/mail/MailConsumer.java | 8 -- .../component/mail/SplitAttachmentsExpression.java | 2 +- .../component/mail/MailAttachmentNamesTest.java | 5 +- .../component/servlet/AttachmentHttpBinding.java | 3 +- .../undertow/DefaultUndertowHttpBinding.java | 3 +- .../src/main/java/org/apache/camel/Message.java | 9 +- .../apache/camel/trait/message/MessageTrait.java | 9 +- .../org/apache/camel/support/AbstractExchange.java | 11 +- .../org/apache/camel/support/DefaultMessage.java | 21 +--- .../org/apache/camel/support/MessageSupport.java | 27 +++-- .../apache/camel/support/MessageHelperTest.java | 14 +-- .../ROOT/pages/camel-4x-upgrade-guide-4_10.adoc | 20 ++++ .../ROOT/pages/camel-4x-upgrade-guide-4_11.adoc | 20 ++++ 19 files changed, 196 insertions(+), 173 deletions(-) diff --git a/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentConverter.java b/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentConverter.java index 9fcf132a725..bfe3b0e81d4 100644 --- a/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentConverter.java +++ b/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentConverter.java @@ -37,8 +37,6 @@ public final class AttachmentConverter { answer = am; } else { answer = new DefaultAttachmentMessage(message); - // need to wrap exchange message as attachment capable - message.getExchange().setMessage(answer); } return answer; } diff --git a/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentExpressionBuilder.java b/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentExpressionBuilder.java index d86f06e6664..fbdda092088 100644 --- a/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentExpressionBuilder.java +++ b/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentExpressionBuilder.java @@ -30,14 +30,21 @@ import static org.apache.camel.support.builder.ExpressionBuilder.simpleExpressio public class AttachmentExpressionBuilder { + private static AttachmentMessage toAttachmentMessage(Exchange exchange) { + AttachmentMessage answer; + if (exchange.getMessage() instanceof AttachmentMessage am) { + answer = am; + } else { + answer = new DefaultAttachmentMessage(exchange.getMessage()); + } + return answer; + } + public static Expression attachments() { return new ExpressionAdapter() { @Override public Object evaluate(Exchange exchange) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - return am.getAttachments(); - } - return null; + return toAttachmentMessage(exchange).getAttachments(); } }; } @@ -46,10 +53,7 @@ public class AttachmentExpressionBuilder { return new ExpressionAdapter() { @Override public Object evaluate(Exchange exchange) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - return am.getAttachments().size(); - } - return 0; + return toAttachmentMessage(exchange).getAttachments().size(); } }; } @@ -60,20 +64,18 @@ public class AttachmentExpressionBuilder { @Override public Object evaluate(Exchange exchange) { - Object answer = null; - if (exchange.getMessage() instanceof AttachmentMessage am) { - var dh = am.getAttachment(key); + Object answer; + var dh = toAttachmentMessage(exchange).getAttachment(key); + try { + answer = dh.getContent(); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (answer != null && clazz != null) { try { - answer = dh.getContent(); - } catch (Exception e) { - throw new RuntimeException(e); - } - if (answer != null && clazz != null) { - try { - answer = exchange.getContext().getTypeConverter().mandatoryConvertTo(clazz, answer); - } catch (NoTypeConversionAvailableException e) { - throw CamelExecutionException.wrapCamelExecutionException(exchange, e); - } + answer = exchange.getContext().getTypeConverter().mandatoryConvertTo(clazz, answer); + } catch (NoTypeConversionAvailableException e) { + throw CamelExecutionException.wrapCamelExecutionException(exchange, e); } } return answer; @@ -99,16 +101,14 @@ public class AttachmentExpressionBuilder { @Override public Object evaluate(Exchange exchange) { Object answer = null; - if (exchange.getMessage() instanceof AttachmentMessage am) { - var ao = am.getAttachmentObject(key); - if (ao != null) { - answer = ao.getHeader(name); - if (answer != null && clazz != null) { - try { - answer = exchange.getContext().getTypeConverter().mandatoryConvertTo(clazz, answer); - } catch (NoTypeConversionAvailableException e) { - throw CamelExecutionException.wrapCamelExecutionException(exchange, e); - } + var ao = toAttachmentMessage(exchange).getAttachmentObject(key); + if (ao != null) { + answer = ao.getHeader(name); + if (answer != null && clazz != null) { + try { + answer = exchange.getContext().getTypeConverter().mandatoryConvertTo(clazz, answer); + } catch (NoTypeConversionAvailableException e) { + throw CamelExecutionException.wrapCamelExecutionException(exchange, e); } } } @@ -132,11 +132,9 @@ public class AttachmentExpressionBuilder { return new ExpressionAdapter() { @Override public Object evaluate(Exchange exchange) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - var dh = am.getAttachment(key); - if (dh != null) { - return dh.getContentType(); - } + var dh = toAttachmentMessage(exchange).getAttachment(key); + if (dh != null) { + return dh.getContentType(); } return null; } @@ -164,15 +162,12 @@ public class AttachmentExpressionBuilder { return new ExpressionAdapter() { @Override public Object evaluate(Exchange exchange) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - String key = attachmentName.evaluate(exchange, String.class); - Object answer = am.getAttachment(key); - if (mandatory && answer == null) { - throw RuntimeCamelException.wrapRuntimeCamelException(new NoSuchAttachmentException(exchange, key)); - } - return answer; + String key = attachmentName.evaluate(exchange, String.class); + Object answer = toAttachmentMessage(exchange).getAttachment(key); + if (mandatory && answer == null) { + throw RuntimeCamelException.wrapRuntimeCamelException(new NoSuchAttachmentException(exchange, key)); } - return null; + return answer; } @Override @@ -198,27 +193,25 @@ public class AttachmentExpressionBuilder { return new SimpleExpressionBuilder.KeyedOgnlExpressionAdapter( ognl, "attachmentOgnl(" + ognl + ")", (exchange, exp) -> { - if (exchange.getMessage() instanceof AttachmentMessage am) { - String text = exp.evaluate(exchange, String.class); - var dh = am.getAttachment(text); - if (dh == null && ObjectHelper.isNumber(text)) { - try { - // fallback to lookup by numeric index - int idx = Integer.parseInt(text); - if (idx < am.getAttachments().size()) { - var it = am.getAttachments().values().iterator(); - for (int i = 0; i < idx; i++) { - it.next(); - } - dh = it.next(); + String text = exp.evaluate(exchange, String.class); + var am = toAttachmentMessage(exchange); + var dh = am.getAttachment(text); + if (dh == null && ObjectHelper.isNumber(text)) { + try { + // fallback to lookup by numeric index + int idx = Integer.parseInt(text); + if (idx < am.getAttachments().size()) { + var it = am.getAttachments().values().iterator(); + for (int i = 0; i < idx; i++) { + it.next(); } - } catch (NumberFormatException e) { - // ignore + dh = it.next(); } + } catch (NumberFormatException e) { + // ignore } - return dh; } - return null; + return dh; }); } diff --git a/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentMessage.java b/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentMessage.java index 44240d265e7..4a910993ddf 100644 --- a/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentMessage.java +++ b/components/camel-attachments/src/main/java/org/apache/camel/attachment/AttachmentMessage.java @@ -28,12 +28,6 @@ import org.apache.camel.Message; */ public interface AttachmentMessage extends Message { - /** - * The {@link AttachmentMessage} will wrap the previous {@link Message} and this method gives access to the previous - * message instance. - */ - Message getDelegateMessage(); - /** * Returns the attachment specified by the id * @@ -81,16 +75,20 @@ public interface AttachmentMessage extends Message { void addAttachmentObject(String id, Attachment content); /** - * Returns all attachments of the message + * Returns all attachments of the message. + * <p/> + * To add or remove attachments then use the APIs from this message, as the returned map is a read-only instance. * - * @return the attachments in a map or <tt>null</tt> + * @return the attachments in a read-only map */ Map<String, DataHandler> getAttachments(); /** * Returns all attachments of the message + * <p/> + * To add or remove attachments then use the APIs from this message, as the returned map is a read-only instance. * - * @return the attachments in a map or <tt>null</tt> + * @return the attachments in a read-only map */ Map<String, Attachment> getAttachmentObjects(); @@ -115,4 +113,9 @@ public interface AttachmentMessage extends Message { */ boolean hasAttachments(); + /** + * Clears all the attachments. + */ + void clearAttachments(); + } diff --git a/components/camel-attachments/src/main/java/org/apache/camel/attachment/CSimpleAttachmentHelper.java b/components/camel-attachments/src/main/java/org/apache/camel/attachment/CSimpleAttachmentHelper.java index 1252657eadd..b6caaefb121 100644 --- a/components/camel-attachments/src/main/java/org/apache/camel/attachment/CSimpleAttachmentHelper.java +++ b/components/camel-attachments/src/main/java/org/apache/camel/attachment/CSimpleAttachmentHelper.java @@ -24,31 +24,33 @@ import org.apache.camel.Exchange; public class CSimpleAttachmentHelper { - public static Map<String, DataHandler> attachments(Exchange exchange) { + private static AttachmentMessage toAttachmentMessage(Exchange exchange) { + AttachmentMessage answer; if (exchange.getMessage() instanceof AttachmentMessage am) { - return am.getAttachments(); + answer = am; + } else { + answer = new DefaultAttachmentMessage(exchange.getMessage()); } - return null; + return answer; + } + + public static Map<String, DataHandler> attachments(Exchange exchange) { + return toAttachmentMessage(exchange).getAttachments(); } public static int attachmentsSize(Exchange exchange) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - return am.getAttachments().size(); - } - return 0; + return toAttachmentMessage(exchange).getAttachments().size(); } public static Object attachmentContent(Exchange exchange, String key) throws Exception { - if (exchange.getMessage() instanceof AttachmentMessage am) { - var dh = am.getAttachments().get(key); - if (dh != null) { - return dh.getContent(); - } + var dh = toAttachmentMessage(exchange).getAttachments().get(key); + if (dh != null) { + return dh.getContent(); } return null; } - public static Object attachmentContentAsText(Exchange exchange, String key) throws Exception { + public static String attachmentContentAsText(Exchange exchange, String key) throws Exception { Object data = attachmentContent(exchange, key); if (data != null) { return exchange.getContext().getTypeConverter().convertTo(String.class, exchange, data); @@ -65,21 +67,17 @@ public class CSimpleAttachmentHelper { } public static String attachmentContentType(Exchange exchange, String key) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - var dh = am.getAttachments().get(key); - if (dh != null) { - return dh.getContentType(); - } + var dh = toAttachmentMessage(exchange).getAttachments().get(key); + if (dh != null) { + return dh.getContentType(); } return null; } public static String attachmentHeader(Exchange exchange, String key, String name) { - if (exchange.getMessage() instanceof AttachmentMessage am) { - var ao = am.getAttachmentObjects().get(key); - if (ao != null) { - return ao.getHeader(name); - } + var ao = toAttachmentMessage(exchange).getAttachmentObjects().get(key); + if (ao != null) { + return ao.getHeader(name); } return null; } diff --git a/components/camel-attachments/src/main/java/org/apache/camel/attachment/DefaultAttachmentMessage.java b/components/camel-attachments/src/main/java/org/apache/camel/attachment/DefaultAttachmentMessage.java index 49fdb908c73..fb31dfb2837 100644 --- a/components/camel-attachments/src/main/java/org/apache/camel/attachment/DefaultAttachmentMessage.java +++ b/components/camel-attachments/src/main/java/org/apache/camel/attachment/DefaultAttachmentMessage.java @@ -16,6 +16,7 @@ */ package org.apache.camel.attachment; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; @@ -36,9 +37,13 @@ public final class DefaultAttachmentMessage implements AttachmentMessage { this.delegate = delegate; } - @Override - public Message getDelegateMessage() { - return delegate; + private Map<String, Object> getAttachmentsMap() { + var m = (Map<String, Object>) delegate.getPayloadForTrait(MessageTrait.ATTACHMENTS); + if (m == null) { + m = new LinkedHashMap<>(); + delegate.setPayloadForTrait(MessageTrait.ATTACHMENTS, m); + } + return m; } @Override @@ -178,7 +183,7 @@ public final class DefaultAttachmentMessage implements AttachmentMessage { @Override public void copyFrom(Message message) { - + delegate.copyFrom(message); } @Override @@ -227,7 +232,7 @@ public final class DefaultAttachmentMessage implements AttachmentMessage { Attachment a = (Attachment) att; answer.put(id, a.getDataHandler()); }); - return answer; + return Collections.unmodifiableMap(answer); } @Override @@ -237,7 +242,7 @@ public final class DefaultAttachmentMessage implements AttachmentMessage { Attachment a = (Attachment) att; answer.put(id, a); }); - return answer; + return Collections.unmodifiableMap(answer); } @Override @@ -252,12 +257,12 @@ public final class DefaultAttachmentMessage implements AttachmentMessage { @Override public boolean hasAttachments() { - return delegate.hasAttachments(); + return delegate.hasTrait(MessageTrait.ATTACHMENTS); } @Override - public Map<String, Object> getAttachmentsMap() { - return delegate.getAttachmentsMap(); + public void clearAttachments() { + delegate.removeTrait(MessageTrait.ATTACHMENTS); } @Override @@ -274,4 +279,9 @@ public final class DefaultAttachmentMessage implements AttachmentMessage { public void setPayloadForTrait(MessageTrait trait, Object object) { delegate.setPayloadForTrait(trait, object); } + + @Override + public void removeTrait(MessageTrait trait) { + delegate.removeTrait(trait); + } } diff --git a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty12/AttachmentHttpBinding.java b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty12/AttachmentHttpBinding.java index c22ea5c1222..6e7597e2320 100644 --- a/components/camel-jetty/src/main/java/org/apache/camel/component/jetty12/AttachmentHttpBinding.java +++ b/components/camel-jetty/src/main/java/org/apache/camel/component/jetty12/AttachmentHttpBinding.java @@ -33,6 +33,7 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.attachment.Attachment; import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.attachment.DefaultAttachment; +import org.apache.camel.attachment.DefaultAttachmentMessage; import org.apache.camel.component.jetty.MultiPartFilter; import org.apache.camel.http.common.DefaultHttpBinding; import org.apache.camel.http.common.HttpHelper; @@ -65,7 +66,7 @@ final class AttachmentHttpBinding extends DefaultHttpBinding { attachment.addHeader(headerName, headerValue); } } - AttachmentMessage am = message.getExchange().getMessage(AttachmentMessage.class); + AttachmentMessage am = new DefaultAttachmentMessage(message); am.addAttachmentObject(part.getName(), attachment); String name = part.getSubmittedFileName(); Object value = am.getAttachment(name); @@ -101,12 +102,12 @@ final class AttachmentHttpBinding extends DefaultHttpBinding { // } // attachment is optional - AttachmentMessage am = message.getExchange().getMessage(AttachmentMessage.class); + AttachmentMessage am = new DefaultAttachmentMessage(message); Enumeration<?> names = request.getParameterNames(); while (names.hasMoreElements()) { String name = (String) names.nextElement(); - if (am != null && am.getAttachment(name) != null) { + if (am.getAttachment(name) != null) { DataHandler dh = am.getAttachment(name); Object value = dh; if (dh.getContentType() == null || dh.getContentType().startsWith("text/plain")) { diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java index d770c7daf2c..82c0887bb4e 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java @@ -235,10 +235,6 @@ public class MailConsumer extends ScheduledBatchPollingConsumer { // must use the original message in case we need to work around a charset issue when extracting mail content var msg = exchange.getIn(); - if (msg instanceof AttachmentMessage am) { - // unwrap from attachment message - msg = am.getDelegateMessage(); - } final Message mail = ((MailMessage) msg).getOriginalMessage(); // add on completion to handle after work when the exchange is done @@ -456,10 +452,6 @@ public class MailConsumer extends ScheduledBatchPollingConsumer { protected void processExchange(Exchange exchange) throws Exception { if (LOG.isDebugEnabled()) { var msg = exchange.getIn(); - if (msg instanceof AttachmentMessage am) { - // unwrap from attachment message - msg = am.getDelegateMessage(); - } if (msg instanceof MailMessage mm) { LOG.debug("Processing message: {}", MailUtils.dumpMessage(mm.getMessage())); } diff --git a/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java b/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java index d12ab09c643..3ec673dbd94 100644 --- a/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java +++ b/components/camel-mail/src/main/java/org/apache/camel/component/mail/SplitAttachmentsExpression.java @@ -72,7 +72,7 @@ public class SplitAttachmentsExpression extends ExpressionAdapter { } // clear attachments on original message after we have split them - inMessage.getAttachmentObjects().clear(); + inMessage.clearAttachments(); return answer; } catch (Exception e) { diff --git a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentNamesTest.java b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentNamesTest.java index b2c740b4499..28daf0c5858 100644 --- a/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentNamesTest.java +++ b/components/camel-mail/src/test/java/org/apache/camel/component/mail/MailAttachmentNamesTest.java @@ -42,7 +42,6 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; public class MailAttachmentNamesTest extends CamelTestSupport { @@ -170,7 +169,7 @@ public class MailAttachmentNamesTest extends CamelTestSupport { resultDefaultEndpoint.assertIsSatisfied(); Exchange exchange = resultDefaultEndpoint.getReceivedExchanges().get(0); assertNotNull(exchange.getIn(AttachmentMessage.class)); - assertNull(exchange.getIn(AttachmentMessage.class).getAttachmentObjects()); + assertEquals(0, exchange.getIn(AttachmentMessage.class).getAttachmentObjects().size()); } /** @@ -185,7 +184,7 @@ public class MailAttachmentNamesTest extends CamelTestSupport { resultDefaultEndpoint.assertIsSatisfied(); Exchange exchange = resultDefaultEndpoint.getReceivedExchanges().get(0); assertNotNull(exchange.getIn(AttachmentMessage.class)); - assertNull(exchange.getIn(AttachmentMessage.class).getAttachmentObjects()); + assertEquals(0, exchange.getIn(AttachmentMessage.class).getAttachmentObjects().size()); } @Test diff --git a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java index 1b360d5c0ec..0495a2cb9ab 100644 --- a/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java +++ b/components/camel-servlet/src/main/java/org/apache/camel/component/servlet/AttachmentHttpBinding.java @@ -31,6 +31,7 @@ import org.apache.camel.RuntimeCamelException; import org.apache.camel.attachment.Attachment; import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.attachment.DefaultAttachment; +import org.apache.camel.attachment.DefaultAttachmentMessage; import org.apache.camel.http.common.DefaultHttpBinding; import org.apache.camel.util.FileUtil; import org.slf4j.Logger; @@ -75,7 +76,7 @@ public final class AttachmentHttpBinding extends DefaultHttpBinding { attachment.addHeader(headerName, headerValue); } } - AttachmentMessage am = message.getExchange().getMessage(AttachmentMessage.class); + AttachmentMessage am = new DefaultAttachmentMessage(message); am.addAttachmentObject(part.getName(), attachment); } else { LOG.debug( diff --git a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java index 114a9e95be6..a669de857ba 100644 --- a/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java +++ b/components/camel-undertow/src/main/java/org/apache/camel/component/undertow/DefaultUndertowHttpBinding.java @@ -47,6 +47,7 @@ import org.apache.camel.Message; import org.apache.camel.TypeConverter; import org.apache.camel.attachment.AttachmentMessage; import org.apache.camel.attachment.DefaultAttachment; +import org.apache.camel.attachment.DefaultAttachmentMessage; import org.apache.camel.spi.HeaderFilterStrategy; import org.apache.camel.support.DefaultMessage; import org.apache.camel.support.ExceptionHelper; @@ -136,7 +137,7 @@ public class DefaultUndertowHttpBinding implements UndertowHttpBinding { formData.get(key).forEach(value -> { if (value.isFile()) { DefaultAttachment attachment = new DefaultAttachment(new FilePartDataSource(value)); - AttachmentMessage am = result.getExchange().getMessage(AttachmentMessage.class); + AttachmentMessage am = new DefaultAttachmentMessage(result); am.addAttachmentObject(key, attachment); body.put(key, attachment.getDataHandler()); } else if (headerFilterStrategy != null diff --git a/core/camel-api/src/main/java/org/apache/camel/Message.java b/core/camel-api/src/main/java/org/apache/camel/Message.java index 1211354c25b..9bdd1bb1e75 100644 --- a/core/camel-api/src/main/java/org/apache/camel/Message.java +++ b/core/camel-api/src/main/java/org/apache/camel/Message.java @@ -220,10 +220,6 @@ public interface Message { */ boolean hasHeaders(); - boolean hasAttachments(); - - Map<String, Object> getAttachmentsMap(); - /** * Returns the body of the message as a POJO * <p/> @@ -364,4 +360,9 @@ public interface Message { */ void setPayloadForTrait(MessageTrait trait, Object object); + /** + * Removes the trait + */ + void removeTrait(MessageTrait trait); + } diff --git a/core/camel-api/src/main/java/org/apache/camel/trait/message/MessageTrait.java b/core/camel-api/src/main/java/org/apache/camel/trait/message/MessageTrait.java index 604c7fb1f1c..3b7067eaae2 100644 --- a/core/camel-api/src/main/java/org/apache/camel/trait/message/MessageTrait.java +++ b/core/camel-api/src/main/java/org/apache/camel/trait/message/MessageTrait.java @@ -22,13 +22,20 @@ package org.apache.camel.trait.message; * type, etc). This is specifically for internal usage of Camel and not a public API. */ public enum MessageTrait { + /** * The redelivery trait for the message. See {@link RedeliveryTraitPayload}. */ REDELIVERY, + /** * Whether the message can store a data type. This carries the payload associated with the API specified in * {@link org.apache.camel.spi.DataTypeAware}. */ - DATA_AWARE + DATA_AWARE, + + /** + * Trait for storing attachments on the message. + */ + ATTACHMENTS } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java index f158bd54f2f..46d948f1b1e 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/AbstractExchange.java @@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; import org.apache.camel.CamelExecutionException; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; @@ -515,7 +516,13 @@ abstract class AbstractExchange implements Exchange { } private Message newOutMessage() { - return in.newInstance(); + if (in != null) { + Message answer = in.newInstance(); + CamelContextAware.trySetCamelContext(answer, getContext()); + return answer; + } else { + return new DefaultMessage(getContext()); + } } @SuppressWarnings("deprecated") @@ -652,10 +659,8 @@ abstract class AbstractExchange implements Exchange { public boolean isExternalRedelivered() { if (externalRedelivered == RedeliveryTraitPayload.UNDEFINED_REDELIVERY) { Message message = getIn(); - externalRedelivered = (RedeliveryTraitPayload) message.getPayloadForTrait(MessageTrait.REDELIVERY); } - return externalRedelivered == RedeliveryTraitPayload.IS_REDELIVERY; } diff --git a/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessage.java b/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessage.java index 7af576a13c4..728486f44dd 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessage.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/DefaultMessage.java @@ -17,7 +17,6 @@ package org.apache.camel.support; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; import java.util.function.Supplier; @@ -25,6 +24,7 @@ import java.util.function.Supplier; import org.apache.camel.CamelContext; import org.apache.camel.Exchange; import org.apache.camel.spi.HeadersMapFactory; +import org.apache.camel.trait.message.MessageTrait; /** * The default implementation of {@link org.apache.camel.Message} @@ -37,7 +37,6 @@ import org.apache.camel.spi.HeadersMapFactory; */ public class DefaultMessage extends MessageSupport { private Map<String, Object> headers; - private Map<String, Object> attachments; public DefaultMessage(Exchange exchange) { setExchange(exchange); @@ -57,9 +56,7 @@ public class DefaultMessage extends MessageSupport { if (headers != null) { headers.clear(); } - if (attachments != null) { - attachments.clear(); - } + removeTrait(MessageTrait.ATTACHMENTS); } @Override @@ -297,20 +294,6 @@ public class DefaultMessage extends MessageSupport { return !headers.isEmpty(); } - @Override - public boolean hasAttachments() { - return attachments != null && !attachments.isEmpty(); - } - - @Override - public Map<String, Object> getAttachmentsMap() { - if (attachments == null) { - // force creating attachments - attachments = new LinkedHashMap<>(); - } - return attachments; - } - @Override public DefaultMessage newInstance() { return new DefaultMessage(camelContext); diff --git a/core/camel-support/src/main/java/org/apache/camel/support/MessageSupport.java b/core/camel-support/src/main/java/org/apache/camel/support/MessageSupport.java index baf81854880..cb241291c1d 100644 --- a/core/camel-support/src/main/java/org/apache/camel/support/MessageSupport.java +++ b/core/camel-support/src/main/java/org/apache/camel/support/MessageSupport.java @@ -17,6 +17,8 @@ package org.apache.camel.support; import java.util.EnumMap; +import java.util.LinkedHashMap; +import java.util.Map; import org.apache.camel.CamelContext; import org.apache.camel.CamelContextAware; @@ -198,6 +200,7 @@ public abstract class MessageSupport implements Message, CamelContextAware, Data } @Override + @SuppressWarnings("raw") public void copyFromWithNewBody(Message that, Object newBody) { if (that == this) { // it's the same instance, so do not need to copy @@ -227,28 +230,17 @@ public abstract class MessageSupport implements Message, CamelContextAware, Data } } - // the attachments may be the same instance if the end user has made some mistake - // and set the OUT message with the same attachment instance of the IN message etc - if (!sameAttachments(that)) { - if (hasAttachments()) { - // okay its safe to clear the attachments - getAttachmentsMap().clear(); - } - if (that.hasAttachments()) { - getAttachmentsMap().putAll(that.getAttachmentsMap()); - } + // copy attachments + Map<String, Object> attachments = (Map<String, Object>) that.getPayloadForTrait(MessageTrait.ATTACHMENTS); + if (attachments != null) { + setPayloadForTrait(MessageTrait.ATTACHMENTS, new LinkedHashMap<>(attachments)); } - } private boolean sameHeaders(Message that) { return hasHeaders() && that.hasHeaders() && getHeaders() == that.getHeaders(); } - private boolean sameAttachments(Message that) { - return hasAttachments() && that.hasAttachments() && getAttachmentsMap() == that.getAttachmentsMap(); - } - @Override public Exchange getExchange() { return exchange; @@ -331,4 +323,9 @@ public abstract class MessageSupport implements Message, CamelContextAware, Data public void setPayloadForTrait(MessageTrait trait, Object object) { traits.put(trait, object); } + + @Override + public void removeTrait(MessageTrait trait) { + traits.remove(trait); + } } diff --git a/core/camel-support/src/test/java/org/apache/camel/support/MessageHelperTest.java b/core/camel-support/src/test/java/org/apache/camel/support/MessageHelperTest.java index 32f251c710a..55d9a099154 100644 --- a/core/camel-support/src/test/java/org/apache/camel/support/MessageHelperTest.java +++ b/core/camel-support/src/test/java/org/apache/camel/support/MessageHelperTest.java @@ -187,16 +187,6 @@ class MessageHelperTest { return false; } - @Override - public boolean hasAttachments() { - return false; - } - - @Override - public Map<String, Object> getAttachmentsMap() { - return null; - } - @Override public Object getBody() { return body; @@ -252,5 +242,9 @@ class MessageHelperTest { @Override public void setPayloadForTrait(MessageTrait trait, Object object) { } + + @Override + public void removeTrait(MessageTrait trait) { + } } } diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc index 18f1f24f789..d03880b0ad1 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_10.adoc @@ -6,6 +6,26 @@ from both 4.0 to 4.1 and 4.1 to 4.2. == Upgrading from 4.10.0 to 4.10.1 +=== camel-api + +Added `removeTraits` method to `org.apache.camel.Message`. + +=== camel-attachments + +The attachments have been refactored to be stored internally as a _message trait_, +and the `org.apache.camel.attachment.AttachmentMessage` is only a facade to provide +end user access to the fine-grained Attachment APIs. The underlying message implementation +such as `DefaultMessage` in the `Exchange` is un-affected when converting from `Message` to `AttachmentMessage` via: + +[source,java] +---- +AttachmentMessage am = exchange.getMessage(AttachmentMessage.class); +am.addAttachment("message1.xml", new DataHandler(new FileDataSource(new File("src/test/data/message1.xml")))); +---- + +The class `org.apache.camel.attachment.AttachmentMap` has been removed. +Removed `getDelegateMessage` method from `org.apache.camel.attachment.AttachmentMessage`. + === camel-ftp The file name header `Exchange.FILE_NAME` now includes the relative path such as `subdir/hello.txt` diff --git a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_11.adoc b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_11.adoc index 1b49530f034..83e0a725569 100644 --- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_11.adoc +++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_11.adoc @@ -6,6 +6,26 @@ from both 4.0 to 4.1 and 4.1 to 4.2. == Upgrading Camel 4.10 to 4.11 +=== camel-api + +Added `removeTraits` method to `org.apache.camel.Message`. + +=== camel-attachments + +The attachments have been refactored to be stored internally as a _message trait_, +and the `org.apache.camel.attachment.AttachmentMessage` is only a facade to provide +end user access to the fine-grained Attachment APIs. The underlying message implementation +such as `DefaultMessage` in the `Exchange` is un-affected when converting from `Message` to `AttachmentMessage` via: + +[source,java] +---- +AttachmentMessage am = exchange.getMessage(AttachmentMessage.class); +am.addAttachment("message1.xml", new DataHandler(new FileDataSource(new File("src/test/data/message1.xml")))); +---- + +The class `org.apache.camel.attachment.AttachmentMap` has been removed. +Removed `getDelegateMessage` method from `org.apache.camel.attachment.AttachmentMessage`. + === camel-main Remove the deprecated `camel.main.lightweight` option that was not in use.
