diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java index fa1296a31e7..072d3e29cdb 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/AbstractAdaptableMessageListener.java @@ -235,10 +235,10 @@ public abstract class AbstractAdaptableMessageListener * Extract the message body from the given JMS message. * @param message the JMS {@code Message} * @return the content of the message, to be passed into the listener method - * as an argument + * as an argument, or {@code null} if the message has no body * @throws MessageConversionException if the message could not be extracted */ - protected Object extractMessage(Message message) { + protected @Nullable Object extractMessage(Message message) { try { MessageConverter converter = getMessageConverter(); if (converter != null) { @@ -462,7 +462,7 @@ public abstract class AbstractAdaptableMessageListener } @Override - protected Object extractPayload(Message message) throws JMSException { + protected @Nullable Object extractPayload(Message message) throws JMSException { Object payload = extractMessage(message); if (message instanceof BytesMessage bytesMessage) { try { @@ -532,6 +532,10 @@ public abstract class AbstractAdaptableMessageListener if (payload instanceof org.springframework.messaging.Message springMessage) { return springMessage.getPayload(); } + if (payload == null) { + throw new MessageConversionException( + "Cannot convert JMS message with no body to a Message with a payload: " + this.message); + } return payload; } diff --git a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/MessageListenerAdapter.java b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/MessageListenerAdapter.java index b8a02946182..6c387f4f381 100644 --- a/spring-jms/src/main/java/org/springframework/jms/listener/adapter/MessageListenerAdapter.java +++ b/spring-jms/src/main/java/org/springframework/jms/listener/adapter/MessageListenerAdapter.java @@ -106,9 +106,9 @@ import org.springframework.util.ObjectUtils; * String handleMessage(String text); * } * - * For further examples and discussion please do refer to the Spring - * reference documentation which describes this class (and it's attendant - * XML configuration) in detail. + *
For further examples and discussion, please refer to the Spring reference + * documentation which describes this class (and its corresponding configuration) + * in detail. * * @author Juergen Hoeller * @since 2.0 @@ -219,7 +219,7 @@ public class MessageListenerAdapter extends AbstractAdaptableMessageListener imp String methodName = getListenerMethodName(message, convertedMessage); // Invoke the handler method with appropriate arguments. - Object[] listenerArguments = buildListenerArguments(convertedMessage); + @Nullable Object[] listenerArguments = buildListenerArguments(convertedMessage); Object result = invokeListenerMethod(methodName, listenerArguments); if (result != null) { handleResult(result, message, session); @@ -247,12 +247,12 @@ public class MessageListenerAdapter extends AbstractAdaptableMessageListener imp * default listener method, if any. * @param originalMessage the JMS request message * @param extractedMessage the converted JMS request message, - * to be passed into the listener method as argument + * to be passed into the listener method as an argument * @return the name of the listener method (never {@code null}) * @throws JMSException if thrown by JMS API methods * @see #setDefaultListenerMethod */ - protected String getListenerMethodName(Message originalMessage, Object extractedMessage) throws JMSException { + protected String getListenerMethodName(Message originalMessage, @Nullable Object extractedMessage) throws JMSException { return getDefaultListenerMethod(); } @@ -260,31 +260,34 @@ public class MessageListenerAdapter extends AbstractAdaptableMessageListener imp * Build an array of arguments to be passed into the target listener method. * Allows for multiple method arguments to be built from a single message object. *
The default implementation builds an array with the given message object - * as sole element. This means that the extracted message will always be passed + * as its sole element. This means that the extracted message will always be passed * into a single method argument, even if it is an array, with the target * method having a corresponding single argument of the array's type declared. *
This can be overridden to treat special message content such as arrays
* differently, for example passing in each element of the message array
- * as distinct method argument.
- * @param extractedMessage the content of the message
+ * as a distinct method argument.
+ * @param extractedMessage the content of the message, which may be
+ * {@code null} if the message had no body
* @return the array of arguments to be passed into the
* listener method (each element of the array corresponding
- * to a distinct method argument)
+ * to a distinct method argument); an element may be {@code null}
+ * if the corresponding extracted message content was {@code null}
*/
- protected Object[] buildListenerArguments(Object extractedMessage) {
+ protected @Nullable Object[] buildListenerArguments(@Nullable Object extractedMessage) {
return new Object[] {extractedMessage};
}
/**
* Invoke the specified listener method.
* @param methodName the name of the listener method
- * @param arguments the message arguments to be passed in
+ * @param arguments the message arguments to be passed in (an element
+ * may be {@code null})
* @return the result returned from the listener method
* @throws JMSException if thrown by JMS API methods
* @see #getListenerMethodName
* @see #buildListenerArguments
*/
- protected @Nullable Object invokeListenerMethod(String methodName, Object[] arguments) throws JMSException {
+ protected @Nullable Object invokeListenerMethod(String methodName, @Nullable Object[] arguments) throws JMSException {
try {
MethodInvoker methodInvoker = new MethodInvoker();
methodInvoker.setTargetObject(getDelegate());
diff --git a/spring-jms/src/main/java/org/springframework/jms/support/converter/MessageConverter.java b/spring-jms/src/main/java/org/springframework/jms/support/converter/MessageConverter.java
index 6ecd85bd8bf..e9b4dc769f6 100644
--- a/spring-jms/src/main/java/org/springframework/jms/support/converter/MessageConverter.java
+++ b/spring-jms/src/main/java/org/springframework/jms/support/converter/MessageConverter.java
@@ -19,6 +19,7 @@ package org.springframework.jms.support.converter;
import jakarta.jms.JMSException;
import jakarta.jms.Message;
import jakarta.jms.Session;
+import org.jspecify.annotations.Nullable;
/**
* Strategy interface that specifies a converter between Java objects and JMS messages.
@@ -48,10 +49,12 @@ public interface MessageConverter {
/**
* Convert from a JMS Message to a Java object.
* @param message the message to convert
- * @return the converted Java object
+ * @return the converted Java object, or {@code null} if the message has no
+ * body (for example, a {@link jakarta.jms.TextMessage} or
+ * {@link jakarta.jms.ObjectMessage} whose body was never set)
* @throws jakarta.jms.JMSException if thrown by JMS API methods
* @throws MessageConversionException in case of conversion failure
*/
- Object fromMessage(Message message) throws JMSException, MessageConversionException;
+ @Nullable Object fromMessage(Message message) throws JMSException, MessageConversionException;
}
diff --git a/spring-jms/src/main/java/org/springframework/jms/support/converter/MessagingMessageConverter.java b/spring-jms/src/main/java/org/springframework/jms/support/converter/MessagingMessageConverter.java
index 0b422ee5693..7869eac9fcc 100644
--- a/spring-jms/src/main/java/org/springframework/jms/support/converter/MessagingMessageConverter.java
+++ b/spring-jms/src/main/java/org/springframework/jms/support/converter/MessagingMessageConverter.java
@@ -117,6 +117,9 @@ public class MessagingMessageConverter implements MessageConverter, Initializing
public Object fromMessage(jakarta.jms.Message message) throws JMSException, MessageConversionException {
Map