Skip to content

Commit 86054a9

Browse files
author
Dave Syer
committed
Use reflection to setup Websocket SCI so it works in Tomcat 8
Annoyingly this is necessary if we want to support Tomcat 7 and 8 since the package name changed. Fixes gh-554
1 parent 45315a9 commit 86054a9

File tree

1 file changed

+35
-5
lines changed

1 file changed

+35
-5
lines changed

spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/websocket/WebSocketAutoConfiguration.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@
1919
import javax.servlet.Servlet;
2020

2121
import org.apache.catalina.Context;
22-
import org.apache.catalina.deploy.ApplicationListener;
2322
import org.apache.catalina.startup.Tomcat;
2423
import org.apache.commons.logging.Log;
2524
import org.apache.commons.logging.LogFactory;
25+
import org.springframework.beans.BeanUtils;
2626
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
2727
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
2828
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@@ -34,6 +34,8 @@
3434
import org.springframework.boot.context.web.NonEmbeddedServletContainerFactory;
3535
import org.springframework.context.annotation.Bean;
3636
import org.springframework.context.annotation.Configuration;
37+
import org.springframework.util.ClassUtils;
38+
import org.springframework.util.ReflectionUtils;
3739
import org.springframework.web.socket.WebSocketHandler;
3840

3941
/**
@@ -50,10 +52,11 @@
5052
@AutoConfigureBefore(EmbeddedServletContainerAutoConfiguration.class)
5153
public class WebSocketAutoConfiguration {
5254

53-
private static Log logger = LogFactory.getLog(WebSocketAutoConfiguration.class);
55+
private static final String TOMCAT_7_LISTENER_TYPE = "org.apache.catalina.deploy.ApplicationListener";
56+
57+
private static final String TOMCAT_8_LISTENER_TYPE = "org.apache.tomcat.util.descriptor.web.ApplicationListener";
5458

55-
private static final ApplicationListener WS_APPLICATION_LISTENER = new ApplicationListener(
56-
"org.apache.tomcat.websocket.server.WsContextListener", false);
59+
private static Log logger = LogFactory.getLog(WebSocketAutoConfiguration.class);
5760

5861
@Bean
5962
@ConditionalOnMissingBean(name = "websocketContainerCustomizer")
@@ -76,7 +79,7 @@ public void customize(ConfigurableEmbeddedServletContainer container) {
7679
.addContextCustomizers(new TomcatContextCustomizer() {
7780
@Override
7881
public void customize(Context context) {
79-
context.addApplicationListener(WS_APPLICATION_LISTENER);
82+
addListener(context, findListenerType());
8083
}
8184
});
8285
}
@@ -86,4 +89,31 @@ public void customize(Context context) {
8689
return customizer;
8790

8891
}
92+
93+
private static Class<?> findListenerType() {
94+
if (ClassUtils.isPresent(TOMCAT_7_LISTENER_TYPE, null)) {
95+
return ClassUtils.resolveClassName(TOMCAT_7_LISTENER_TYPE, null);
96+
}
97+
if (ClassUtils.isPresent(TOMCAT_8_LISTENER_TYPE, null)) {
98+
return ClassUtils.resolveClassName(TOMCAT_8_LISTENER_TYPE, null);
99+
}
100+
throw new UnsupportedOperationException(
101+
"Cannot find Tomcat 7 or 8 ApplicationListener class");
102+
}
103+
104+
/**
105+
* Instead of registering the WsSci directly as a ServletContainerInitializer, we use
106+
* the ApplicationListener provided by Tomcat. Unfortunately the ApplicationListener
107+
* class moved packages in Tomcat 8 so we have to do it reflectively.
108+
*
109+
* @param context the current context
110+
* @param listenerType the type of listener to add
111+
*/
112+
private static void addListener(Context context, Class<?> listenerType) {
113+
Object instance = BeanUtils.instantiateClass(ClassUtils
114+
.getConstructorIfAvailable(listenerType, String.class, boolean.class),
115+
"org.apache.tomcat.websocket.server.WsContextListener", false);
116+
ReflectionUtils.invokeMethod(ClassUtils.getMethod(context.getClass(),
117+
"addApplicationListener", listenerType), context, instance);
118+
}
89119
}

0 commit comments

Comments
 (0)