Allow use of @JsonView on @MessageMapping methods
Issue: SPR-12741
This commit is contained in:
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
@@ -38,13 +39,24 @@ import org.springframework.util.MimeType;
|
||||
* and MIME type.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sebastien Deleuze
|
||||
* @since 4.0
|
||||
*/
|
||||
public abstract class AbstractMessageConverter implements MessageConverter {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
/**
|
||||
* Name of the header that can be set to provide further information
|
||||
* ({@link MethodParameter} instance) about the origin of the payload (for
|
||||
* {@link #toMessage(Object, MessageHeaders)}) or about the target of the payload
|
||||
* ({@link #fromMessage(Message, Class)}).
|
||||
*
|
||||
* @since 4.2
|
||||
*/
|
||||
public static final String METHOD_PARAMETER_HINT_HEADER = "methodParameterHint";
|
||||
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final List<MimeType> supportedMimeTypes;
|
||||
|
||||
private ContentTypeResolver contentTypeResolver = new DefaultContentTypeResolver();
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonView;
|
||||
import com.fasterxml.jackson.core.JsonEncoding;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
@@ -33,6 +34,7 @@ import com.fasterxml.jackson.databind.MapperFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -212,16 +214,27 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||
@Override
|
||||
public Object convertToInternal(Object payload, MessageHeaders headers) {
|
||||
try {
|
||||
Class<?> serializationView = getSerializationView(headers);
|
||||
if (byte[].class.equals(getSerializedPayloadClass())) {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||||
JsonEncoding encoding = getJsonEncoding(getMimeType(headers));
|
||||
JsonGenerator generator = this.objectMapper.getFactory().createGenerator(out, encoding);
|
||||
this.objectMapper.writeValue(generator, payload);
|
||||
if (serializationView != null) {
|
||||
this.objectMapper.writerWithView(serializationView).writeValue(generator, payload);
|
||||
}
|
||||
else {
|
||||
this.objectMapper.writeValue(generator, payload);
|
||||
}
|
||||
payload = out.toByteArray();
|
||||
}
|
||||
else {
|
||||
Writer writer = new StringWriter();
|
||||
this.objectMapper.writeValue(writer, payload);
|
||||
if (serializationView != null) {
|
||||
this.objectMapper.writerWithView(serializationView).writeValue(writer, payload);
|
||||
}
|
||||
else {
|
||||
this.objectMapper.writeValue(writer, payload);
|
||||
}
|
||||
payload = writer.toString();
|
||||
}
|
||||
}
|
||||
@@ -231,6 +244,24 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||
return payload;
|
||||
}
|
||||
|
||||
private Class<?> getSerializationView(MessageHeaders headers) {
|
||||
MethodParameter returnType = (headers == null ? null :
|
||||
(MethodParameter)headers.get(METHOD_PARAMETER_HINT_HEADER));
|
||||
if (returnType == null) {
|
||||
return null;
|
||||
}
|
||||
JsonView annotation = returnType.getMethodAnnotation(JsonView.class);
|
||||
if (annotation == null) {
|
||||
return null;
|
||||
}
|
||||
Class<?>[] classes = annotation.value();
|
||||
if (classes.length != 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"@JsonView only supported for handler methods with exactly 1 class argument: " + returnType);
|
||||
}
|
||||
return classes[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the JSON encoding to use for the given content type.
|
||||
* @param contentType the MIME type from the MessageHeaders, if any
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.converter.AbstractMessageConverter;
|
||||
import org.springframework.messaging.handler.DestinationPatternsMessageCondition;
|
||||
import org.springframework.messaging.handler.annotation.SendTo;
|
||||
import org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver;
|
||||
@@ -51,6 +52,7 @@ import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
|
||||
* the message is sent to each destination.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sebastien Deleuze
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
@@ -162,10 +164,10 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
for (String destination : destinations) {
|
||||
destination = this.placeholderHelper.replacePlaceholders(destination, varResolver);
|
||||
if (broadcast) {
|
||||
this.messagingTemplate.convertAndSendToUser(user, destination, returnValue);
|
||||
this.messagingTemplate.convertAndSendToUser(user, destination, returnValue, createHeaders(null, returnType));
|
||||
}
|
||||
else {
|
||||
this.messagingTemplate.convertAndSendToUser(user, destination, returnValue, createHeaders(sessionId));
|
||||
this.messagingTemplate.convertAndSendToUser(user, destination, returnValue, createHeaders(sessionId, returnType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -174,7 +176,7 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
String[] destinations = getTargetDestinations(sendTo, message, this.defaultDestinationPrefix);
|
||||
for (String destination : destinations) {
|
||||
destination = this.placeholderHelper.replacePlaceholders(destination, varResolver);
|
||||
this.messagingTemplate.convertAndSend(destination, returnValue, createHeaders(sessionId));
|
||||
this.messagingTemplate.convertAndSend(destination, returnValue, createHeaders(sessionId, returnType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -210,12 +212,15 @@ public class SendToMethodReturnValueHandler implements HandlerMethodReturnValueH
|
||||
new String[] {defaultPrefix + destination} : new String[] {defaultPrefix + "/" + destination});
|
||||
}
|
||||
|
||||
private MessageHeaders createHeaders(String sessionId) {
|
||||
private MessageHeaders createHeaders(String sessionId, MethodParameter returnType) {
|
||||
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
|
||||
if (getHeaderInitializer() != null) {
|
||||
getHeaderInitializer().initHeaders(headerAccessor);
|
||||
}
|
||||
headerAccessor.setSessionId(sessionId);
|
||||
if (sessionId != null) {
|
||||
headerAccessor.setSessionId(sessionId);
|
||||
}
|
||||
headerAccessor.setHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER, returnType);
|
||||
headerAccessor.setLeaveMutable(true);
|
||||
return headerAccessor.getMessageHeaders();
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.converter.AbstractMessageConverter;
|
||||
import org.springframework.messaging.core.MessageSendingOperations;
|
||||
import org.springframework.messaging.handler.annotation.SendTo;
|
||||
import org.springframework.messaging.handler.invocation.HandlerMethodReturnValueHandler;
|
||||
@@ -44,6 +45,7 @@ import org.springframework.util.Assert;
|
||||
* input message. The message is then sent directly back to the connected client.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Sebastien Deleuze
|
||||
* @since 4.0
|
||||
*/
|
||||
public class SubscriptionMethodReturnValueHandler implements HandlerMethodReturnValueHandler {
|
||||
@@ -109,16 +111,17 @@ public class SubscriptionMethodReturnValueHandler implements HandlerMethodReturn
|
||||
logger.debug("Reply to @SubscribeMapping: " + returnValue);
|
||||
}
|
||||
|
||||
this.messagingTemplate.convertAndSend(destination, returnValue, createHeaders(sessionId, subscriptionId));
|
||||
this.messagingTemplate.convertAndSend(destination, returnValue, createHeaders(sessionId, subscriptionId, returnType));
|
||||
}
|
||||
|
||||
private MessageHeaders createHeaders(String sessionId, String subscriptionId) {
|
||||
private MessageHeaders createHeaders(String sessionId, String subscriptionId, MethodParameter returnType) {
|
||||
SimpMessageHeaderAccessor headerAccessor = SimpMessageHeaderAccessor.create(SimpMessageType.MESSAGE);
|
||||
if (getHeaderInitializer() != null) {
|
||||
getHeaderInitializer().initHeaders(headerAccessor);
|
||||
}
|
||||
headerAccessor.setSessionId(sessionId);
|
||||
headerAccessor.setSubscriptionId(subscriptionId);
|
||||
headerAccessor.setHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER, returnType);
|
||||
headerAccessor.setLeaveMutable(true);
|
||||
return headerAccessor.getMessageHeaders();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user