Skip to content

Commit 4ede9cd

Browse files
author
Phillip Webb
committed
Support websockets with Tomcat 8.0.8
Fixes gh-1210
1 parent 54f1b29 commit 4ede9cd

File tree

1 file changed

+33
-27
lines changed

1 file changed

+33
-27
lines changed

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

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
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.Assert;
3738
import org.springframework.util.ClassUtils;
3839
import org.springframework.util.ReflectionUtils;
3940
import org.springframework.web.socket.WebSocketHandler;
@@ -45,6 +46,7 @@
4546
* already be there.
4647
*
4748
* @author Dave Syer
49+
* @author Phillip Webb
4850
*/
4951
@Configuration
5052
@ConditionalOnClass(name = "org.apache.tomcat.websocket.server.WsSci", value = {
@@ -56,38 +58,35 @@ public class WebSocketAutoConfiguration {
5658

5759
private static final String TOMCAT_8_LISTENER_TYPE = "org.apache.tomcat.util.descriptor.web.ApplicationListener";
5860

61+
private static final String WS_LISTENER = "org.apache.tomcat.websocket.server.WsContextListener";
62+
5963
private static Log logger = LogFactory.getLog(WebSocketAutoConfiguration.class);
6064

6165
@Bean
6266
@ConditionalOnMissingBean(name = "websocketContainerCustomizer")
6367
public EmbeddedServletContainerCustomizer websocketContainerCustomizer() {
64-
65-
EmbeddedServletContainerCustomizer customizer = new EmbeddedServletContainerCustomizer() {
68+
return new EmbeddedServletContainerCustomizer() {
6669

6770
@Override
6871
public void customize(ConfigurableEmbeddedServletContainer container) {
6972
if (container instanceof NonEmbeddedServletContainerFactory) {
70-
logger.info("NonEmbeddedServletContainerFactory detected. Websockets support should be native so this normally is not a problem.");
73+
logger.info("NonEmbeddedServletContainerFactory detected. Websockets "
74+
+ "support should be native so this normally is not a problem.");
7175
return;
7276
}
73-
if (!(container instanceof TomcatEmbeddedServletContainerFactory)) {
74-
throw new IllegalStateException(
75-
"Websockets are currently only supported in Tomcat (found "
76-
+ container.getClass() + "). ");
77-
}
78-
((TomcatEmbeddedServletContainerFactory) container)
79-
.addContextCustomizers(new TomcatContextCustomizer() {
80-
@Override
81-
public void customize(Context context) {
82-
addListener(context, findListenerType());
83-
}
84-
});
77+
Assert.state(container instanceof TomcatEmbeddedServletContainerFactory,
78+
"Websockets are currently only supported in Tomcat (found "
79+
+ container.getClass() + "). ");
80+
TomcatEmbeddedServletContainerFactory tomcatContainer = (TomcatEmbeddedServletContainerFactory) container;
81+
tomcatContainer.addContextCustomizers(new TomcatContextCustomizer() {
82+
@Override
83+
public void customize(Context context) {
84+
addListener(context, findListenerType());
85+
}
86+
});
8587
}
8688

8789
};
88-
89-
return customizer;
90-
9190
}
9291

9392
private static Class<?> findListenerType() {
@@ -97,23 +96,30 @@ private static Class<?> findListenerType() {
9796
if (ClassUtils.isPresent(TOMCAT_8_LISTENER_TYPE, null)) {
9897
return ClassUtils.resolveClassName(TOMCAT_8_LISTENER_TYPE, null);
9998
}
100-
throw new UnsupportedOperationException(
101-
"Cannot find Tomcat 7 or 8 ApplicationListener class");
99+
// With Tomcat 8.0.8 ApplicationListener is not required
100+
return null;
102101
}
103102

104103
/**
105104
* Instead of registering the WsSci directly as a ServletContainerInitializer, we use
106105
* the ApplicationListener provided by Tomcat. Unfortunately the ApplicationListener
107-
* class moved packages in Tomcat 8 so we have to do it reflectively.
108-
*
106+
* class moved packages in Tomcat 8 and been deleted in 8.0.8 so we have to use
107+
* reflection.
109108
* @param context the current context
110109
* @param listenerType the type of listener to add
111110
*/
112111
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);
112+
if (listenerType == null) {
113+
ReflectionUtils.invokeMethod(ClassUtils.getMethod(context.getClass(),
114+
"addApplicationListener", String.class), context, WS_LISTENER);
115+
116+
}
117+
else {
118+
Object instance = BeanUtils.instantiateClass(
119+
ClassUtils.getConstructorIfAvailable(listenerType, String.class,
120+
boolean.class), WS_LISTENER, false);
121+
ReflectionUtils.invokeMethod(ClassUtils.getMethod(context.getClass(),
122+
"addApplicationListener", listenerType), context, instance);
123+
}
118124
}
119125
}

0 commit comments

Comments
 (0)