Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot upgrade to WebSocket connection when using Spring 4 WebSocket with embedded Tomcat 8.0.0-RC1 [SPR-10841] #15467

Closed
spring-issuemaster opened this issue Aug 16, 2013 · 6 comments
Assignees

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Aug 16, 2013

Sergey Shcherbakov opened SPR-10841 and commented

I'm building a Spring 4 driven application with an embedded Tomcat 8 and SockJS to support WebSocket clients.
The latest 4.0.0.BUILD-SNAPSHOT (14.08.2013) as well as 4.0.0.M2 cannot upgrade the incoming HTTP connection to WS with the following exception (for the snapshot version):

2013-08-16 10:49:02,711 15913 ERROR [http-nio-8080-exec-4] org.apache.coyote.http11.Http11NioProtocol - Error reading request, ignored                    
java.lang.NullPointerException: null
at org.apache.tomcat.websocket.server.WsRemoteEndpointImplServer.<init>(WsRemoteEndpointImplServer.java:57) ~[tomcat-embed-core-8.0.0-RC1.jar:8.0.0-RC1]
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:116) ~[tomcat-embed-core-8.0.0-RC1.jar:8.0.0-RC1]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:658) ~[tomcat-embed-core-8.0.0-RC1.jar:8.0.0-RC1]
at org.apache.coyote.http11.Http11NioProtocol$Http11ConnectionHandler.process(Http11NioProtocol.java:223) [tomcat-embed-core-8.0.0-RC1.jar:8.0.0-RC1]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1592) [tomcat-embed-core-8.0.0-RC1.jar:8.0.0-RC1]
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1550) [tomcat-embed-core-8.0.0-RC1.jar:8.0.0-RC1]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_17]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_17]
at java.lang.Thread.run(Thread.java:722) [na:1.7.0_17]

Affects: 4.0 M2

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 16, 2013

Rossen Stoyanchev commented

Have you tried the standalone version? I've been using that with both 8.0 RC1 and Tomcat trunk so it would be good to confirm if this is due to the standalone vs embedded version, or something specific in your code that's triggering it.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 19, 2013

Sergey Shcherbakov commented

Hi Rossen,

The NPE is caused by the webSocketContainer which is not getting passed to the preInit() method.
I see that the TomcatRequestUpgradeStrategy is passing null to the preInit() method because the ServerHttpRequest.getServletRequest().getServletContext().getAttribute("javax.websocket.server.ServerContainer")
returns null, i.e. the servletContext attribute is not set when my embedded Tomcat gets started by the spring-boot (this may be a spring-boot issue, I looking into it further).

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 19, 2013

Rossen Stoyanchev commented

It sounds SCI scanning is not enabled. It's what underlies the new WebSocket support so if not enabled, there is no ServerContainer. You might want to see https://issues.apache.org/bugzilla/show_bug.cgi?id=55312.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 19, 2013

Sergey Shcherbakov commented

I have found the way to fix the issue locally.
The following customization code suffice to switch on the WS SCI scanning for embedded Tomcat bootstrapped by spring-boot:

@Bean
public TomcatEmbeddedServletContainerFactory tomcatContainerFactory() {
	TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
	factory.setTomcatContextCustomizers(Arrays.asList(new TomcatContextCustomizer[] {
			tomcatContextCustomizer()
	}));
	return factory;
}

@Bean 
public TomcatContextCustomizer tomcatContextCustomizer() {
	return new TomcatContextCustomizer() {
		@Override
		public void customize(Context context) {
			context.addServletContainerInitializer(new WsSci(), null);
		}
	};
}

The WS upgrade and communication works perfectly after that.
Thanks for the help! The issue can probably be closed now.

PS: The spring-boot team might be interested in switching this customization on by default.

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 19, 2013

@spring-issuemaster
Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Aug 19, 2013

Rossen Stoyanchev commented

You might want to open an issue with Spring Boot. Doesn't seem to be anything we can fix in the core Spring framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.