diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
index 8f4101a839..f1ba2ee74f 100644
--- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
+++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java
@@ -16,122 +16,45 @@
package org.springframework.boot.autoconfigure.websocket;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletContainerInitializer;
+import javax.servlet.Servlet;
import org.apache.catalina.Context;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.BeansException;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.ListableBeanFactory;
-import org.springframework.beans.factory.config.BeanPostProcessor;
+import org.apache.catalina.deploy.ApplicationListener;
+import org.apache.catalina.startup.Tomcat;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
-import org.springframework.util.ClassUtils;
import org.springframework.web.socket.WebSocketHandler;
-import org.springframework.web.socket.config.annotation.EnableWebSocket;
-import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
-import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
-import org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService;
/**
- * Auto configuration for websocket server (and sockjs in particular). Users should be
- * able to just define beans of type {@link WebSocketHandler}. If
- * spring-websocket is detected on the classpath then we add a
- * {@link DefaultSockJsService} and an MVC handler mapping to
- * /<beanName>/** for all of the WebSocketHandler beans
- * that have a bean name beginning with "/".
+ * Auto configuration for websocket server in embedded Tomcat. If
+ * spring-websocket is detected on the classpath then we add a listener that
+ * installs the Tomcat Websocket initializer. In a non-embedded container it should
+ * already be there.
*
* @author Dave Syer
*/
@Configuration
-@ConditionalOnClass({ WebSocketHandler.class })
+@ConditionalOnClass(name = "org.apache.tomcat.websocket.server.WsSci", value = {
+ Servlet.class, Tomcat.class, WebSocketHandler.class })
@AutoConfigureBefore(EmbeddedServletContainerAutoConfiguration.class)
-@ConditionalOnMissingBean(WebSocketConfigurer.class)
-@EnableWebSocket
public class WebSocketAutoConfiguration {
- private static Log logger = LogFactory.getLog(WebSocketAutoConfiguration.class);
+ private static final ApplicationListener WS_APPLICATION_LISTENER = new ApplicationListener(
+ "org.apache.tomcat.websocket.server.WsContextListener", false);
- // Nested class to avoid having to load WebSocketConfigurer before conditions are
- // evaluated
- @Configuration
- protected static class WebSocketRegistrationConfiguration implements
- BeanPostProcessor, BeanFactoryAware, WebSocketConfigurer {
-
- private final Map prefixes = new HashMap();
-
- private ListableBeanFactory beanFactory;
-
- @Override
- public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
- this.beanFactory = (ListableBeanFactory) beanFactory;
- }
-
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException {
- return bean;
- }
-
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- if (bean instanceof WebSocketHandler && beanName.startsWith("/")) {
- this.prefixes.put(beanName, (WebSocketHandler) bean);
+ @Bean
+ public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
+ TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory() {
+ @Override
+ protected void postProcessContext(Context context) {
+ context.addApplicationListener(WS_APPLICATION_LISTENER);
}
- return bean;
- }
-
- private WebSocketHandler getHandler(String prefix) {
- return this.prefixes.get(prefix);
- }
-
- private String[] getPrefixes() {
- return this.prefixes.keySet().toArray(new String[this.prefixes.size()]);
- }
-
- @Override
- public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
- // Force initialization of WebSocketHandler beans
- this.beanFactory.getBeansOfType(WebSocketHandler.class);
- for (String prefix : getPrefixes()) {
- logger.info("Adding SockJS handler: " + prefix);
- registry.addHandler(getHandler(prefix), prefix).withSockJS();
- }
- }
-
- }
-
- @Configuration
- @ConditionalOnClass(name = "org.apache.tomcat.websocket.server.WsSci")
- protected static class TomcatWebSocketConfiguration {
-
- @Bean
- public TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory() {
- TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory() {
- @Override
- protected void postProcessContext(Context context) {
- context.addServletContainerInitializer(
- (ServletContainerInitializer) BeanUtils
- .instantiate(ClassUtils.resolveClassName(
- "org.apache.tomcat.websocket.server.WsSci",
- null)), null);
- }
- };
- return factory;
- }
-
+ };
+ return factory;
}
}
diff --git a/spring-boot-samples/spring-boot-sample-websocket/src/main/java/samples/websocket/config/SampleWebSocketsApplication.java b/spring-boot-samples/spring-boot-sample-websocket/src/main/java/samples/websocket/config/SampleWebSocketsApplication.java
index 6233fd048c..8d84d2fcd2 100644
--- a/spring-boot-samples/spring-boot-sample-websocket/src/main/java/samples/websocket/config/SampleWebSocketsApplication.java
+++ b/spring-boot-samples/spring-boot-sample-websocket/src/main/java/samples/websocket/config/SampleWebSocketsApplication.java
@@ -23,6 +23,9 @@ import org.springframework.boot.context.web.SpringBootServletInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.WebSocketHandler;
+import org.springframework.web.socket.config.annotation.EnableWebSocket;
+import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
+import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;
import org.springframework.web.socket.handler.PerConnectionWebSocketHandler;
import samples.websocket.client.GreetingService;
@@ -34,7 +37,15 @@ import samples.websocket.snake.SnakeWebSocketHandler;
@Configuration
@EnableAutoConfiguration
-public class SampleWebSocketsApplication extends SpringBootServletInitializer {
+@EnableWebSocket
+public class SampleWebSocketsApplication extends SpringBootServletInitializer implements
+ WebSocketConfigurer {
+
+ @Override
+ public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
+ registry.addHandler(echoWebSocketHandler(), "/echo").withSockJS();
+ registry.addHandler(snakeWebSocketHandler(), "/snake").withSockJS();
+ }
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
@@ -55,12 +66,12 @@ public class SampleWebSocketsApplication extends SpringBootServletInitializer {
return new SimpleGreetingService();
}
- @Bean(name = "/echo")
+ @Bean
public WebSocketHandler echoWebSocketHandler() {
return new EchoWebSocketHandler(echoService());
}
- @Bean(name = "/snake")
+ @Bean
public WebSocketHandler snakeWebSocketHandler() {
return new PerConnectionWebSocketHandler(SnakeWebSocketHandler.class);
}