In this short article, we are going to shed light on a common Spring Boot error: ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean.

We will first start with some background on what is ApplicationContext. Then, we will dig down into the rabbit hole to see how to reproduce the error and how to fix it.

So let’s get started

What is ApplicationContext

ApplicationContext is one of the bone stones of Spring applications.

It’s the central interface that provides configuration for spring-based applications. It’s responsible for assembling, instantiating and managing Spring beans.

Every Spring web application has an associated web application context which is always an instance of WebApplicationContext.

In short, WebApplicationContext is a simple extension of the ApplicationContext which uses a contained ServletWebServerFactory bean to bootstrap itself, initialize and run a web server.

Understanding ApplicationContextException

The error Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean is self-explanatory. It states that Spring Boot fails to find a ServletWebServerFactory bean in the ApplicationContext.

Hence, Spring Boot fails to start the ServletWebServerApplicationContext. As we already said, ServletWebServerApplicationContext needs a ServletWebServerFactory bean to start and bootstrap itself.

One of the main causes of this error is forgetting to annotate the Spring Boot main class with the @SpringBootApplication annotation.

For web applications, missing spring-boot-starter-web dependency can be a reason to produce the error. Excluding spring-boot-starter-tomcat can be also one of the main causes of the error.

Another common reason is including web dependencies such as spring-webmvc in the classpath of a non-web Spring application.

The presence of these dependencies tells Spring Boot to consider the application as a web application which is not the case. Hence the error.

Practical Example

Now, let’s dive into how to reproduce our Spring Boot ApplicationContextException error.

Let’s suppose we want to create a simple Spring Boot application with a single main class. For instance, consider MainApp class:

    
        public class MainApp {
            public static void main(String[] args) {
                SpringApplication.run(MainApp.class, args);
            }
        }
    

Now, let’s run our application as a Java Application and see the output:

    
        19:51:49.106 [main] ERROR 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:162)
            at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:576)
            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:1311)
            at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300)
            at com.baeldung.applicationcontextexception.MainEntryPoint.main(MainEntryPoint.java:10)
        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)
            ... 9 common frames omitted
    

As we can see, Spring Boot fails to start the application and the main cause here is that our main class is missing the @SpringBootApplication annotation.

How to Solve the Error

Now that we have reproduced the error, let’s find a way to solve it. The best solution is to annotate our main class MainApp with @SpringBootApplication.

Spring Boot provides @SpringBootApplication annotation as a short-cut for:

  • @Configuration

  • @ComponentScan

  • @EnableAutoConfgiuration

It enables two of the most important features provided by Spring Boot: auto-configuration and component scan.

By annotating our main class with @SpringBootApplication, we tell Spring Boot to auto-configure all the beans required for application startup.

Another way to fix this problem is to disable the webserver for non-web applications. By design, Spring Boot automatically starts a web server if the app classpath contains the necessary dependencies.

We can always override this behavior by defining the Spring property spring.main.web-application-type in application.properties:

    
        spring.main.web-application-type=none
    

Or in YAML:

    
        spring:
            main:
                web-application-type: none
    

We can also use SpringApplicationBuilder to accomplish the same thing:

    
        public class MainClassApp {
            public static void main(String[] args) {
                new SpringApplicationBuilder(MainClassApp.class)
                    .web(false)
                    .run(args);
            }
        }
    

Please keep in mind that starting from Spring Boot 2, we can use WebApplicationType to define a specific type for our application:

  • NONE: The application should not run as a web application

  • REACTIVE: The application should run as a reactive web application

  • SERVLET: The application should run as a servlet-based web application

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

For web based applications, one of the solutions would be updating the main class to extend SpringBootServletInitializer:

    
        @SpringBootApplication
        public class MainClassApp extends SpringBootServletInitializer{
            @Override
            protected SpringApplicationBuilder configure(SpringApplicationBuilder application){
               return application.sources(MainClassApp.class);
            }
            public static void main(String[] args) {
                SpringApplication.run(MainClassApp.class, args);
            }
        }
    

For reactive applications, we need to make sure to exclude spring-webmvc from Maven dependencies and define WebApplicationType.REACTIVE explicitly.

Conclusion

That’s all. In this short article, we learned how to produce and fix Spring Boot error: org.springframework.context.ApplicationContextException: Unable to start ServletWebServerApplicationContext due to missing ServletWebServerFactory bean

Thanks for reading and stay tuned for the next article.