3434import org .springframework .boot .context .web .NonEmbeddedServletContainerFactory ;
3535import org .springframework .context .annotation .Bean ;
3636import org .springframework .context .annotation .Configuration ;
37+ import org .springframework .util .Assert ;
3738import org .springframework .util .ClassUtils ;
3839import org .springframework .util .ReflectionUtils ;
3940import org .springframework .web .socket .WebSocketHandler ;
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