33

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
membersound
  • 66,525
  • 139
  • 452
  • 886

5 Answers5

34

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
Tim
  • 18,795
  • 8
  • 63
  • 90
28

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 {
Artem Bilan
  • 92,176
  • 10
  • 73
  • 99
  • I tried `@EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class, EmbeddedServletContainerAutoConfiguration.class})` but still same error... It would be nice if the auto configuration for `spring-web` could be disabled by annotation without having to modify my main starter method... – membersound Apr 22 '15 at 14:33
  • Though your suggestion works, thanks! But anyhow it would be nice to disable the autoconfiguration annotation based only. – membersound Apr 22 '15 at 14:41
  • 7
    The `spring.main.web_environment=false` is better though... No need to code any Java :-) – Artem Bilan Apr 22 '15 at 14:43
  • @membersound I had the same problem today. I ended up ditching RestTemplate for Retrofit: http://square.github.io/retrofit/ ... for one, it gets rid of the spring-web dependency from my classpath. For two, it's much easier to reason about and read. – jamsesso Jan 11 '16 at 02:56
14

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

geoand
  • 49,266
  • 16
  • 140
  • 156
  • The linked page doesn't give any information about the `spring.main.web-application-type` property though (when I write this), not even what the valid values are. Googling for `Spring WebApplicationType API` will reveal that the valid values are `servlet`, `reactive` and `none` (with lower-case like that, I guess). – ddekany Feb 15 '18 at 21:36
  • @ddekany They must have changed the documentation. Thanks for pointing this out! – geoand Feb 16 '18 at 07:40
13

This works in Spring Boot 2.x

public static void main(String[] args) {
   new SpringApplicationBuilder(MyApplication.class)
            .web(WebApplicationType.NONE)
            .build()
            .run(args);
}
Andy
  • 139
  • 1
  • 3
4

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!

FoggyDay
  • 10,517
  • 4
  • 24
  • 33