What is WebApplicationType, how does Spring Boot infer it, and how does it govern which server (if any) starts?
answer
- enum SERVLET / REACTIVE / NONE
- deduceFromClasspath()
- both present -> SERVLET wins
- NONE = no server, batch/CLI
- spring.main.web-application-type override
basics
~20 sWebApplicationType 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 sWebApplicationType 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// 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
Know the three values SERVLET/REACTIVE/NONE and that they decide if/what server runs.
Explain classpath inference and that NONE means no server for batch/CLI apps.
Detail deduceFromClasspath, SERVLET-wins-when-both, and the context/server-factory linkage.
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)