How to prevent spring-boot autoconfiguration for spring-web?

守給你的承諾、 提交于 2019-12-03 08:16:36

问题


I'm using spring-boot and added spring-web dependency in maven pom, to make use of RestTemplate.

Now spring tries to initialize an EmbeddedServletContext. How can I prevent it?

Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:133)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:686)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:957)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:946)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:183)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:156)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130)
    ... 8 more

回答1:


For reference: This use case is documented in the Spring Boot Reference Guide:

Not all Spring applications have to be web applications (or web services). If you want to execute some code in a main method, but also bootstrap a Spring application to set up the infrastructure to use, then it’s easy with the SpringApplication features of Spring Boot. A SpringApplication changes its ApplicationContext class depending on whether it thinks it needs a web application or not. The first thing you can do to help it is to just leave the servlet API dependencies off the classpath. If you can’t do that (e.g. you are running 2 applications from the same code base) then you can explicitly call SpringApplication.setWebEnvironment(false), or set the applicationContextClass property (through the Java API or with external properties). Application code that you want to run as your business logic can be implemented as a CommandLineRunner and dropped into the context as a @Bean definition.

application.properties:

spring.main.web-environment=false   #webEnvironment property



回答2:


First trick:

public static void main(String[] args) throws Exception {
    ConfigurableApplicationContext ctx = new SpringApplicationBuilder(Application.class)
                .web(false)
                .run(args);
}

Second:

@Configuration
@EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class)
public class Application {



回答3:


Although the legacy way of disabling the web environment (as mentioned in @Tim's answer) still works in Spring Boot 2.x, however the new preferred way is by setting the following property

spring.main.web-application-type=none

Here is the enum that defines the allowed values




回答4:


This works in Spring Boot 2.x

public static void main(String[] args) {
   new SpringApplicationBuilder(MyApplication.class)
            .web(WebApplicationType.NONE)
            .build()
            .run(args);
}



回答5:


I was trying to build a Reactive Web App with Spring Boot 2.06 and got this 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:155) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-5.0.10.RELEASE.jar:5.0.10.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1242) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1230) [spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at com.vogella.springboot2.Test3Application.main(Test3Application.java:10) [main/:na]
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:204) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:178) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:152) ~[spring-boot-2.0.6.RELEASE.jar:2.0.6.RELEASE]
    ... 8 common frames omitted

This link explained the problem, and offered two suggestions:

https://vividcode.io/Fixing-Spring-Boot-error-Unable-to-start-ServletWebServerApplicationContext-due-to-missing-ServletWebServerFactory-bean/

I was building a new Spring WebFlux application with Spring Boot. After downloading the project template from start.spring.io, I added some third-party dependencies and tried to start the application. Then I met the error org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean....

The error message is the clue to the solution. It says Unable to start ServletWebServerApplicationContext, but my project is using WebFlux and it’s a reactive web project, not a servlet-based Spring Web MVC project.

Debugging into the Spring source code helped me find the cause. In the method deduceWebApplicationType of org.springframework.boot.SpringApplication, the web application type is set to WebApplicationType.REACTIVE only when classes of Spring Web MVC is not present in the CLASSPATH.

The solution is easy once the root cause is identified. We can either:

Update Maven dependencies to exclude spring-webmvc, or Set the web application type to WebApplicationType.REACTIVE explicitly, as shown below.

@SpringBootApplication class MyApplication
fun main(args: Array<String>) {
    val app = SpringApplication(MyApplication::class.java)
    app.webApplicationType = WebApplicationType.REACTIVE
    app.run(*args)
}

Unfortunately, neither of these solutions worked for me. Instead, I adapted geoand's response, and added this to my application.properties:

spring.main.web-application-type=reactive

Voila! Problem resolved!



来源:https://stackoverflow.com/questions/29800584/how-to-prevent-spring-boot-autoconfiguration-for-spring-web

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!