Reputation: 649
Im trying to deploy a springboot rest api to google cloud's app engine, However i'm getting this error:
org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
Which is caused by this class, which extends websecurityConfigurerAdapter to be exact:
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
APIUserDetailsService apiUserDetailsService;
@Bean
public DaoAuthenticationProvider authProvider() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(apiUserDetailsService);
authProvider.setPasswordEncoder(passwordEncoder());
return authProvider;
}
private static final String[] AUTH_WHITELIST = {"/hello"};
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors().and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(STATELESS).and()
.authorizeRequests()
.antMatchers(AUTH_WHITELIST).permitAll()
.anyRequest().authenticated()
.and()
.httpBasic();
http.headers().frameOptions().disable();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Removing this class completely fixes the error, the app deploys on the app engine and runs perfectly, albeit at the expense of no security. From what i can understand so far it seems that we have to use google app engine's web server, instead of the default tomcat embedded in spring. Therefore when the app deploys it tries to extend WebSecurityConfigurerAdapter which doesnt exist as there is no embeded tomcat web server. Im I have been trying to find a way to make it use googles web server, does anyone know of a way to make this work on google app engine?
POM xml:
<parent>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-sql-mysql</artifactId>
<version>1.2.8.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
</project>
main:
@SpringBootApplication
@EnableCaching
public class OwlServerApplication {
public static void main(String[] args) {
SpringApplication.run(OwlServerApplication.class, args);
}
Full stack trace of error:
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:162)
at
org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:582)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh (ServletWebServerApplicationContext.java:144)
at
org.springframework.boot.SpringApplication.refresh (SpringApplication.java:767)
at
org.springframework.boot.SpringApplication.refresh (SpringApplication.java:759)
at
org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:426)
at
org.springframework.boot.SpringApplication.run (SpringApplication.java:326)
at
org.springframework.boot.SpringApplication.run (SpringApplication.java:1309)
at
org.springframework.boot.SpringApplication.run (SpringApplication.java:1298)
at
com.owl.owlserver.OwlServerApplication.main (OwlServerApplication.java:12)
Caused by: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getWebServerFactory (ServletWebServerApplicationContext.java:209)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer (ServletWebServerApplicationContext.java:179)
at
org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh (ServletWebServerApplicationContext.java:159)
by adding the. 3.1 servlet we get this error now:
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.example.demo.DemoApplication]; nested exception is java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.class] cannot be opened because it does not exist
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:189)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:331)
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311)
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112)
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:746)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:564)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:144)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:782)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:774)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:439)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:339)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1340)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1329)
at com.example.demo.DemoApplication.main(DemoApplication.java:18)
Caused by: java.io.FileNotFoundException: class path resource [org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurerAdapter.class] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:187)
at org.springframework.core.type.classreading.SimpleMetadataReader.getClassReader(SimpleMetadataReader.java:55)
at org.springframework.core.type.classreading.SimpleMetadataReader.<init>(SimpleMetadataReader.java:49)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:103)
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.createMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:86)
at org.springframework.boot.type.classreading.ConcurrentReferenceCachingMetadataReaderFactory.getMetadataReader(ConcurrentReferenceCachingMetadataReaderFactory.java:73)
at org.springframework.core.type.classreading.SimpleMetadataReaderFactory.getMetadataReader(SimpleMetadataReaderFactory.java:81)
at org.springframework.context.annotation.ConfigurationClassParser.asSourceClass(ConfigurationClassParser.java:696)
at org.springframework.context.annotation.ConfigurationClassParser$SourceClass.getSuperClass(ConfigurationClassParser.java:1010)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:341)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:199)
at org.springframework.context.annotation.ConfigurationClassParser.doProcessConfigurationClass(ConfigurationClassParser.java:304)
at org.springframework.context.annotation.ConfigurationClassParser.processConfigurationClass(ConfigurationClassParser.java:250)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:207)
at org.springframework.context.annotation.ConfigurationClassParser.parse(ConfigurationClassParser.java:175)
... 14 common frames omitted
it seems that the app engine cannot find the websecurityconfigurerAdapter class.
Upvotes: 1
Views: 360
Reputation: 459
Although I am not sure what is causing this problem, a common solution here is to configure auto-configuration, in the following way.
@EnableAutoConfiguration
@SpringBootApplication
@EnableCaching
public class OwlServerApplication {
public static void main(String[] args) {
SpringApplication.run(OwlServerApplication.class, args);
}
This annotation @EnableAutoConfiguration
makes sure that the configuration beans can be scanned from sibling or child package paths, and can also be auto-configured.
Meanwhile, make sure that you have ApplicationSecurityConfig
class in the same or a sibling package.
Neither Springboot nor Google App Engine explicitly mentions this Servlet version problem.
I found this answer https://stackoverflow.com/a/28869503/15262845 here.
If I am guessing it right (I never worked with Google App Engine before), Google App Engine supports Sevlet 2.5 but it requires Servlet 3.1 above to properly initialize the bean extending WebSecurityConfigurerAdapter
.
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
See also the official guidance from Google Cloud Engine for migrating to Servlet 3.1 https://javaee.github.io/servlet-spec/ See also the answer Upgrade App Engine servlet-api-2.5 to servlet-api-3.1?
Let me know if it works or there is more to discuess.
Upvotes: 1