提交 876c9694 编写于 作者: S Sebastien Deleuze

Allow use of @JsonView on @MessageMapping methods

Issue: SPR-12741
上级 c36435c0
......@@ -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();
}
......
......@@ -17,14 +17,17 @@
package org.springframework.messaging.converter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.annotation.JsonView;
import com.fasterxml.jackson.databind.DeserializationFeature;
import org.junit.Test;
import org.springframework.core.MethodParameter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.support.MessageBuilder;
......@@ -174,6 +177,23 @@ public class MappingJackson2MessageConverterTests {
assertEquals(contentType, message.getHeaders().get(MessageHeaders.CONTENT_TYPE));
}
@Test
public void jsonView() throws Exception {
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
Map<String, Object> map = new HashMap<>();
Method method = this.getClass().getDeclaredMethod("handle");
MethodParameter returnType = new MethodParameter(method, -1);
map.put(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER, returnType);
MessageHeaders headers = new MessageHeaders(map);
Message<?> message = converter.toMessage(handle(), headers);
String actual = new String((byte[]) message.getPayload(), UTF_8);
assertThat(actual, containsString("\"withView1\":\"with\""));
assertThat(actual, not(containsString("\"withView2\":\"with\"")));
assertThat(actual, not(containsString("\"withoutView\":\"without\"")));
}
public static class MyBean {
......@@ -238,4 +258,51 @@ public class MappingJackson2MessageConverterTests {
}
}
public interface MyJacksonView1 {};
public interface MyJacksonView2 {};
public static class JacksonViewBean {
@JsonView(MyJacksonView1.class)
private String withView1;
@JsonView(MyJacksonView2.class)
private String withView2;
private String withoutView;
public String getWithView1() {
return withView1;
}
public void setWithView1(String withView1) {
this.withView1 = withView1;
}
public String getWithView2() {
return withView2;
}
public void setWithView2(String withView2) {
this.withView2 = withView2;
}
public String getWithoutView() {
return withoutView;
}
public void setWithoutView(String withoutView) {
this.withoutView = withoutView;
}
}
@JsonView(MyJacksonView1.class)
public JacksonViewBean handle() {
JacksonViewBean bean = new JacksonViewBean();
bean.setWithView1("with");
bean.setWithView2("with");
bean.setWithoutView("without");
return bean;
}
}
......@@ -16,6 +16,7 @@
package org.springframework.messaging.simp.annotation.support;
import com.fasterxml.jackson.annotation.JsonView;
import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
import static org.springframework.messaging.handler.annotation.support.DestinationVariableMethodArgumentResolver.DESTINATION_TEMPLATE_VARIABLES_HEADER;
......@@ -23,6 +24,7 @@ import static org.springframework.messaging.support.MessageHeaderAccessor.*;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import java.util.LinkedHashMap;
import java.util.Map;
......@@ -41,6 +43,8 @@ import org.springframework.core.MethodParameter;
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.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.handler.DestinationPatternsMessageCondition;
import org.springframework.messaging.handler.annotation.SendTo;
......@@ -57,6 +61,7 @@ import org.springframework.util.MimeType;
* Test fixture for {@link SendToMethodReturnValueHandlerTests}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
*/
public class SendToMethodReturnValueHandlerTests {
......@@ -69,18 +74,21 @@ public class SendToMethodReturnValueHandlerTests {
private SendToMethodReturnValueHandler handlerAnnotationNotRequired;
private SendToMethodReturnValueHandler jsonHandler;
@Mock private MessageChannel messageChannel;
@Captor ArgumentCaptor<Message<?>> messageCaptor;
@Captor private ArgumentCaptor<Message<?>> messageCaptor;
private MethodParameter noAnnotationsReturnType;
private MethodParameter sendToReturnType;
private MethodParameter sendToDefaultDestReturnType;
private MethodParameter sendToWithPlaceholdersType;
private MethodParameter sendToWithPlaceholdersReturnType;
private MethodParameter sendToUserReturnType;
private MethodParameter sendToUserSingleSessionReturnType;
private MethodParameter sendToUserDefaultDestReturnType;
private MethodParameter sendToUserSingleSessionDefaultDestReturnType;
private MethodParameter jsonViewReturnType;
@Before
......@@ -90,10 +98,13 @@ public class SendToMethodReturnValueHandlerTests {
SimpMessagingTemplate messagingTemplate = new SimpMessagingTemplate(this.messageChannel);
messagingTemplate.setMessageConverter(new StringMessageConverter());
this.handler = new SendToMethodReturnValueHandler(messagingTemplate, true);
this.handlerAnnotationNotRequired = new SendToMethodReturnValueHandler(messagingTemplate, false);
SimpMessagingTemplate jsonMessagingTemplate = new SimpMessagingTemplate(this.messageChannel);
jsonMessagingTemplate.setMessageConverter(new MappingJackson2MessageConverter());
this.jsonHandler = new SendToMethodReturnValueHandler(jsonMessagingTemplate, true);
Method method = this.getClass().getDeclaredMethod("handleNoAnnotations");
this.noAnnotationsReturnType = new MethodParameter(method, -1);
......@@ -104,7 +115,7 @@ public class SendToMethodReturnValueHandlerTests {
this.sendToReturnType = new MethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToWithPlaceholders");
this.sendToWithPlaceholdersType = new MethodParameter(method, -1);
this.sendToWithPlaceholdersReturnType = new MethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToUser");
this.sendToUserReturnType = new MethodParameter(method, -1);
......@@ -117,6 +128,9 @@ public class SendToMethodReturnValueHandlerTests {
method = this.getClass().getDeclaredMethod("handleAndSendToUserDefaultDestinationSingleSession");
this.sendToUserSingleSessionDefaultDestReturnType = new MethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("handleAndSendToJsonView");
this.jsonViewReturnType = new MethodParameter(method, -1);
}
......@@ -143,6 +157,7 @@ public class SendToMethodReturnValueHandlerTests {
assertEquals("/topic/dest", accessor.getDestination());
assertEquals(MIME_TYPE, accessor.getContentType());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.noAnnotationsReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -161,12 +176,14 @@ public class SendToMethodReturnValueHandlerTests {
assertEquals("/dest1", accessor.getDestination());
assertEquals(MIME_TYPE, accessor.getContentType());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.sendToReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
accessor = getCapturedAccessor(1);
assertEquals(sessionId, accessor.getSessionId());
assertEquals("/dest2", accessor.getDestination());
assertEquals(MIME_TYPE, accessor.getContentType());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.sendToReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -185,6 +202,7 @@ public class SendToMethodReturnValueHandlerTests {
assertEquals("/topic/dest", accessor.getDestination());
assertEquals(MIME_TYPE, accessor.getContentType());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.sendToDefaultDestReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -220,6 +238,7 @@ public class SendToMethodReturnValueHandlerTests {
assertTrue(accessor.isMutable());
assertEquals("sess1", accessor.getSessionId());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.noAnnotationsReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -261,7 +280,7 @@ public class SendToMethodReturnValueHandlerTests {
accessor.setSubscriptionId("sub1");
accessor.setHeader(DESTINATION_TEMPLATE_VARIABLES_HEADER, vars);
Message<?> message = MessageBuilder.createMessage(PAYLOAD, accessor.getMessageHeaders());
this.handler.handleReturnValue(PAYLOAD, this.sendToWithPlaceholdersType, message);
this.handler.handleReturnValue(PAYLOAD, this.sendToWithPlaceholdersReturnType, message);
verify(this.messageChannel, times(1)).send(this.messageCaptor.capture());
......@@ -287,12 +306,14 @@ public class SendToMethodReturnValueHandlerTests {
assertEquals(MIME_TYPE, accessor.getContentType());
assertEquals("/user/" + user.getName() + "/dest1", accessor.getDestination());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.sendToUserSingleSessionReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
accessor = getCapturedAccessor(1);
assertEquals(sessionId, accessor.getSessionId());
assertEquals("/user/" + user.getName() + "/dest2", accessor.getDestination());
assertEquals(MIME_TYPE, accessor.getContentType());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.sendToUserSingleSessionReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -364,6 +385,7 @@ public class SendToMethodReturnValueHandlerTests {
assertEquals("/user/" + user.getName() + "/queue/dest", accessor.getDestination());
assertEquals(MIME_TYPE, accessor.getContentType());
assertNull("Subscription id should not be copied", accessor.getSubscriptionId());
assertEquals(this.sendToUserSingleSessionDefaultDestReturnType, accessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -386,6 +408,22 @@ public class SendToMethodReturnValueHandlerTests {
assertEquals("sess1", accessor.getSessionId());
}
@Test
public void jsonView() throws Exception {
given(this.messageChannel.send(any(Message.class))).willReturn(true);
String sessionId = "sess1";
Message<?> inputMessage = createInputMessage(sessionId, "sub1", "/app", "/dest", null);
this.jsonHandler.handleReturnValue(handleAndSendToJsonView(), this.jsonViewReturnType, inputMessage);
verify(this.messageChannel).send(this.messageCaptor.capture());
Message<?> message = this.messageCaptor.getValue();
assertNotNull(message);
assertEquals("{\"withView1\":\"with\"}", new String((byte[])message.getPayload(), StandardCharsets.UTF_8));
}
private Message<?> createInputMessage(String sessId, String subsId, String destinationPrefix,
String destination, Principal principal) {
......@@ -475,4 +513,54 @@ public class SendToMethodReturnValueHandlerTests {
return PAYLOAD;
}
@SuppressWarnings("unused")
@SendTo({"/dest"})
@JsonView(MyJacksonView1.class)
public JacksonViewBean handleAndSendToJsonView() {
JacksonViewBean payload = new JacksonViewBean();
payload.setWithView1("with");
payload.setWithView2("with");
payload.setWithoutView("without");
return payload;
}
private interface MyJacksonView1 {};
private interface MyJacksonView2 {};
private static class JacksonViewBean {
@JsonView(MyJacksonView1.class)
private String withView1;
@JsonView(MyJacksonView2.class)
private String withView2;
private String withoutView;
public String getWithView1() {
return withView1;
}
public void setWithView1(String withView1) {
this.withView1 = withView1;
}
public String getWithView2() {
return withView2;
}
public void setWithView2(String withView2) {
this.withView2 = withView2;
}
public String getWithoutView() {
return withoutView;
}
public void setWithoutView(String withoutView) {
this.withoutView = withoutView;
}
}
}
/*
* 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");
* you may not use this file except in compliance with the License.
......@@ -18,8 +18,10 @@ package org.springframework.messaging.simp.annotation.support;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.security.Principal;
import com.fasterxml.jackson.annotation.JsonView;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
......@@ -32,6 +34,8 @@ import org.springframework.core.MethodParameter;
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.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.converter.StringMessageConverter;
import org.springframework.messaging.core.MessageSendingOperations;
import org.springframework.messaging.handler.annotation.MessageMapping;
......@@ -50,6 +54,7 @@ import static org.mockito.BDDMockito.*;
* Test fixture for {@link SubscriptionMethodReturnValueHandler}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
*/
public class SubscriptionMethodReturnValueHandlerTests {
......@@ -60,9 +65,11 @@ public class SubscriptionMethodReturnValueHandlerTests {
private SubscriptionMethodReturnValueHandler handler;
private SubscriptionMethodReturnValueHandler jsonHandler;
@Mock private MessageChannel messageChannel;
@Captor ArgumentCaptor<Message<?>> messageCaptor;
@Captor private ArgumentCaptor<Message<?>> messageCaptor;
private MethodParameter subscribeEventReturnType;
......@@ -70,6 +77,8 @@ public class SubscriptionMethodReturnValueHandlerTests {
private MethodParameter messageMappingReturnType;
private MethodParameter subscribeEventJsonViewReturnType;
@Before
public void setup() throws Exception {
......@@ -78,9 +87,12 @@ public class SubscriptionMethodReturnValueHandlerTests {
SimpMessagingTemplate messagingTemplate = new SimpMessagingTemplate(this.messageChannel);
messagingTemplate.setMessageConverter(new StringMessageConverter());
this.handler = new SubscriptionMethodReturnValueHandler(messagingTemplate);
SimpMessagingTemplate jsonMessagingTemplate = new SimpMessagingTemplate(this.messageChannel);
jsonMessagingTemplate.setMessageConverter(new MappingJackson2MessageConverter());
this.jsonHandler = new SubscriptionMethodReturnValueHandler(jsonMessagingTemplate);
Method method = this.getClass().getDeclaredMethod("getData");
this.subscribeEventReturnType = new MethodParameter(method, -1);
......@@ -89,6 +101,9 @@ public class SubscriptionMethodReturnValueHandlerTests {
method = this.getClass().getDeclaredMethod("handle");
this.messageMappingReturnType = new MethodParameter(method, -1);
method = this.getClass().getDeclaredMethod("getJsonView");
this.subscribeEventJsonViewReturnType = new MethodParameter(method, -1);
}
......@@ -123,6 +138,7 @@ public class SubscriptionMethodReturnValueHandlerTests {
assertEquals(subscriptionId, headerAccessor.getSubscriptionId());
assertEquals(destination, headerAccessor.getDestination());
assertEquals(MIME_TYPE, headerAccessor.getContentType());
assertEquals(this.subscribeEventReturnType, headerAccessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
......@@ -149,6 +165,26 @@ public class SubscriptionMethodReturnValueHandlerTests {
assertTrue(headerAccessor.isMutable());
assertEquals(sessionId, headerAccessor.getSessionId());
assertEquals(subscriptionId, headerAccessor.getSubscriptionId());
assertEquals(this.subscribeEventReturnType, headerAccessor.getHeader(AbstractMessageConverter.METHOD_PARAMETER_HINT_HEADER));
}
@Test
public void testJsonView() throws Exception {
given(this.messageChannel.send(any(Message.class))).willReturn(true);
String sessionId = "sess1";
String subscriptionId = "subs1";
String destination = "/dest";
Message<?> inputMessage = createInputMessage(sessionId, subscriptionId, destination, null);
this.jsonHandler.handleReturnValue(getJsonView(), this.subscribeEventJsonViewReturnType, inputMessage);
verify(this.messageChannel).send(this.messageCaptor.capture());
Message<?> message = this.messageCaptor.getValue();
assertNotNull(message);
assertEquals("{\"withView1\":\"with\"}", new String((byte[])message.getPayload(), StandardCharsets.UTF_8));
}
......@@ -177,4 +213,54 @@ public class SubscriptionMethodReturnValueHandlerTests {
public String handle() {
return PAYLOAD;
}
@SubscribeMapping("/jsonview") // not needed for the tests but here for completeness
@JsonView(MyJacksonView1.class)
public JacksonViewBean getJsonView() {
JacksonViewBean payload = new JacksonViewBean();
payload.setWithView1("with");
payload.setWithView2("with");
payload.setWithoutView("without");
return payload;
}
private interface MyJacksonView1 {};
private interface MyJacksonView2 {};
private static class JacksonViewBean {
@JsonView(MyJacksonView1.class)
private String withView1;
@JsonView(MyJacksonView2.class)
private String withView2;
private String withoutView;
public String getWithView1() {
return withView1;
}
public void setWithView1(String withView1) {
this.withView1 = withView1;
}
public String getWithView2() {
return withView2;
}
public void setWithView2(String withView2) {
this.withView2 = withView2;
}
public String getWithoutView() {
return withoutView;
}
public void setWithoutView(String withoutView) {
this.withoutView = withoutView;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册