This is an automated email from the ASF dual-hosted git repository.
gnodet pushed a commit to branch camel-4.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-4.18.x by this push:
new 237f0628a1fb [backport camel-4.18.x] CAMEL-24766:
camel-huaweicloud-smn - resolve the operation before the empty-body check
237f0628a1fb is described below
commit 237f0628a1fb8bf528b7bc86990005f02552beb6
Author: Guillaume Nodet - AI Bot <[email protected]>
AuthorDate: Mon Sep 21 11:10:09 2026 +0200
[backport camel-4.18.x] CAMEL-24766: camel-huaweicloud-smn - resolve the
operation before the empty-body check
* [backport camel-4.18.x] CAMEL-24766: camel-huaweicloud-smn - resolve the
operation before the empty-body check
* Fix: add camel-test-junit5 alongside camel-test-junit6 for 4.18.x
compatibility
* fix: use camel-test-junit5 instead of camel-test-junit6 on camel-4.18.x
camel-4.18.x uses junit6-jupiter-version=6.0.1 which pulls in JUnit
Platform 1.12+. The 3-argument Store.computeIfAbsent() was removed in
JUnit Platform 1.12, causing NoSuchMethodError in TestLoggerExtension.
Switch the backported test to camel-test-junit5 (already used by the
other tests in this module) to avoid the incompatibility.
---------
Co-authored-by: gnodet-bot <[email protected]>
Co-authored-by: Guillaume Nodet <[email protected]>
---
.../camel-huawei/camel-huaweicloud-smn/pom.xml | 2 +-
.../smn/SimpleNotificationProducer.java | 25 +++--
...PublishTextMessageOperationViaPropertyTest.java | 117 +++++++++++++++++++++
3 files changed, 130 insertions(+), 14 deletions(-)
diff --git a/components/camel-huawei/camel-huaweicloud-smn/pom.xml
b/components/camel-huawei/camel-huaweicloud-smn/pom.xml
index bd59a908a995..78e72f0c289e 100644
--- a/components/camel-huawei/camel-huaweicloud-smn/pom.xml
+++ b/components/camel-huawei/camel-huaweicloud-smn/pom.xml
@@ -69,7 +69,7 @@
<!-- for testing -->
<dependency>
<groupId>org.apache.camel</groupId>
- <artifactId>camel-test-spring-junit5</artifactId>
+ <artifactId>camel-test-junit5</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
diff --git
a/components/camel-huawei/camel-huaweicloud-smn/src/main/java/org/apache/camel/component/huaweicloud/smn/SimpleNotificationProducer.java
b/components/camel-huawei/camel-huaweicloud-smn/src/main/java/org/apache/camel/component/huaweicloud/smn/SimpleNotificationProducer.java
index ee1b28f95c13..f5cec86a8c13 100644
---
a/components/camel-huawei/camel-huaweicloud-smn/src/main/java/org/apache/camel/component/huaweicloud/smn/SimpleNotificationProducer.java
+++
b/components/camel-huawei/camel-huaweicloud-smn/src/main/java/org/apache/camel/component/huaweicloud/smn/SimpleNotificationProducer.java
@@ -124,8 +124,7 @@ public class SimpleNotificationProducer extends
DefaultProducer {
.withSubject(clientConfigurations.getSubject())
.withTimeToLive(String.valueOf(clientConfigurations.getMessageTtl()))
.withMessageTemplateName((String)
exchange.getProperty(SmnProperties.TEMPLATE_NAME))
- .withTags((HashMap<String, String>)
exchange.getProperty(SmnProperties.TEMPLATE_TAGS))
-
.withTimeToLive(String.valueOf(clientConfigurations.getMessageTtl()));
+ .withTags((HashMap<String, String>)
exchange.getProperty(SmnProperties.TEMPLATE_TAGS));
response = smnClient.publishMessage(new PublishMessageRequest()
.withBody(apiBody)
@@ -307,17 +306,8 @@ public class SimpleNotificationProducer extends
DefaultProducer {
if (LOG.isDebugEnabled()) {
LOG.debug("Inspecting exchange body");
}
- // verifying if exchange has valid body content. this is mandatory for
'publish as text' operation
- if (ObjectHelper.isEmpty(exchange.getMessage().getBody())) {
- if
(simpleNotificationEndpoint.getOperation().equals("publishAsTextMessage")) {
- if (LOG.isErrorEnabled()) {
- LOG.error("Found null/empty body. Cannot perform publish
as text operation");
- }
- throw new IllegalArgumentException("exchange body cannot be
null / empty");
- }
- }
-
- // checking for mandatory field 'operation name'
+ // resolve the operation first: the CamelHwCloudSmnOperation exchange
property takes precedence over the
+ // endpoint parameter, so the body check below must test the operation
that is actually dispatched
if (LOG.isDebugEnabled()) {
LOG.debug("Inspecting operation name");
}
@@ -332,6 +322,15 @@ public class SimpleNotificationProducer extends
DefaultProducer {
? (String)
exchange.getProperty(SmnProperties.SMN_OPERATION) :
simpleNotificationEndpoint.getOperation());
}
+ // verifying if exchange has valid body content. this is mandatory for
'publish as text' operation
+ if (ObjectHelper.isEmpty(exchange.getMessage().getBody())
+ &&
SmnOperations.PUBLISH_AS_TEXT_MESSAGE.equals(clientConfigurations.getOperation()))
{
+ if (LOG.isErrorEnabled()) {
+ LOG.error("Found null/empty body. Cannot perform publish as
text operation");
+ }
+ throw new IllegalArgumentException("exchange body cannot be null /
empty");
+ }
+
// checking for mandatory field 'topic name'
if (LOG.isDebugEnabled()) {
LOG.debug("Inspecting topic name");
diff --git
a/components/camel-huawei/camel-huaweicloud-smn/src/test/java/org/apache/camel/component/huaweicloud/smn/PublishTextMessageOperationViaPropertyTest.java
b/components/camel-huawei/camel-huaweicloud-smn/src/test/java/org/apache/camel/component/huaweicloud/smn/PublishTextMessageOperationViaPropertyTest.java
new file mode 100644
index 000000000000..42dace6ba496
--- /dev/null
+++
b/components/camel-huawei/camel-huaweicloud-smn/src/test/java/org/apache/camel/component/huaweicloud/smn/PublishTextMessageOperationViaPropertyTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.huaweicloud.smn;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.huaweicloud.smn.constants.SmnOperations;
+import org.apache.camel.component.huaweicloud.smn.constants.SmnProperties;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * When the operation is supplied only through the {@code
CamelHwCloudSmnOperation} exchange property (with no
+ * {@code operation} endpoint parameter), an empty text-message body must fail
with the clear
+ * {@code IllegalArgumentException} - not a {@code NullPointerException} from
the guard testing the (null) endpoint
+ * operation, which was the behaviour before the operation was resolved ahead
of the body check.
+ */
+public class PublishTextMessageOperationViaPropertyTest extends
CamelTestSupport {
+
+ TestConfiguration testConfiguration = new TestConfiguration();
+
+ @BindToRegistry("smnClient")
+ SmnClientMock smnClientMock = new SmnClientMock(null);
+
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ public void configure() {
+ from("direct:publish_without_operation_param")
+ .setProperty(SmnProperties.NOTIFICATION_SUBJECT,
constant("Dummy Subject Line"))
+ .setProperty(SmnProperties.NOTIFICATION_TOPIC_NAME,
constant(testConfiguration.getProperty("topic")))
+ .setProperty(SmnProperties.NOTIFICATION_TTL,
constant(60))
+ // operation supplied only via the exchange property;
the endpoint has no operation= parameter
+ .setProperty(SmnProperties.SMN_OPERATION,
constant(SmnOperations.PUBLISH_AS_TEXT_MESSAGE))
+ .to("hwcloud-smn:publishMessageService?accessKey="
+ + testConfiguration.getProperty("accessKey") +
"&secretKey="
+ + testConfiguration.getProperty("secretKey") +
"&projectId="
+ + testConfiguration.getProperty("projectId") +
"®ion=" + testConfiguration.getProperty("region")
+ + "&ignoreSslVerification=true"
+ + "&smnClient=#smnClient")
+ .to("mock:result");
+
+ from("direct:templated_endpoint_text_property")
+ .setProperty(SmnProperties.NOTIFICATION_SUBJECT,
constant("Dummy Subject Line"))
+ .setProperty(SmnProperties.NOTIFICATION_TOPIC_NAME,
constant(testConfiguration.getProperty("topic")))
+ .setProperty(SmnProperties.NOTIFICATION_TTL,
constant(60))
+ // endpoint operation is templated, but the property
overrides it to text
+ .setProperty(SmnProperties.SMN_OPERATION,
constant(SmnOperations.PUBLISH_AS_TEXT_MESSAGE))
+ .to("hwcloud-smn:publishMessageService?operation=" +
SmnOperations.PUBLISH_AS_TEMPLATED_MESSAGE
+ + "&accessKey=" +
testConfiguration.getProperty("accessKey") + "&secretKey="
+ + testConfiguration.getProperty("secretKey") +
"&projectId="
+ + testConfiguration.getProperty("projectId") +
"®ion="
+ + testConfiguration.getProperty("region")
+ + "&ignoreSslVerification=true"
+ + "&smnClient=#smnClient")
+ .to("mock:result");
+ }
+ };
+ }
+
+ @Test
+ public void emptyBodyReportsAClearErrorNotAnNpe() {
+ Exchange result =
template.request("direct:publish_without_operation_param", e ->
e.getIn().setBody(null));
+
+ Throwable cause = result.getException();
+ assertNotNull(cause, "an empty text-message body was expected to
fail");
+ boolean clearError = false;
+ while (cause != null) {
+ if (cause instanceof IllegalArgumentException &&
cause.getMessage() != null
+ && cause.getMessage().contains("exchange body cannot be
null / empty")) {
+ clearError = true;
+ break;
+ }
+ cause = cause.getCause();
+ }
+ assertTrue(clearError,
+ "expected a clear 'exchange body cannot be null / empty'
IllegalArgumentException, got: "
+ + result.getException());
+ }
+
+ @Test
+ public void propertyOverridingTemplatedEndpointToTextRejectsEmptyBody() {
+ // endpoint operation is publishAsTemplatedMessage but the property
overrides to publishAsTextMessage;
+ // the guard must test the RESOLVED operation, otherwise an empty text
message is silently published
+ Exchange result =
template.request("direct:templated_endpoint_text_property", e ->
e.getIn().setBody(null));
+
+ Throwable cause = result.getException();
+ assertNotNull(cause, "an empty text-message body was expected to
fail");
+ boolean clearError = false;
+ while (cause != null) {
+ if (cause instanceof IllegalArgumentException &&
cause.getMessage() != null
+ && cause.getMessage().contains("exchange body cannot be
null / empty")) {
+ clearError = true;
+ break;
+ }
+ cause = cause.getCause();
+ }
+ assertTrue(clearError, "expected 'exchange body cannot be null /
empty', got: " + result.getException());
+ }
+}