This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git
The following commit(s) were added to refs/heads/main by this push:
new 7f4cb4e3b76 Disable JMS ObjectMessage deserialization by default
(#3337)
7f4cb4e3b76 is described below
commit 7f4cb4e3b765e632216fb7fc8acfa2c64e2179bf
Author: Colm O hEigeartaigh <[email protected]>
AuthorDate: Mon Jul 27 15:34:19 2026 +0100
Disable JMS ObjectMessage deserialization by default (#3337)
---
.../org/apache/cxf/transport/jms/JMSConduit.java | 3 +-
.../apache/cxf/transport/jms/JMSConfigFactory.java | 2 +
.../apache/cxf/transport/jms/JMSConfiguration.java | 29 ++++++++++++
.../apache/cxf/transport/jms/JMSDestination.java | 4 +-
.../apache/cxf/transport/jms/JMSMessageUtils.java | 15 ++++--
.../apache/cxf/transport/jms/uri/JMSEndpoint.java | 26 ++++++++++
.../transport/jms/util/JMSMessageConverter.java | 13 +++++
.../cxf/transport/jms/JMSConfigFactoryTest.java | 14 ++++++
.../cxf/transport/jms/uri/JMSEndpointTest.java | 24 ++++++++++
.../jms/util/JMSMessageConverterTest.java | 55 ++++++++++++++++++++++
.../apache/cxf/transport/jms/util/JMSUtilTest.java | 11 +++--
11 files changed, 187 insertions(+), 9 deletions(-)
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
index 41d3377a72d..4f8db4a28cb 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConduit.java
@@ -472,7 +472,8 @@ public class JMSConduit extends AbstractConduit implements
JMSExchangeSender, Me
LOG.log(Level.FINE, "client received reply: ", jmsMessage);
try {
Message inMessage = JMSMessageUtils.asCXFMessage(jmsMessage,
-
JMSConstants.JMS_CLIENT_RESPONSE_HEADERS);
+
JMSConstants.JMS_CLIENT_RESPONSE_HEADERS,
+
jmsConfig.isAllowObjectMessages());
if (jmsConfig.isCreateSecurityContext()) {
SecurityContext securityContext =
SecurityContextFactory.buildSecurityContext(jmsMessage, jmsConfig);
inMessage.put(SecurityContext.class, securityContext);
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
index 5a95b40d406..2cfe46df416 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfigFactory.java
@@ -83,6 +83,8 @@ public final class JMSConfigFactory {
jmsConfig.setConcurrentConsumers(endpoint.getConcurrentConsumers());
jmsConfig.setOneSessionPerConnection(endpoint.isOneSessionPerConnection());
jmsConfig.setMessageSelector(endpoint.getMessageSelector());
+
jmsConfig.setUseObjectMessageFallback(endpoint.isUseObjectMessageFallback());
+ jmsConfig.setAllowObjectMessages(endpoint.isAllowObjectMessages());
TransactionManager tm = getTransactionManager(bus, endpoint);
jmsConfig.setTransactionManager(tm);
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
index b72a111885d..e6cbb9da07f 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSConfiguration.java
@@ -87,7 +87,16 @@ public class JMSConfiguration {
private volatile Destination replyToDestinationDest;
private String messageType = JMSConstants.TEXT_MESSAGE_TYPE;
+ /**
+ * Outbound only: when true, non-text payloads may fall back to
ObjectMessage.
+ * When false, non-text payloads are sent as BytesMessage.
+ */
private boolean useObjectMessageFallback;
+ /**
+ * Inbound only: when true, ObjectMessage deserialization is allowed.
+ * When false, inbound ObjectMessage is rejected.
+ */
+ private boolean allowObjectMessages;
private boolean pubSubDomain;
private boolean replyPubSubDomain;
@@ -285,14 +294,34 @@ public class JMSConfiguration {
this.messageType = messageType;
}
+ /**
+ * Outbound only: controls ObjectMessage fallback in payload creation.
+ */
public boolean isUseObjectMessageFallback() {
return useObjectMessageFallback;
}
+ /**
+ * Outbound only: controls ObjectMessage fallback in payload creation.
+ */
public void setUseObjectMessageFallback(boolean useObjectMessageFallback) {
this.useObjectMessageFallback = useObjectMessageFallback;
}
+ /**
+ * Inbound only: controls whether ObjectMessage deserialization is
permitted.
+ */
+ public boolean isAllowObjectMessages() {
+ return allowObjectMessages;
+ }
+
+ /**
+ * Inbound only: controls whether ObjectMessage deserialization is
permitted.
+ */
+ public void setAllowObjectMessages(boolean allowObjectMessages) {
+ this.allowObjectMessages = allowObjectMessages;
+ }
+
public boolean isPubSubDomain() {
return pubSubDomain;
}
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
index 1430d80f9f7..a54c265afe3 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSDestination.java
@@ -228,7 +228,9 @@ public class JMSDestination extends
AbstractMultiplexDestination implements Mess
getLogger().log(Level.FINE,
"JMS destination received message " + message + "
on "
+ jmsConfig.getTargetDestination());
- Message inMessage = JMSMessageUtils.asCXFMessage(message,
JMSConstants.JMS_SERVER_REQUEST_HEADERS);
+ Message inMessage = JMSMessageUtils.asCXFMessage(message,
+
JMSConstants.JMS_SERVER_REQUEST_HEADERS,
+
jmsConfig.isAllowObjectMessages());
if (jmsConfig.isCreateSecurityContext()) {
SecurityContext securityContext =
SecurityContextFactory.buildSecurityContext(message, jmsConfig);
inMessage.put(SecurityContext.class, securityContext);
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
index 5e28ebbad4c..4a5c80232c2 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/JMSMessageUtils.java
@@ -58,11 +58,18 @@ final class JMSMessageUtils {
}
public static org.apache.cxf.message.Message asCXFMessage(Message message,
String jmsHeadersKey)
throws UnsupportedEncodingException, JMSException {
+ return asCXFMessage(message, jmsHeadersKey, false);
+ }
+
+ public static org.apache.cxf.message.Message asCXFMessage(Message message,
+ String
jmsHeadersKey,
+ boolean
allowObjectMessage)
+ throws UnsupportedEncodingException, JMSException {
org.apache.cxf.message.Message inMessage = new MessageImpl();
JMSMessageHeadersType messageHeaders =
JMSMessageHeadersType.from(message);
inMessage.put(jmsHeadersKey, messageHeaders);
populateIncomingContext(messageHeaders, inMessage);
- retrieveAndSetPayload(inMessage, message);
+ retrieveAndSetPayload(inMessage, message, allowObjectMessage);
return inMessage;
}
@@ -74,10 +81,12 @@ final class JMSMessageUtils {
* @throws UnsupportedEncodingException
* @throws JMSException
*/
- private static void retrieveAndSetPayload(org.apache.cxf.message.Message
inMessage, Message message)
+ private static void retrieveAndSetPayload(org.apache.cxf.message.Message
inMessage,
+ Message message,
+ boolean allowObjectMessage)
throws UnsupportedEncodingException, JMSException {
final String messageType;
- Object converted = new JMSMessageConverter().fromMessage(message);
+ Object converted = new
JMSMessageConverter(allowObjectMessage).fromMessage(message);
if (converted instanceof String) {
inMessage.setContent(Reader.class, new
StringReader((String)converted));
messageType = JMSConstants.TEXT_MESSAGE_TYPE;
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
index a05571d67ac..886e5317a95 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/uri/JMSEndpoint.java
@@ -89,6 +89,8 @@ public class JMSEndpoint {
private int retryInterval = 5000;
private boolean oneSessionPerConnection;
private boolean ignoreTimeoutException;
+ private boolean useObjectMessageFallback;
+ private boolean allowObjectMessages;
/**
* @param endpointUri
@@ -517,4 +519,28 @@ public class JMSEndpoint {
this.ignoreTimeoutException = ignoreTimeoutException;
}
+ public boolean isAllowObjectMessages() {
+ return allowObjectMessages;
+ }
+
+ public void setAllowObjectMessages(boolean allowObjectMessages) {
+ this.allowObjectMessages = allowObjectMessages;
+ }
+
+ public void setAllowObjectMessages(String allowObjectMessages) {
+ this.allowObjectMessages = Boolean.parseBoolean(allowObjectMessages);
+ }
+
+ public boolean isUseObjectMessageFallback() {
+ return useObjectMessageFallback;
+ }
+
+ public void setUseObjectMessageFallback(boolean useObjectMessageFallback) {
+ this.useObjectMessageFallback = useObjectMessageFallback;
+ }
+
+ public void setUseObjectMessageFallback(String useObjectMessageFallback) {
+ this.useObjectMessageFallback =
Boolean.parseBoolean(useObjectMessageFallback);
+ }
+
}
diff --git
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
index c25287366a7..9744fefac5e 100644
---
a/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
+++
b/rt/transports/jms/src/main/java/org/apache/cxf/transport/jms/util/JMSMessageConverter.java
@@ -37,6 +37,16 @@ import jakarta.jms.TextMessage;
*/
public class JMSMessageConverter {
+ private final boolean allowObjectMessage;
+
+ public JMSMessageConverter() {
+ this(false);
+ }
+
+ public JMSMessageConverter(boolean allowObjectMessage) {
+ this.allowObjectMessage = allowObjectMessage;
+ }
+
public Message toMessage(Object object, Session session) throws
JMSException {
if (object instanceof Message) {
return (Message)object;
@@ -67,6 +77,9 @@ public class JMSMessageConverter {
message1.readBytes(bytes);
return bytes;
} else if (message instanceof ObjectMessage) {
+ if (!allowObjectMessage) {
+ throw new JMSException("ObjectMessage is disabled by
configuration");
+ }
return ((ObjectMessage)message).getObject();
} else if (message instanceof StreamMessage) {
StreamMessage streamMessage = (StreamMessage)message;
diff --git
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
index 0c4af03be86..ffcdca0a119 100644
---
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
+++
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/JMSConfigFactoryTest.java
@@ -136,4 +136,18 @@ public class JMSConfigFactoryTest extends
AbstractJMSTester {
JMSConfiguration config = JMSConfigFactory.createFromEndpointInfo(bus,
ei, null);
Assert.assertEquals("customJMSAttribute=helloWorld",
config.getMessageSelector());
}
+
+ @Test
+ public void testUseObjectMessageFallbackIsSet() {
+ JMSEndpoint endpoint = new
JMSEndpoint("jms:queue:Foo.Bar?useObjectMessageFallback=true");
+ JMSConfiguration jmsConfig = JMSConfigFactory.createFromEndpoint(bus,
endpoint);
+ Assert.assertTrue(jmsConfig.isUseObjectMessageFallback());
+ }
+
+ @Test
+ public void testAllowObjectMessagesIsSet() {
+ JMSEndpoint endpoint = new
JMSEndpoint("jms:queue:Foo.Bar?allowObjectMessages=true");
+ JMSConfiguration jmsConfig = JMSConfigFactory.createFromEndpoint(bus,
endpoint);
+ Assert.assertTrue(jmsConfig.isAllowObjectMessages());
+ }
}
diff --git
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
index bc9b4400929..158d81633fa 100644
---
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
+++
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/uri/JMSEndpointTest.java
@@ -190,6 +190,30 @@ public class JMSEndpointTest {
}
+ @Test
+ public void testAllowObjectMessagesDefaultsToFalse() {
+ JMSEndpoint endpoint = new JMSEndpoint("jms:queue:Foo.Bar");
+ assertFalse(endpoint.isAllowObjectMessages());
+ }
+
+ @Test
+ public void testAllowObjectMessagesCanBeEnabledFromUri() {
+ JMSEndpoint endpoint = new
JMSEndpoint("jms:queue:Foo.Bar?allowObjectMessages=true");
+ assertTrue(endpoint.isAllowObjectMessages());
+ }
+
+ @Test
+ public void testUseObjectMessageFallbackDefaultsToFalse() {
+ JMSEndpoint endpoint = new JMSEndpoint("jms:queue:Foo.Bar");
+ assertFalse(endpoint.isUseObjectMessageFallback());
+ }
+
+ @Test
+ public void testUseObjectMessageFallbackCanBeEnabledFromUri() {
+ JMSEndpoint endpoint = new
JMSEndpoint("jms:queue:Foo.Bar?useObjectMessageFallback=true");
+ assertTrue(endpoint.isUseObjectMessageFallback());
+ }
+
@Test
public void nonSoapJMS() throws Exception {
JMSEndpoint endpoint = new JMSEndpoint("jms://");
diff --git
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSMessageConverterTest.java
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSMessageConverterTest.java
new file mode 100644
index 00000000000..8e08d33d17a
--- /dev/null
+++
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSMessageConverterTest.java
@@ -0,0 +1,55 @@
+/**
+ * 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.cxf.transport.jms.util;
+
+import jakarta.jms.JMSException;
+import jakarta.jms.ObjectMessage;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class JMSMessageConverterTest {
+
+ @Test
+ public void testObjectMessageIsRejectedByDefault() throws Exception {
+ JMSMessageConverter converter = new JMSMessageConverter();
+ ObjectMessage objectMessage = mock(ObjectMessage.class);
+
+ try {
+ converter.fromMessage(objectMessage);
+ fail("Expected JMSException to be thrown");
+ } catch (JMSException ex) {
+ assertEquals("ObjectMessage is disabled by configuration",
ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testObjectMessageCanBeEnabled() throws Exception {
+ JMSMessageConverter converter = new JMSMessageConverter(true);
+ ObjectMessage objectMessage = mock(ObjectMessage.class);
+ when(objectMessage.getObject()).thenReturn("payload");
+
+ Object payload = converter.fromMessage(objectMessage);
+ assertEquals("payload", payload);
+ }
+}
diff --git
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
index 5345b9bf540..b66ed47ddeb 100644
---
a/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
+++
b/rt/transports/jms/src/test/java/org/apache/cxf/transport/jms/util/JMSUtilTest.java
@@ -83,14 +83,17 @@ public class JMSUtilTest {
Connection connection = JMSFactory.createConnection(jmsConfig);
Session session = connection.createSession(false,
Session.AUTO_ACKNOWLEDGE);
jakarta.jms.Message jmsMessage =
- JMSUtil.createAndSetPayload(testBytes, session,
JMSConstants.BYTE_MESSAGE_TYPE);
+ JMSUtil.createAndSetPayload(testBytes, session,
JMSConstants.BYTE_MESSAGE_TYPE, false);
assertTrue("Message should have been of type BytesMessage ",
jmsMessage instanceof BytesMessage);
- jmsMessage = JMSUtil.createAndSetPayload(testBytes, session,
JMSConstants.BINARY_MESSAGE_TYPE);
- assertTrue("Binary message fallback should have been of type
ObjectMessage ",
- jmsMessage instanceof ObjectMessage);
+ jmsMessage = JMSUtil.createAndSetPayload(testBytes, session,
JMSConstants.BINARY_MESSAGE_TYPE, false);
+ assertTrue("Default binary message should have been of type
BytesMessage ",
+ jmsMessage instanceof BytesMessage);
jmsMessage = JMSUtil.createAndSetPayload(testBytes, session,
JMSConstants.BINARY_MESSAGE_TYPE, false);
assertTrue("Fallback-disabled binary message should have been of
type BytesMessage ",
jmsMessage instanceof BytesMessage);
+ jmsMessage = JMSUtil.createAndSetPayload(testBytes, session,
JMSConstants.BINARY_MESSAGE_TYPE, true);
+ assertTrue("Fallback-enabled binary message should have been of
type ObjectMessage ",
+ jmsMessage instanceof ObjectMessage);
jmsMessage = JMSUtil.createAndSetPayload(testBytes, session,
"application/octet-stream", true);
assertTrue("Non-text message fallback should have been of type
ObjectMessage ",
jmsMessage instanceof ObjectMessage);