Skip to content

Commit

Permalink
Strip out most of websocket autoconfig
Browse files Browse the repository at this point in the history
... leaving only the embedded Tomcat enabling feature (registering
the WsSci).

Fixes part of spring-projectsgh-65
  • Loading branch information
Dave Syer authored and mdeinum committed Jun 6, 2014
1 parent 1168430 commit 155b302
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 99 deletions.
Expand Up @@ -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
* <code>spring-websocket</code> is detected on the classpath then we add a
* {@link DefaultSockJsService} and an MVC handler mapping to
* <code>/&lt;beanName&gt;/**</code> for all of the <code>WebSocketHandler</code> beans
* that have a bean name beginning with "/".
* Auto configuration for websocket server in embedded Tomcat. If
* <code>spring-websocket</code> 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);

// Nested class to avoid having to load WebSocketConfigurer before conditions are
// evaluated
@Configuration
protected static class WebSocketRegistrationConfiguration implements
BeanPostProcessor, BeanFactoryAware, WebSocketConfigurer {

private final Map<String, WebSocketHandler> prefixes = new HashMap<String, WebSocketHandler>();

private ListableBeanFactory beanFactory;
private static final ApplicationListener WS_APPLICATION_LISTENER = new ApplicationListener(
"org.apache.tomcat.websocket.server.WsContextListener", false);

@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;
}

}
Expand Up @@ -23,6 +23,9 @@
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;
Expand All @@ -34,7 +37,15 @@

@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) {
Expand All @@ -55,12 +66,12 @@ public GreetingService greetingService() {
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);
}
Expand Down

0 comments on commit 155b302

Please sign in to comment.