This is an automated email from the ASF dual-hosted git repository.
acosentino pushed a commit to branch camel-4.14.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.14.x by this push:
new 88eeadc1b8fe CAMEL-22429 - camel-aws2-sns component fails when sending
CloudEvents with subjects over 100 characters (#21136) (#21144)
88eeadc1b8fe is described below
commit 88eeadc1b8fe6aacfeac416b4e8f4791ba773a1e
Author: Andrea Cosentino <[email protected]>
AuthorDate: Thu Jan 29 14:19:14 2026 +0100
CAMEL-22429 - camel-aws2-sns component fails when sending CloudEvents with
subjects over 100 characters (#21136) (#21144)
Signed-off-by: Andrea Cosentino <[email protected]>
---
.../src/main/docs/aws2-sns-component.adoc | 6 ++
.../camel/component/aws2/sns/Sns2Constants.java | 5 ++
.../camel/component/aws2/sns/Sns2Producer.java | 7 ++
.../component/aws2/sns/AmazonSNSClientMock.java | 7 ++
.../camel/component/aws2/sns/SnsComponentTest.java | 61 +++++++++++++++
.../SnsTopicProducerSubjectTruncationIT.java | 87 ++++++++++++++++++++++
6 files changed, 173 insertions(+)
diff --git
a/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc
b/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc
index 3123fdb9ca4b..d462de127feb 100644
--- a/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc
+++ b/components/camel-aws/camel-aws2-sns/src/main/docs/aws2-sns-component.adoc
@@ -176,6 +176,12 @@ When sending something to the FIFO topic, you'll need to
always set up a message
If the content-based message deduplication has been enabled on the SNS Fifo
topic, where won't be the need of setting a message deduplication id strategy,
otherwise you'll have to set it.
+=== Message Subject Length Limitation
+
+AWS SNS has a maximum subject length of 100 characters. If you send a message
with a subject longer than 100 characters (for example, when using CloudEvents
with long subjects), the subject will be automatically truncated to 100
characters.
+
+This behavior ensures compatibility with AWS SNS constraints while allowing
seamless integration with systems like CloudEvents that do not impose such
restrictions.
+
== Examples
=== Producer Examples
diff --git
a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Constants.java
b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Constants.java
index 61e49aee8c04..c4f4052a7bc7 100644
---
a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Constants.java
+++
b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Constants.java
@@ -23,6 +23,11 @@ import org.apache.camel.spi.Metadata;
*/
public interface Sns2Constants {
+ /**
+ * AWS SNS has a maximum subject length of 100 characters. Subjects longer
than this will be truncated.
+ */
+ int MAX_SUBJECT_LENGTH = 100;
+
@Metadata(description = "The Amazon SNS message ID.", javaType = "String")
String MESSAGE_ID = "CamelAwsSnsMessageId";
@Metadata(description = "The Amazon SNS message subject. If not set, the
subject from the\n" +
diff --git
a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
index 579d6d961d9d..2ff906a6782d 100644
---
a/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
+++
b/components/camel-aws/camel-aws2-sns/src/main/java/org/apache/camel/component/aws2/sns/Sns2Producer.java
@@ -94,6 +94,13 @@ public class Sns2Producer extends DefaultProducer {
subject = getConfiguration().getSubject();
}
+ // AWS SNS has a maximum subject length of 100 characters
+ if (subject != null && subject.length() >
Sns2Constants.MAX_SUBJECT_LENGTH) {
+ LOG.debug("Subject exceeds AWS SNS maximum length of {}
characters, truncating from {} to {} characters",
+ Sns2Constants.MAX_SUBJECT_LENGTH, subject.length(),
Sns2Constants.MAX_SUBJECT_LENGTH);
+ subject = subject.substring(0, Sns2Constants.MAX_SUBJECT_LENGTH);
+ }
+
return subject;
}
diff --git
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/AmazonSNSClientMock.java
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/AmazonSNSClientMock.java
index a01cbc4c0551..f3240855b059 100644
---
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/AmazonSNSClientMock.java
+++
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/AmazonSNSClientMock.java
@@ -37,9 +37,15 @@ public class AmazonSNSClientMock implements SnsClient {
private static final String DEFAULT_TOPIC_ARN =
"arn:aws:sns:us-east-1:541925086079:MyTopic";
+ private PublishRequest lastPublishRequest;
+
public AmazonSNSClientMock() {
}
+ public PublishRequest getLastPublishRequest() {
+ return lastPublishRequest;
+ }
+
@Override
public SetTopicAttributesResponse
setTopicAttributes(SetTopicAttributesRequest setTopicAttributesRequest) {
assertEquals(DEFAULT_TOPIC_ARN, setTopicAttributesRequest.topicArn());
@@ -59,6 +65,7 @@ public class AmazonSNSClientMock implements SnsClient {
@Override
public PublishResponse publish(PublishRequest publishRequest) {
+ this.lastPublishRequest = publishRequest;
return
PublishResponse.builder().messageId("dcc8ce7a-7f18-4385-bedd-b97984b4363c").build();
}
diff --git
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsComponentTest.java
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsComponentTest.java
index 46652ee80052..a70ec46279bd 100644
---
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsComponentTest.java
+++
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/SnsComponentTest.java
@@ -66,6 +66,67 @@ public class SnsComponentTest extends CamelTestSupport {
};
}
+ @DisplayName(value = "Test for CAMEL-22429 - Subject truncation to 100
characters")
+ @Test
+ public void sendWithLongSubject() {
+ // Create a subject longer than 100 characters
+ String longSubject
+ = "This is a very long subject that exceeds the AWS SNS
maximum subject length of 100 characters and should be truncated";
+
+ Exchange exchange = template.send("direct:start",
ExchangePattern.InOnly, new Processor() {
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Sns2Constants.SUBJECT, longSubject);
+ exchange.getIn().setBody("This is my message text.");
+ }
+ });
+
+ assertEquals("dcc8ce7a-7f18-4385-bedd-b97984b4363c",
exchange.getIn().getHeader(Sns2Constants.MESSAGE_ID));
+
+ // Verify the subject was truncated to 100 characters
+ String actualSubject = client.getLastPublishRequest().subject();
+ assertEquals(Sns2Constants.MAX_SUBJECT_LENGTH, actualSubject.length());
+ assertEquals(longSubject.substring(0,
Sns2Constants.MAX_SUBJECT_LENGTH), actualSubject);
+ }
+
+ @DisplayName(value = "Test for CAMEL-22429 - Subject exactly at 100
characters should not be truncated")
+ @Test
+ public void sendWithExact100CharSubject() {
+ // Create a subject exactly 100 characters
+ String exact100Subject = "A".repeat(Sns2Constants.MAX_SUBJECT_LENGTH);
+
+ Exchange exchange = template.send("direct:start",
ExchangePattern.InOnly, new Processor() {
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Sns2Constants.SUBJECT,
exact100Subject);
+ exchange.getIn().setBody("This is my message text.");
+ }
+ });
+
+ assertEquals("dcc8ce7a-7f18-4385-bedd-b97984b4363c",
exchange.getIn().getHeader(Sns2Constants.MESSAGE_ID));
+
+ // Verify the subject was not modified
+ String actualSubject = client.getLastPublishRequest().subject();
+ assertEquals(exact100Subject, actualSubject);
+ }
+
+ @DisplayName(value = "Test for CAMEL-22429 - Short subject should not be
modified")
+ @Test
+ public void sendWithShortSubject() {
+ String shortSubject = "Short subject";
+
+ Exchange exchange = template.send("direct:start",
ExchangePattern.InOnly, new Processor() {
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Sns2Constants.SUBJECT,
shortSubject);
+ exchange.getIn().setBody("This is my message text.");
+ }
+ });
+
+ assertEquals("dcc8ce7a-7f18-4385-bedd-b97984b4363c",
exchange.getIn().getHeader(Sns2Constants.MESSAGE_ID));
+
+ // Verify the subject was not modified
+ String actualSubject = client.getLastPublishRequest().subject();
+ assertEquals(shortSubject, actualSubject);
+ }
+
@DisplayName(value = "Test for CAMEL-16586")
@Test
public void createMultipleEndpoints() throws Exception {
diff --git
a/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/integration/SnsTopicProducerSubjectTruncationIT.java
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/integration/SnsTopicProducerSubjectTruncationIT.java
new file mode 100644
index 000000000000..a9394d705e9f
--- /dev/null
+++
b/components/camel-aws/camel-aws2-sns/src/test/java/org/apache/camel/component/aws2/sns/integration/SnsTopicProducerSubjectTruncationIT.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.aws2.sns.integration;
+
+import org.apache.camel.Exchange;
+import org.apache.camel.ExchangePattern;
+import org.apache.camel.Processor;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.aws2.sns.Sns2Constants;
+import org.apache.camel.test.infra.common.SharedNameGenerator;
+import org.apache.camel.test.infra.common.TestEntityNameGenerator;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+/**
+ * Integration test for CAMEL-22429: Verify that subjects longer than 100
characters are properly truncated when sending
+ * to AWS SNS, preventing InvalidParameterException.
+ */
+@DisabledIfSystemProperty(named = "ci.env.name", matches = ".*",
disabledReason = "Flaky on GitHub Actions")
+public class SnsTopicProducerSubjectTruncationIT extends Aws2SNSBase {
+
+ @RegisterExtension
+ public static SharedNameGenerator sharedNameGenerator = new
TestEntityNameGenerator();
+
+ @DisplayName("Test for CAMEL-22429 - Subject longer than 100 chars should
be truncated and message sent successfully")
+ @Test
+ public void sendWithLongSubject() {
+ // Create a subject longer than 100 characters (e.g., CloudEvents
style subject)
+ String longSubject
+ = "This is a very long subject that exceeds the AWS SNS
maximum subject length of 100 characters and should be truncated automatically";
+
+ Exchange exchange = template.send("direct:start",
ExchangePattern.InOnly, new Processor() {
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Sns2Constants.SUBJECT, longSubject);
+ exchange.getIn().setBody("This is my message text with a long
subject.");
+ }
+ });
+
+ // If we get here without an exception, the truncation worked
+ assertNotNull(exchange.getIn().getHeader(Sns2Constants.MESSAGE_ID));
+ }
+
+ @DisplayName("Test for CAMEL-22429 - Subject exactly 100 chars should work
without truncation")
+ @Test
+ public void sendWithExact100CharSubject() {
+ // Create a subject exactly 100 characters
+ String exact100Subject = "A".repeat(Sns2Constants.MAX_SUBJECT_LENGTH);
+
+ Exchange exchange = template.send("direct:start",
ExchangePattern.InOnly, new Processor() {
+ public void process(Exchange exchange) {
+ exchange.getIn().setHeader(Sns2Constants.SUBJECT,
exact100Subject);
+ exchange.getIn().setBody("This is my message text with exact
100 char subject.");
+ }
+ });
+
+ assertNotNull(exchange.getIn().getHeader(Sns2Constants.MESSAGE_ID));
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:start")
+ .toF("aws2-sns://%s?autoCreateTopic=true",
sharedNameGenerator.getName());
+ }
+ };
+ }
+}