diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfiguration.java index f0164264bf..3dbbda14f9 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 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. @@ -28,9 +28,11 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.converter.ByteArrayMessageConverter; import org.springframework.messaging.converter.DefaultContentTypeResolver; import org.springframework.messaging.converter.MappingJackson2MessageConverter; import org.springframework.messaging.converter.MessageConverter; +import org.springframework.messaging.converter.StringMessageConverter; import org.springframework.messaging.simp.config.AbstractMessageBrokerConfiguration; import org.springframework.util.MimeTypeUtils; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; @@ -72,8 +74,10 @@ public class WebSocketMessagingAutoConfiguration { DefaultContentTypeResolver resolver = new DefaultContentTypeResolver(); resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON); converter.setContentTypeResolver(resolver); + messageConverters.add(new StringMessageConverter()); + messageConverters.add(new ByteArrayMessageConverter()); messageConverters.add(converter); - return true; + return false; } } diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfigurationTests.java index a560edd0ab..01cf4416a4 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/websocket/WebSocketMessagingAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 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. @@ -17,12 +17,15 @@ package org.springframework.boot.autoconfigure.websocket; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -39,6 +42,8 @@ import org.springframework.boot.context.web.ServerPortInfoApplicationContextInit import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.messaging.converter.CompositeMessageConverter; +import org.springframework.messaging.converter.MessageConverter; import org.springframework.messaging.converter.SimpleMessageConverter; import org.springframework.messaging.simp.annotation.SubscribeMapping; import org.springframework.messaging.simp.config.MessageBrokerRegistry; @@ -49,9 +54,11 @@ import org.springframework.messaging.simp.stomp.StompSession; import org.springframework.messaging.simp.stomp.StompSessionHandler; import org.springframework.messaging.simp.stomp.StompSessionHandlerAdapter; import org.springframework.stereotype.Controller; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.client.RestTemplate; import org.springframework.web.socket.client.standard.StandardWebSocketClient; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; +import org.springframework.web.socket.config.annotation.DelegatingWebSocketMessageBrokerConfiguration; import org.springframework.web.socket.config.annotation.EnableWebSocket; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @@ -90,7 +97,48 @@ public class WebSocketMessagingAutoConfigurationTests { } @Test - public void basicMessagingWithJson() throws Throwable { + public void basicMessagingWithJsonResponse() throws Throwable { + Object result = performStompSubscription("/app/json"); + assertThat(new String((byte[]) result)) + .isEqualTo(String.format("{%n \"foo\" : 5,%n \"bar\" : \"baz\"%n}")); + } + + @Test + public void basicMessagingWithStringResponse() throws Throwable { + Object result = performStompSubscription("/app/string"); + assertThat(new String((byte[]) result)).isEqualTo(String.format("string data")); + } + + @Test + public void customizedConverterTypesMatchDefaultConverterTypes() { + List customizedConverters = getCustomizedConverters(); + List defaultConverters = getDefaultConverters(); + assertThat(customizedConverters.size()).isEqualTo(defaultConverters.size()); + Iterator customizedIterator = customizedConverters.iterator(); + Iterator defaultIterator = defaultConverters.iterator(); + while (customizedIterator.hasNext()) { + assertThat(customizedIterator.next()) + .isInstanceOf(defaultIterator.next().getClass()); + } + } + + private List getCustomizedConverters() { + List customizedConverters = new ArrayList(); + WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration configuration = new WebSocketMessagingAutoConfiguration.WebSocketMessageConverterConfiguration(); + ReflectionTestUtils.setField(configuration, "objectMapper", new ObjectMapper()); + configuration.configureMessageConverters(customizedConverters); + return customizedConverters; + } + + @SuppressWarnings("unchecked") + private List getDefaultConverters() { + CompositeMessageConverter compositeDefaultConverter = new DelegatingWebSocketMessageBrokerConfiguration() + .brokerMessageConverter(); + return (List) ReflectionTestUtils + .getField(compositeDefaultConverter, "converters"); + } + + private Object performStompSubscription(final String topic) throws Throwable { EnvironmentTestUtils.addEnvironment(this.context, "server.port:0", "spring.jackson.serialization.indent-output:true"); this.context.register(WebSocketMessagingConfiguration.class); @@ -105,7 +153,7 @@ public class WebSocketMessagingAutoConfigurationTests { @Override public void afterConnected(StompSession session, StompHeaders connectedHeaders) { - session.subscribe("/app/data", new StompFrameHandler() { + session.subscribe(topic, new StompFrameHandler() { @Override public void handleFrame(StompHeaders headers, Object payload) { @@ -151,8 +199,7 @@ public class WebSocketMessagingAutoConfigurationTests { } fail("Response was not received within 30 seconds"); } - assertThat(new String((byte[]) result.get())) - .isEqualTo(String.format("{%n \"foo\" : 5,%n \"bar\" : \"baz\"%n}")); + return result.get(); } @Configuration @@ -197,11 +244,16 @@ public class WebSocketMessagingAutoConfigurationTests { @Controller static class MessagingController { - @SubscribeMapping("/data") - Data getData() { + @SubscribeMapping("/json") + Data json() { return new Data(5, "baz"); } + @SubscribeMapping("/string") + String string() { + return "string data"; + } + } static class Data {