skip to content

What is WebApplicationType, how does Spring Boot infer it, and how does it govern which server (if any) starts?

level: seniorimportance: should knowfreq 40%

answer

  1. enum SERVLET / REACTIVE / NONE
  2. deduceFromClasspath()
  3. both present -> SERVLET wins
  4. NONE = no server, batch/CLI
  5. spring.main.web-application-type override

basics

~20 s

WebApplicationType is an enum (SERVLET, REACTIVE, NONE) that tells Spring Boot which kind of application context and web server to create. Boot infers it from the classpath: servlet classes -> SERVLET (Tomcat), only reactive/WebFlux -> REACTIVE (Netty), no web classes -> NONE (no server).

solid answer

~30 s

WebApplicationType is a Spring Boot enum with three values: SERVLET, REACTIVE, and NONE. It decides which ApplicationContext and embedded server Boot creates. SpringApplication infers it from the classpath at startup: if Spring MVC / Servlet API classes (DispatcherServlet, jakarta.servlet.Servlet) are present it's SERVLET → AnnotationConfigServletWebServerApplicationContext + Tomcat; if only WebFlux/reactive classes (DispatcherHandler) are present it's REACTIVE → AnnotationConfigReactiveWebServerApplicationContext + Netty; if neither, it's NONE → a plain context with no server (good for batch/CLI apps). Crucially, if BOTH servlet and reactive are on the classpath, SERVLET wins. You can override inference explicitly with spring.main.web-application-type or SpringApplication.setWebApplicationType(...).

code

java · 15 lines
java
// Force a non-web app even though spring-boot-starter-web is on the classpath
// (e.g. a scheduler/consumer that should NOT bind port 8080).
@SpringBootApplication
public class BatchApp {
    public static void main(String[] args) {
        new SpringApplicationBuilder(BatchApp.class)
            .web(WebApplicationType.NONE)   // no embedded server starts
            .run(args);
    }
}
// Equivalent property: spring.main.web-application-type=none
// Programmatic alternative:
//   SpringApplication app = new SpringApplication(BatchApp.class);
//   app.setWebApplicationType(WebApplicationType.REACTIVE);
//   app.run(args);

go deeper

for a junior

Know the three values SERVLET/REACTIVE/NONE and that they decide if/what server runs.

for a middle

Explain classpath inference and that NONE means no server for batch/CLI apps.

for a senior

Detail deduceFromClasspath, SERVLET-wins-when-both, and the context/server-factory linkage.

for a principal

Use it deliberately (force NONE for consumers, force REACTIVE) and explain it as the upstream switch above server auto-config.

**`WebApplicationType`** (`org.springframework.boot.WebApplicationType`) is an enum that captures *what kind of web application* Spring Boot should bootstrap. It has three constants: - **SERVLET** — a servlet-based web app (Spring MVC). Boot creates a servlet web `ApplicationContext` (`AnnotationConfigServletWebServerApplicationContext`) and an embedded servlet container (Tomcat by default). - **REACTIVE** — a reactive web app (Spring WebFlux). Boot creates `AnnotationConfigReactiveWebServerApplicationContext` and a reactive server (Netty by default). - **NONE** — not a web app. Boot creates a plain `AnnotationConfigApplicationContext`, starts **no** embedded server, and typically exits after `CommandLineRunner`/`ApplicationRunner` work — ideal for batch jobs, scheduled tasks, or CLI tools. **How inference works:** `SpringApplication` calls `WebApplicationType.deduceFromClasspath()` during construction. The logic (simplified): 1. If the WebFlux marker class `org.springframework.web.reactive.DispatcherHandler` is present **AND** the Servlet MVC marker `org.springframework.web.servlet.DispatcherServlet` is **absent** **AND** the servlet-container marker is absent → **REACTIVE**. 2. Else if neither `jakarta.servlet.Servlet` nor `org.springframework.web.context.ConfigurableWebApplicationContext` is on the classpath → **NONE**. 3. Otherwise → **SERVLET**. The practical consequences: **SERVLET is the default whenever the Servlet API is present**, and if you have *both* the servlet and reactive stacks on the classpath, you get **SERVLET** (WebFlux then acts only as a library — e.g. you use `WebClient` inside an MVC app). **This is the master switch above the server choice.** The embedded-server auto-configurations key off the context type: `ServletWebServerFactoryAutoConfiguration` only applies in a servlet context (→ Tomcat/Jetty/Undertow), `ReactiveWebServerFactoryAutoConfiguration` only in a reactive context (→ Netty). So `WebApplicationType` is the upstream decision that determines *whether* a server starts and *which family* of factories runs; the classpath's specific container starter then picks the concrete server within that family. **Overriding inference:** you rarely need to, but you can force it: - Property: `spring.main.web-application-type=none|servlet|reactive`. - Programmatic: `new SpringApplicationBuilder(App.class).web(WebApplicationType.NONE).run(args)` or `springApplication.setWebApplicationType(WebApplicationType.REACTIVE)`. **Common uses/gotchas:** - A scheduled-task or Kafka-consumer service that pulls in `spring-boot-starter-web` transitively will still open port 8080 unless you set `web-application-type=none` — a frequent source of "why is my batch app binding a port?". - Forcing REACTIVE while the servlet API is present lets you run a WebFlux app even though Boot would otherwise pick SERVLET. - `NONE` is how you make a non-web Spring Boot app that runs and exits. **Terms:** *DispatcherServlet* = front controller of Spring MVC (servlet). *DispatcherHandler* = its reactive counterpart in WebFlux. *ApplicationContext* = the Spring IoC container; the web variants add embedded-server lifecycle.

  • If both the servlet and reactive stacks are on the classpath, which WebApplicationType is chosen?
    SERVLET. Boot favors the servlet stack when both are present, so you get Spring MVC on Tomcat; WebFlux is available only as a library. Override with spring.main.web-application-type=reactive to force reactive.
  • How would you stop a Spring Boot app from starting an embedded server at all?
    Set WebApplicationType.NONE — via spring.main.web-application-type=none, SpringApplicationBuilder.web(WebApplicationType.NONE), or setWebApplicationType(NONE). Boot then creates a non-web context and starts no server.

saying these in an interview costs you the question

  • Thinking REACTIVE wins when both stacks are on the classpath (SERVLET actually wins)
  • Not knowing NONE exists / that a web starter forces a port even for batch apps
  • Believing the server choice is independent of the context type
  • Assuming you must remove all web deps to avoid starting a server (setting NONE suffices)

context