How to Run Spring Boot Without a Web Server
Introduction
Not every Spring Boot application serves HTTP. A command-line tool, a batch job or a message consumer has no use for an embedded Tomcat, yet one starts - and keeps the JVM running - as soon as a web starter is on the classpath, often brought in by a dependency for some other reason. This quick tip shows how to start Spring Boot without a web server, and how to check that none started.Tested on Spring Boot 4.1.2, Spring Framework 7.0.10 and JDK 25.
Setting the web application type to none
Spring Boot decides from the classpath which kind of application context to create: with Spring MVC present it creates a servlet web context and starts the embedded server. The propertyspring.main.web-application-type=none overrides that decision: Spring Boot creates a plain application context and starts no web server, whatever is on the classpath.
application.properties - the short answer
spring.main.web-application-type=none
The three ways to turn the web server off
| Option | When to use it | Limit |
|---|---|---|
Leave the web starter out: depend on spring-boot-starter instead of spring-boot-starter-webmvc | The application never serves HTTP | A web starter that arrives through another dependency brings the server back |
spring.main.web-application-type=none | The web libraries are needed on the classpath but not the server, or only some deployments should run it | None - it can be set per profile, environment variable or command line |
new SpringApplicationBuilder(App.class).web(WebApplicationType.NONE).run(args) | The decision belongs in code, for example in a separate main class for a tool | Fixed at compile time; the property is easier to change |
Checking whether a web server started
The example is a small console application. ACommandLineRunner prints the class of the application context Spring Boot created and the port of the web server: Spring Boot sets the property local.server.port when an embedded server has started. main() closes the application when the runner has finished, as console applications usually do, so that every run ends.
src/main/resources/application.properties
spring.main.banner-mode=off
logging.level.root=WARN
ConsoleApp.java
//ConsoleApp.java
package com.javabrahman.tips.noweb;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.core.env.Environment;
@SpringBootApplication
public class ConsoleApp {
public static void main(String[] args) {
System.exit(SpringApplication.exit(SpringApplication.run(ConsoleApp.class, args)));
}
@Bean
CommandLineRunner report(ConfigurableApplicationContext context, Environment env) {
return args -> {
System.out.println("application context: " + context.getClass().getSimpleName());
System.out.println("web server port: " + env.getProperty("local.server.port", "none - no web server started"));
};
}
}
spring-boot-starter-webmvc on the classpath and no setting; the second sets the property on the command line; the third runs with only spring-boot-starter on the classpath.
OUTPUT with the web starter, no settingapplication context: AnnotationConfigServletWebServerApplicationContext web server port: 8080
application context: AnnotationConfigApplicationContext web server port: none - no web server started
application context: AnnotationConfigApplicationContext web server port: none - no web server started
- With the web starter and no setting, Spring Boot created an
AnnotationConfigServletWebServerApplicationContextand started Tomcat on port 8080 - in a console application that only needed to print two lines. - With
--spring.main.web-application-type=none, the same classpath gave a plainAnnotationConfigApplicationContext, andlocal.server.portwas never set: no server started. The web libraries are still on the classpath and usable in code. - Without the web starter, Spring Boot found no web framework and chose the plain context by itself.
Pitfalls
- A web starter can arrive through another dependency. If a server starts although you never added a web starter,
mvn dependency:treeshows which dependency brings it; the property switches the server off either way. - Without a web server, nothing keeps the JVM alive: it ends when the runners have finished and no other non-daemon thread is left. An application that should keep running, such as a message consumer, can set
spring.main.keep-alive=true. - Older answers use
spring.main.web-environment=false. That boolean property was replaced byspring.main.web-application-typein Spring Boot 2.0. - Actuator endpoints are then not reachable over HTTP, since there is no server to serve them.
Related Spring Boot tutorials
How Spring Boot decides what to configure from the classpath is in how Spring Boot auto-configuration worksClick to read tutorial: How Spring Boot Auto-Configuration Works, and what each starter brings in Spring Boot starters explainedClick to read tutorial: Spring Boot Starters Explained with Examples.Related Spring Boot tutorials
How Spring Boot Auto-Configuration WorksClick to read tutorial: How Spring Boot Auto-Configuration Works Spring Boot Starters Explained with ExamplesClick to read tutorial: Spring Boot Starters Explained with Examples Your First Spring Boot Application with Spring InitializrClick to read tutorial: Your First Spring Boot Application with Spring Initializr
How Spring Boot Auto-Configuration WorksClick to read tutorial: How Spring Boot Auto-Configuration Works Spring Boot Starters Explained with ExamplesClick to read tutorial: Spring Boot Starters Explained with Examples Your First Spring Boot Application with Spring InitializrClick to read tutorial: Your First Spring Boot Application with Spring Initializr