Skip to content

Commit a369fc8

Browse files
committed
Introduce SmartMessageConverter interface with conversionHint arguments
Issue: SPR-13343
1 parent 5e9a968 commit a369fc8

File tree

5 files changed

+117
-45
lines changed

5 files changed

+117
-45
lines changed

spring-messaging/src/main/java/org/springframework/messaging/converter/AbstractMessageConverter.java

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
import org.springframework.util.MimeType;
3333

3434
/**
35-
* Abstract base class for {@link MessageConverter} implementations including support
36-
* for common properties and a partial implementation of the conversion methods,
35+
* Abstract base class for {@link SmartMessageConverter} implementations including
36+
* support for common properties and a partial implementation of the conversion methods,
3737
* mainly to check if the converter supports the conversion based on the payload class
3838
* and MIME type.
3939
*
@@ -42,7 +42,7 @@
4242
* @author Juergen Hoeller
4343
* @since 4.0
4444
*/
45-
public abstract class AbstractMessageConverter implements MessageConverter {
45+
public abstract class AbstractMessageConverter implements SmartMessageConverter {
4646

4747
protected final Log logger = LogFactory.getLog(getClass());
4848

@@ -167,19 +167,7 @@ public final Object fromMessage(Message<?> message, Class<?> targetClass) {
167167
return fromMessage(message, targetClass, null);
168168
}
169169

170-
/**
171-
* A variant of {@link #fromMessage(Message, Class)} which takes an extra
172-
* conversion context as an argument, allowing to take e.g. annotations
173-
* on a payload parameter into account.
174-
* @param message the input message
175-
* @param targetClass the target class for the conversion
176-
* @param conversionHint an extra object passed to the {@link MessageConverter},
177-
* e.g. the associated {@code MethodParameter} (may be {@code null}}
178-
* @return the result of the conversion, or {@code null} if the converter cannot
179-
* perform the conversion
180-
* @since 4.2
181-
* @see #fromMessage(Message, Class)
182-
*/
170+
@Override
183171
public final Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint) {
184172
if (!canConvertFrom(message, targetClass)) {
185173
return null;
@@ -196,19 +184,7 @@ public final Message<?> toMessage(Object payload, MessageHeaders headers) {
196184
return toMessage(payload, headers, null);
197185
}
198186

199-
/**
200-
* A variant of {@link #toMessage(Object, MessageHeaders)} which takes an extra
201-
* conversion context as an argument, allowing to take e.g. annotations
202-
* on a return type into account.
203-
* @param payload the Object to convert
204-
* @param headers optional headers for the message (may be {@code null})
205-
* @param conversionHint an extra object passed to the {@link MessageConverter},
206-
* e.g. the associated {@code MethodParameter} (may be {@code null}}
207-
* @return the new message, or {@code null} if the converter does not support the
208-
* Object type or the target media type
209-
* @since 4.2
210-
* @see #toMessage(Object, MessageHeaders)
211-
*/
187+
@Override
212188
public final Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint) {
213189
if (!canConvertTo(payload, headers)) {
214190
return null;

spring-messaging/src/main/java/org/springframework/messaging/converter/CompositeMessageConverter.java

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,13 +25,17 @@
2525
import org.springframework.util.Assert;
2626

2727
/**
28-
* A {@link MessageConverter} that delegates to a list of other converters
28+
* A {@link MessageConverter} that delegates to a list of registered converters
2929
* to be invoked until one of them returns a non-null result.
3030
*
31+
* <p>As of 4.2.1, this composite converter implements {@link SmartMessageConverter}
32+
* in order to support the delegation of conversion hints.
33+
*
3134
* @author Rossen Stoyanchev
35+
* @author Juergen Hoeller
3236
* @since 4.0
3337
*/
34-
public class CompositeMessageConverter implements MessageConverter {
38+
public class CompositeMessageConverter implements SmartMessageConverter {
3539

3640
private final List<MessageConverter> converters;
3741

@@ -44,14 +48,10 @@ public CompositeMessageConverter(Collection<MessageConverter> converters) {
4448
this.converters = new ArrayList<MessageConverter>(converters);
4549
}
4650

47-
public List<MessageConverter> getConverters() {
48-
return this.converters;
49-
}
50-
5151

5252
@Override
5353
public Object fromMessage(Message<?> message, Class<?> targetClass) {
54-
for (MessageConverter converter : this.converters) {
54+
for (MessageConverter converter : getConverters()) {
5555
Object result = converter.fromMessage(message, targetClass);
5656
if (result != null) {
5757
return result;
@@ -60,9 +60,22 @@ public Object fromMessage(Message<?> message, Class<?> targetClass) {
6060
return null;
6161
}
6262

63+
@Override
64+
public Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint) {
65+
for (MessageConverter converter : getConverters()) {
66+
Object result = (converter instanceof SmartMessageConverter ?
67+
((SmartMessageConverter) converter).fromMessage(message, targetClass, conversionHint) :
68+
converter.fromMessage(message, targetClass));
69+
if (result != null) {
70+
return result;
71+
}
72+
}
73+
return null;
74+
}
75+
6376
@Override
6477
public Message<?> toMessage(Object payload, MessageHeaders headers) {
65-
for (MessageConverter converter : this.converters) {
78+
for (MessageConverter converter : getConverters()) {
6679
Message<?> result = converter.toMessage(payload, headers);
6780
if (result != null) {
6881
return result;
@@ -71,9 +84,30 @@ public Message<?> toMessage(Object payload, MessageHeaders headers) {
7184
return null;
7285
}
7386

87+
@Override
88+
public Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint) {
89+
for (MessageConverter converter : getConverters()) {
90+
Message<?> result = (converter instanceof SmartMessageConverter ?
91+
((SmartMessageConverter) converter).toMessage(payload, headers, conversionHint) :
92+
converter.toMessage(payload, headers));
93+
if (result != null) {
94+
return result;
95+
}
96+
}
97+
return null;
98+
}
99+
100+
101+
/**
102+
* Return the underlying list of delegate converters.
103+
*/
104+
public List<MessageConverter> getConverters() {
105+
return this.converters;
106+
}
107+
74108
@Override
75109
public String toString() {
76-
return "CompositeMessageConverter[converters=" + this.converters + "]";
110+
return "CompositeMessageConverter[converters=" + getConverters() + "]";
77111
}
78112

79113
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2002-2015 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.messaging.converter;
18+
19+
import org.springframework.messaging.Message;
20+
import org.springframework.messaging.MessageHeaders;
21+
22+
/**
23+
* An extended {@link MessageConverter} SPI with conversion hint support.
24+
*
25+
* <p>In case of a conversion hint being provided, the framework will call
26+
* these extended methods if a converter implements this interface, instead
27+
* of calling the regular {@code fromMessage} / {@code toMessage} variants.
28+
*
29+
* @author Juergen Hoeller
30+
* @since 4.2.1
31+
*/
32+
public interface SmartMessageConverter extends MessageConverter {
33+
34+
/**
35+
* A variant of {@link #fromMessage(Message, Class)} which takes an extra
36+
* conversion context as an argument, allowing to take e.g. annotations
37+
* on a payload parameter into account.
38+
* @param message the input message
39+
* @param targetClass the target class for the conversion
40+
* @param conversionHint an extra object passed to the {@link MessageConverter},
41+
* e.g. the associated {@code MethodParameter} (may be {@code null}}
42+
* @return the result of the conversion, or {@code null} if the converter cannot
43+
* perform the conversion
44+
* @see #fromMessage(Message, Class)
45+
*/
46+
Object fromMessage(Message<?> message, Class<?> targetClass, Object conversionHint);
47+
48+
/**
49+
* A variant of {@link #toMessage(Object, MessageHeaders)} which takes an extra
50+
* conversion context as an argument, allowing to take e.g. annotations
51+
* on a return type into account.
52+
* @param payload the Object to convert
53+
* @param headers optional headers for the message (may be {@code null})
54+
* @param conversionHint an extra object passed to the {@link MessageConverter},
55+
* e.g. the associated {@code MethodParameter} (may be {@code null}}
56+
* @return the new message, or {@code null} if the converter does not support the
57+
* Object type or the target media type
58+
* @see #toMessage(Object, MessageHeaders)
59+
*/
60+
Message<?> toMessage(Object payload, MessageHeaders headers, Object conversionHint);
61+
62+
}

spring-messaging/src/main/java/org/springframework/messaging/core/AbstractMessageSendingTemplate.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@
2424
import org.springframework.messaging.Message;
2525
import org.springframework.messaging.MessageHeaders;
2626
import org.springframework.messaging.MessagingException;
27-
import org.springframework.messaging.converter.AbstractMessageConverter;
2827
import org.springframework.messaging.converter.MessageConversionException;
2928
import org.springframework.messaging.converter.MessageConverter;
3029
import org.springframework.messaging.converter.SimpleMessageConverter;
30+
import org.springframework.messaging.converter.SmartMessageConverter;
3131
import org.springframework.util.Assert;
3232

3333
/**
@@ -167,8 +167,8 @@ protected Message<?> doConvert(Object payload, Map<String, Object> headers, Mess
167167
}
168168

169169
MessageConverter converter = getMessageConverter();
170-
Message<?> message = (converter instanceof AbstractMessageConverter ?
171-
((AbstractMessageConverter) converter).toMessage(payload, messageHeaders, conversionHint) :
170+
Message<?> message = (converter instanceof SmartMessageConverter ?
171+
((SmartMessageConverter) converter).toMessage(payload, messageHeaders, conversionHint) :
172172
converter.toMessage(payload, messageHeaders));
173173
if (message == null) {
174174
String payloadType = (payload != null ? payload.getClass().getName() : null);

spring-messaging/src/main/java/org/springframework/messaging/handler/annotation/support/PayloadArgumentResolver.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@
2121
import org.springframework.core.MethodParameter;
2222
import org.springframework.core.annotation.AnnotationUtils;
2323
import org.springframework.messaging.Message;
24-
import org.springframework.messaging.converter.AbstractMessageConverter;
2524
import org.springframework.messaging.converter.MessageConversionException;
2625
import org.springframework.messaging.converter.MessageConverter;
26+
import org.springframework.messaging.converter.SmartMessageConverter;
2727
import org.springframework.messaging.handler.annotation.Payload;
2828
import org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolver;
2929
import org.springframework.util.Assert;
@@ -111,8 +111,8 @@ public Object resolveArgument(MethodParameter parameter, Message<?> message) thr
111111
return payload;
112112
}
113113
else {
114-
payload = (this.converter instanceof AbstractMessageConverter ?
115-
((AbstractMessageConverter) this.converter).fromMessage(message, targetClass, parameter) :
114+
payload = (this.converter instanceof SmartMessageConverter ?
115+
((SmartMessageConverter) this.converter).fromMessage(message, targetClass, parameter) :
116116
this.converter.fromMessage(message, targetClass));
117117
if (payload == null) {
118118
throw new MessageConversionException(message,

0 commit comments

Comments
 (0)