Better hide lazy resolution of JMS payloads

This commit fixes MessagingMessageConverter to no longer expose the lazy
message resolution algorithm. This restores proper behaviour for
converters used outside of that context.

Instead, such arrangement is now private to
AbstractAdaptableMessageListener (as it should).

Issue: SPR-14389
This commit is contained in:
Stephane Nicoll
2016-06-29 18:10:34 +02:00
parent 2d5496df2b
commit eba873067c
5 changed files with 118 additions and 64 deletions

View File

@@ -39,6 +39,7 @@ import org.springframework.jms.support.converter.SimpleMessageConverter;
import org.springframework.jms.support.converter.SmartMessageConverter;
import org.springframework.jms.support.destination.DestinationResolver;
import org.springframework.jms.support.destination.DynamicDestinationResolver;
import org.springframework.messaging.MessageHeaders;
import org.springframework.util.Assert;
/**
@@ -417,11 +418,21 @@ public abstract class AbstractAdaptableMessageListener
/**
* Delegates payload extraction to {@link #extractMessage(javax.jms.Message)} to
* enforce backward compatibility.
* A {@link MessagingMessageConverter} that lazily invoke payload extraction and
* delegate it to {@link #extractMessage(javax.jms.Message)} in order to enforce
* backward compatibility.
*/
private class MessagingMessageConverterAdapter extends MessagingMessageConverter {
@SuppressWarnings("unchecked")
@Override
public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException {
if (message == null) {
return null;
}
return new LazyResolutionMessage(message);
}
@Override
protected Object extractPayload(Message message) throws JMSException {
Object payload = extractMessage(message);
@@ -452,6 +463,57 @@ public abstract class AbstractAdaptableMessageListener
}
return converter.toMessage(payload, session);
}
protected class LazyResolutionMessage implements org.springframework.messaging.Message<Object> {
private final javax.jms.Message message;
private Object payload;
private MessageHeaders headers;
public LazyResolutionMessage(javax.jms.Message message) {
this.message = message;
}
@Override
public Object getPayload() {
if (this.payload == null) {
try {
this.payload = unwrapPayload();
}
catch (JMSException ex) {
throw new MessageConversionException(
"Failed to extract payload from [" + this.message + "]", ex);
}
}
//
return this.payload;
}
/**
* Extract the payload of the current message. Since we deferred the resolution
* of the payload, a custom converter may still return a full message for it. In
* this case, its payload is returned.
* @return the payload of the message
*/
private Object unwrapPayload() throws JMSException {
Object payload = extractPayload(this.message);
if (payload instanceof org.springframework.messaging.Message) {
return ((org.springframework.messaging.Message) payload).getPayload();
}
return payload;
}
@Override
public MessageHeaders getHeaders() {
if (this.headers == null) {
this.headers = extractHeaders(this.message);
}
return this.headers;
}
}
}

View File

@@ -16,6 +16,7 @@
package org.springframework.jms.support.converter;
import java.util.Map;
import javax.jms.JMSException;
import javax.jms.Session;
@@ -25,6 +26,7 @@ import org.springframework.jms.support.SimpleJmsHeaderMapper;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.core.AbstractMessagingTemplate;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.util.Assert;
/**
@@ -107,7 +109,12 @@ public class MessagingMessageConverter implements MessageConverter, Initializing
if (message == null) {
return null;
}
return new LazyResolutionMessage(message);
Map<String, Object> mappedHeaders = extractHeaders(message);
Object convertedObject = extractPayload(message);
MessageBuilder<Object> builder = (convertedObject instanceof org.springframework.messaging.Message) ?
MessageBuilder.fromMessage((org.springframework.messaging.Message<Object>) convertedObject) :
MessageBuilder.withPayload(convertedObject);
return builder.copyHeadersIfAbsent(mappedHeaders).build();
}
/**
@@ -141,44 +148,11 @@ public class MessagingMessageConverter implements MessageConverter, Initializing
return createMessageForPayload(payload, session);
}
private MessageHeaders extractHeaders(javax.jms.Message message) {
protected final MessageHeaders extractHeaders(javax.jms.Message message) {
return this.headerMapper.toHeaders(message);
}
private class LazyResolutionMessage implements Message<Object> {
private final javax.jms.Message message;
private Object payload;
private MessageHeaders headers;
public LazyResolutionMessage(javax.jms.Message message) {
this.message = message;
}
@Override
public Object getPayload() {
if (this.payload == null) {
try {
this.payload = extractPayload(this.message);
}
catch (JMSException ex) {
throw new MessageConversionException(
"Failed to extract payload from [" + this.message + "]", ex);
}
}
return this.payload;
}
@Override
public MessageHeaders getHeaders() {
if (this.headers == null) {
this.headers = extractHeaders(this.message);
}
return this.headers;
}
}
}