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

ServerEndpointExporter causes refresh to fail with java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available [SPR-12340] #16945

Closed
spring-projects-issues opened this issue Oct 16, 2014 · 6 comments
Assignees
Labels
in: web status: backported type: bug
Milestone

Comments

@spring-projects-issues
Copy link
Collaborator

@spring-projects-issues spring-projects-issues commented Oct 16, 2014

Andy Wilkinson opened SPR-12340 and commented

This is the same problem as #16725 but the symptom's changed. Sorry for not testing the fix when it was made in 4.0.7.

The failure's now an IllegalStateException:

Caused by: java.lang.IllegalStateException: javax.websocket.server.ServerContainer not available
	at org.springframework.util.Assert.state(Assert.java:385)
	at org.springframework.web.socket.server.standard.ServerEndpointExporter.afterPropertiesSet(ServerEndpointExporter.java:116)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
	... 15 more

The reason is still largely the same. In initApplicationContext, ServerEndpointExporter assumes that the ServletContext will be available on the WebApplicationContext. This isn't true in Spring Boot and leaves ServerEndpointExporter without a ServerContainer.

AFAICT, ServerEndpointExporter needs to defer its use of the ServletContext until ServletContextAware processing.


Affects: 4.0.7, 4.1.1

Issue Links:

  • #16725 ServerEndpointExporter causes application context refresh to fail with an NPE when used in a Spring Boot app

Referenced from: commits 7507560, 10328f1

Backported to: 4.0.8

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 16, 2014

Juergen Hoeller commented

So the problem with Boot is not just that the setServletContext call comes in after setApplicationContext... it even comes in after afterPropertiesSet? In a standard Spring container environment, afterPropertiesSet is defined to always come after the Aware interfaces... We're really bending this quite a bit here.

Anyway, we'll be able to deal with it through extra checks and multiple invocation paths to registerEndpoints. I'd just prefer for this not to be necessary.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 16, 2014

Andy Wilkinson commented

One further inspection, it's more subtle than my description above. The ordering of afterPropertiesSet and calls from the various …Aware interfaces is unchanged in Boot. The problem appears to be that ServerEndpointExporter is a BeanPostProcessor which causes it to be created early on in the application context's initialisation. In Boot, it's too early as the embedded Tomcat instance hasn't been started so there's no ServletContext available. My workaround has been to wrap it in a ServletContextAware bean:

@Bean
public ServletContextAware endpointExporterInitializer(final ApplicationContext applicationContext) {
    return new ServletContextAware() {
        @Override
        public void setServletContext(ServletContext servletContext) {
            ServerEndpointExporter exporter = new ServerEndpointExporter();
            exporter.setApplicationContext(applicationContext);
            exporter.afterPropertiesSet();
        }
    };
}

I realise now that this works, not because it's ServletContextAware, but because it's hiding the fact that it's a bean post-processor. Looking at the code for ServerEndpointExporter I can see that this will work fine for @ServerEndpoint-annotated beans as they're processed as part of afterPropertiesSet being called. However, ServerEndpointConfig beans will be ignored as they're processed as part of the BeanPostProcessor contract.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 16, 2014

Juergen Hoeller commented

Alright, thanks for the in-depth analysis, Andy - that helps a lot. I'll figure out how to deal with it :-)

Juergen

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 20, 2014

Juergen Hoeller commented

This is coming up in the next 4.1.2 snapshot now. I'll backport it to 4.0.8 later this week.

Juergen

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Oct 21, 2014

Andy Wilkinson commented

Thanks, Juergen. I've tested a 4.1.2 snapshot with a small Boot app that uses @ServerEndpoint and all is well.

@spring-projects-issues
Copy link
Collaborator Author

@spring-projects-issues spring-projects-issues commented Nov 28, 2018

Teh Kok How commented

I am using Spring Boot 2.1.0.RELEASE with Java 11 and Tomcat 9 deploying WAR into tomcat webapp and still see the same error. I added the workaround code snippet suggested but doesn't help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web status: backported type: bug
Projects
None yet
Development

No branches or pull requests

2 participants