Introduce SmartMessageConverter interface with conversionHint arguments
Issue: SPR-13343
This commit is contained in:
parent
5e9a96817b
commit
a369fc8afd
|
@ -32,8 +32,8 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.MimeType;
|
import org.springframework.util.MimeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for {@link MessageConverter} implementations including support
|
* Abstract base class for {@link SmartMessageConverter} implementations including
|
||||||
* for common properties and a partial implementation of the conversion methods,
|
* support for common properties and a partial implementation of the conversion methods,
|
||||||
* mainly to check if the converter supports the conversion based on the payload class
|
* mainly to check if the converter supports the conversion based on the payload class
|
||||||
* and MIME type.
|
* and MIME type.
|
||||||
*
|
*
|
||||||
|
@ -42,7 +42,7 @@ import org.springframework.util.MimeType;
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractMessageConverter implements MessageConverter {
|
public abstract class AbstractMessageConverter implements SmartMessageConverter {
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
@ -167,19 +167,7 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
return fromMessage(message, targetClass, null);
|
return fromMessage(message, targetClass, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* A variant of {@link #fromMessage(Message, Class)} which takes an extra
|
|
||||||
* conversion context as an argument, allowing to take e.g. annotations
|
|
||||||
* on a payload parameter into account.
|
|
||||||
* @param message the input message
|
|
||||||
* @param targetClass the target class for the conversion
|
|
||||||
* @param conversionHint an extra object passed to the {@link MessageConverter},
|
|
||||||
* e.g. the associated {@code MethodParameter} (may be {@code null}}
|
|
||||||
* @return the result of the conversion, or {@code null} if the converter cannot
|
|
||||||
* perform the conversion
|
|
||||||
* @since 4.2
|
|
||||||
* @see #fromMessage(Message, Class)
|
|
||||||
*/
|
|
||||||
public final Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint) {
|
public final Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint) {
|
||||||
if (!canConvertFrom(message, targetClass)) {
|
if (!canConvertFrom(message, targetClass)) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -196,19 +184,7 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
return toMessage(payload, headers, null);
|
return toMessage(payload, headers, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* A variant of {@link #toMessage(Object, MessageHeaders)} which takes an extra
|
|
||||||
* conversion context as an argument, allowing to take e.g. annotations
|
|
||||||
* on a return type into account.
|
|
||||||
* @param payload the Object to convert
|
|
||||||
* @param headers optional headers for the message (may be {@code null})
|
|
||||||
* @param conversionHint an extra object passed to the {@link MessageConverter},
|
|
||||||
* e.g. the associated {@code MethodParameter} (may be {@code null}}
|
|
||||||
* @return the new message, or {@code null} if the converter does not support the
|
|
||||||
* Object type or the target media type
|
|
||||||
* @since 4.2
|
|
||||||
* @see #toMessage(Object, MessageHeaders)
|
|
||||||
*/
|
|
||||||
public final Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint) {
|
public final Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint) {
|
||||||
if (!canConvertTo(payload, headers)) {
|
if (!canConvertTo(payload, headers)) {
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -25,13 +25,17 @@ import org.springframework.messaging.MessageHeaders;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link MessageConverter} that delegates to a list of other converters
|
* A {@link MessageConverter} that delegates to a list of registered converters
|
||||||
* to be invoked until one of them returns a non-null result.
|
* to be invoked until one of them returns a non-null result.
|
||||||
*
|
*
|
||||||
|
* <p>As of 4.2.1, this composite converter implements {@link SmartMessageConverter}
|
||||||
|
* in order to support the delegation of conversion hints.
|
||||||
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
*/
|
*/
|
||||||
public class CompositeMessageConverter implements MessageConverter {
|
public class CompositeMessageConverter implements SmartMessageConverter {
|
||||||
|
|
||||||
private final List<MessageConverter> converters;
|
private final List<MessageConverter> converters;
|
||||||
|
|
||||||
|
@ -44,14 +48,10 @@ public class CompositeMessageConverter implements MessageConverter {
|
||||||
this.converters = new ArrayList<MessageConverter>(converters);
|
this.converters = new ArrayList<MessageConverter>(converters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MessageConverter> getConverters() {
|
|
||||||
return this.converters;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object fromMessage(Message<?> message, Class<?> targetClass) {
|
public Object fromMessage(Message<?> message, Class<?> targetClass) {
|
||||||
for (MessageConverter converter : this.converters) {
|
for (MessageConverter converter : getConverters()) {
|
||||||
Object result = converter.fromMessage(message, targetClass);
|
Object result = converter.fromMessage(message, targetClass);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -60,9 +60,22 @@ public class CompositeMessageConverter implements MessageConverter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint) {
|
||||||
|
for (MessageConverter converter : getConverters()) {
|
||||||
|
Object result = (converter instanceof SmartMessageConverter ?
|
||||||
|
((SmartMessageConverter) converter).fromMessage(message, targetClass, conversionHint) :
|
||||||
|
converter.fromMessage(message, targetClass));
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Message<?> toMessage(Object payload, MessageHeaders headers) {
|
public Message<?> toMessage(Object payload, MessageHeaders headers) {
|
||||||
for (MessageConverter converter : this.converters) {
|
for (MessageConverter converter : getConverters()) {
|
||||||
Message<?> result = converter.toMessage(payload, headers);
|
Message<?> result = converter.toMessage(payload, headers);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
|
@ -71,9 +84,30 @@ public class CompositeMessageConverter implements MessageConverter {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint) {
|
||||||
|
for (MessageConverter converter : getConverters()) {
|
||||||
|
Message<?> result = (converter instanceof SmartMessageConverter ?
|
||||||
|
((SmartMessageConverter) converter).toMessage(payload, headers, conversionHint) :
|
||||||
|
converter.toMessage(payload, headers));
|
||||||
|
if (result != null) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying list of delegate converters.
|
||||||
|
*/
|
||||||
|
public List<MessageConverter> getConverters() {
|
||||||
|
return this.converters;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "CompositeMessageConverter[converters=" + this.converters + "]";
|
return "CompositeMessageConverter[converters=" + getConverters() + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2015 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed 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.springframework.messaging.converter;
|
||||||
|
|
||||||
|
import org.springframework.messaging.Message;
|
||||||
|
import org.springframework.messaging.MessageHeaders;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An extended {@link MessageConverter} SPI with conversion hint support.
|
||||||
|
*
|
||||||
|
* <p>In case of a conversion hint being provided, the framework will call
|
||||||
|
* these extended methods if a converter implements this interface, instead
|
||||||
|
* of calling the regular {@code fromMessage} / {@code toMessage} variants.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 4.2.1
|
||||||
|
*/
|
||||||
|
public interface SmartMessageConverter extends MessageConverter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant of {@link #fromMessage(Message, Class)} which takes an extra
|
||||||
|
* conversion context as an argument, allowing to take e.g. annotations
|
||||||
|
* on a payload parameter into account.
|
||||||
|
* @param message the input message
|
||||||
|
* @param targetClass the target class for the conversion
|
||||||
|
* @param conversionHint an extra object passed to the {@link MessageConverter},
|
||||||
|
* e.g. the associated {@code MethodParameter} (may be {@code null}}
|
||||||
|
* @return the result of the conversion, or {@code null} if the converter cannot
|
||||||
|
* perform the conversion
|
||||||
|
* @see #fromMessage(Message, Class)
|
||||||
|
*/
|
||||||
|
Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant of {@link #toMessage(Object, MessageHeaders)} which takes an extra
|
||||||
|
* conversion context as an argument, allowing to take e.g. annotations
|
||||||
|
* on a return type into account.
|
||||||
|
* @param payload the Object to convert
|
||||||
|
* @param headers optional headers for the message (may be {@code null})
|
||||||
|
* @param conversionHint an extra object passed to the {@link MessageConverter},
|
||||||
|
* e.g. the associated {@code MethodParameter} (may be {@code null}}
|
||||||
|
* @return the new message, or {@code null} if the converter does not support the
|
||||||
|
* Object type or the target media type
|
||||||
|
* @see #toMessage(Object, MessageHeaders)
|
||||||
|
*/
|
||||||
|
Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint);
|
||||||
|
|
||||||
|
}
|
|
@ -24,10 +24,10 @@ import org.apache.commons.logging.LogFactory;
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
import org.springframework.messaging.MessageHeaders;
|
import org.springframework.messaging.MessageHeaders;
|
||||||
import org.springframework.messaging.MessagingException;
|
import org.springframework.messaging.MessagingException;
|
||||||
import org.springframework.messaging.converter.AbstractMessageConverter;
|
|
||||||
import org.springframework.messaging.converter.MessageConversionException;
|
import org.springframework.messaging.converter.MessageConversionException;
|
||||||
import org.springframework.messaging.converter.MessageConverter;
|
import org.springframework.messaging.converter.MessageConverter;
|
||||||
import org.springframework.messaging.converter.SimpleMessageConverter;
|
import org.springframework.messaging.converter.SimpleMessageConverter;
|
||||||
|
import org.springframework.messaging.converter.SmartMessageConverter;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,8 +167,8 @@ public abstract class AbstractMessageSendingTemplate<D> implements MessageSendin
|
||||||
}
|
}
|
||||||
|
|
||||||
MessageConverter converter = getMessageConverter();
|
MessageConverter converter = getMessageConverter();
|
||||||
Message<?> message = (converter instanceof AbstractMessageConverter ?
|
Message<?> message = (converter instanceof SmartMessageConverter ?
|
||||||
((AbstractMessageConverter) converter).toMessage(payload, messageHeaders, conversionHint) :
|
((SmartMessageConverter) converter).toMessage(payload, messageHeaders, conversionHint) :
|
||||||
converter.toMessage(payload, messageHeaders));
|
converter.toMessage(payload, messageHeaders));
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
String payloadType = (payload != null ? payload.getClass().getName() : null);
|
String payloadType = (payload != null ? payload.getClass().getName() : null);
|
||||||
|
|
|
@ -21,9 +21,9 @@ import java.lang.annotation.Annotation;
|
||||||
import org.springframework.core.MethodParameter;
|
import org.springframework.core.MethodParameter;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
import org.springframework.messaging.converter.AbstractMessageConverter;
|
|
||||||
import org.springframework.messaging.converter.MessageConversionException;
|
import org.springframework.messaging.converter.MessageConversionException;
|
||||||
import org.springframework.messaging.converter.MessageConverter;
|
import org.springframework.messaging.converter.MessageConverter;
|
||||||
|
import org.springframework.messaging.converter.SmartMessageConverter;
|
||||||
import org.springframework.messaging.handler.annotation.Payload;
|
import org.springframework.messaging.handler.annotation.Payload;
|
||||||
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
@ -111,8 +111,8 @@ public class PayloadArgumentResolver implements HandlerMethodArgumentResolver {
|
||||||
return payload;
|
return payload;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
payload = (this.converter instanceof AbstractMessageConverter ?
|
payload = (this.converter instanceof SmartMessageConverter ?
|
||||||
((AbstractMessageConverter) this.converter).fromMessage(message, targetClass, parameter) :
|
((SmartMessageConverter) this.converter).fromMessage(message, targetClass, parameter) :
|
||||||
this.converter.fromMessage(message, targetClass));
|
this.converter.fromMessage(message, targetClass));
|
||||||
if (payload == null) {
|
if (payload == null) {
|
||||||
throw new MessageConversionException(message,
|
throw new MessageConversionException(message,
|
||||||
|
|
Loading…
Reference in New Issue