When configuring your spring boot application to use netty as embedded http server, the code fails to compile due to missing dependencies. When extending the WebSecurityConfigurerAdapter or the BasicAuthenticationEntryPoint, the following errors occur:
@Configuration
@EnableWebSecurity
public class ABCConfig extends WebSecurityConfigurerAdapter {
..
}
Error:(21, 8) java: cannot access javax.servlet.Filter
class file for javax.servlet.Filter not found
@Component
public class BasicAuthenticationPoint extends BasicAuthenticationEntryPoint {
..
}
Error:(7, 8) java: cannot access javax.servlet.ServletException
class file for javax.servlet.ServletException not found
Gradle Configuration:
spring-boot-gradle-plugin:2.0.1.RELEASE
...
configurations.compile {
exclude module: 'spring-boot-starter-tomcat'
}
dependencies{
compile("org.springframework.boot:spring-boot-starter-web")
compile("org.springframework.boot:spring-boot-starter-reactor-netty")
compile("org.springframework.boot:spring-boot-starter-webflux")
compile("org.springframework.boot:spring-boot-starter-security")
...
}
Including the servlet-api dependency (javax.servlet:javax.servlet-api:3.0.1) fixes the compile problem but the server start fails because no implementation of the ServletWebServerFactory is provided. The console output looks as following:
2018-04-25 12:28:00.695 ERROR 19594 --- [ main] o.s.boot.SpringApplication : Application run failed
org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:155) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:544) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
The mentioned examples above work with Tomcat as well as with Jetty. I would expect it to work with Netty as well.
Thanks for reaching out.
It seems that there is some confusion. Spring Security provides support for a servlet environment (Tomcat / Jetty) and reactive programming model (i.e. netty) separately. This is necessary because they are entirely different programming models. If you want to use netty, your dependencies should remove spring-boot-starter-web.
You can find a working sample at https://github.com/spring-projects/spring-security/tree/5.0.5.RELEASE/samples/javaconfig/hellowebflux You can find a working Boot sample at https://github.com/spring-projects/spring-boot/tree/v2.0.1.RELEASE/spring-boot-samples/spring-boot-sample-secure-webflux
More on that in the Boot docs, but including both Spring MVC and Spring WebFlux means you want to use Spring MVC with a Servlet container as you server + the WebClient from WebFlux for remote calls.
To run Netty as your server, you would include the WebFlux starter only. In that scenario the Servlet API is not at all required on the classpath.
Just to add for anyone wondering, simply removing spring-boot-starter-web from your dependencies won't solve the issue for the code above. If you are intended to skip servlet stack completely, your security configuration shall be different - you should not be extending WebSecurityConfigurerAdapter, but adjusting SecurityWebFilterChain instead. Please refer to docs
Most helpful comment
Just to add for anyone wondering, simply removing spring-boot-starter-web from your dependencies won't solve the issue for the code above. If you are intended to skip servlet stack completely, your security configuration shall be different - you should not be extending WebSecurityConfigurerAdapter, but adjusting SecurityWebFilterChain instead. Please refer to docs