The labs on this site need JavaScript to run. The same content is written out below.
Fundamentals › Spring
What does Spring Boot do for you?
A Spring Boot application is an ordinary Java class (App) that has a main method. It starts when the main method calls one line, SpringApplication.run(App.class, args). This one line starts Spring (it scans the classes and makes beans), starts a web server (Tomcat) inside the program, and gets ready to receive requests. We do not install Tomcat separately, and we do not write code that starts a server. @SpringBootApplication above App is a marker that tells Spring Boot to scan from the package of this class and configure what is needed automatically, and it decides what to configure by looking at the libraries in the project. If a web library is there, it starts Tomcat, and if not, it does not. In this lab, you remove the run line, @SpringBootApplication, and the web library one at a time and run the program with the java command, to see whether the program keeps running, whether Tomcat starts, and whether it answers a request from the browser.
Checked against real execution · Compiled the source for each of the 8 combinations on Spring Boot 4.1.1 and ran it as a child java process, observed the listening port and HTTP requests from outside, and checked against them (the classpath without the web library was decided from the dependencies in the poms)
// build.gradle: the library to put in this project
implementation 'org.springframework.boot:spring-boot-starter-webmvc'
// Marker: scan from this package and configure what is needed automatically
@SpringBootApplication
public class App {
public static void main(String[] args) {
// This one line starts Spring and starts the server
SpringApplication.run(App.class, args);
}
}
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello";
}
}
This is the result of running Spring Boot 4.1.1 (Spring Framework 7.0.9, embedded Tomcat 11.0.24) on JDK 21.0.12.1. For all 8 combinations, a source with the same structure as the code on the screen (App and HelloController in the package app, with no lines that start a server or count anything) was compiled, a new process was run with the java command starting from the main method of app.App, and the result was checked by observing from outside the process. The criteria are as follows. For the program, it waits until the process ends or a listening port opens, and if it is still alive 3 seconds later, it is "keeps running and waits for requests"; if it already ended with exit code 0, it is "ends right away, nothing to do"; and if the exit code is not 0, it is "failed while starting". The web server was decided by whether that process had a listening TCP port (netstat) and whether the log printed "Tomcat started on port" for the same port, and the response was decided by the real HTTP result of sending GET /hello to that port from outside the process. Even for combinations with no server, a request was sent to an arbitrary port that was confirmed beforehand to be empty and was given as server.port, and every one was refused (giving the port as 0 leaves nowhere to connect when there is no server, so this was done instead). The localhost:8080 in the address is an example of starting Spring Boot on its default port on my own computer, and that the default port is 8080 follows the Embedded Servlet Container Support section of the Spring Boot documentation. The classpath was not the whole library folder but only the jars that the one dependency line on the screen brings in. With a web library, the 39 jars that spring-boot-starter-webmvc brings in were used, and without one, the 21 jars that spring-boot-starter brings in were used, and the 18 that are removed are spring-boot-starter-webmvc, spring-boot-starter-jackson, spring-boot-starter-tomcat, spring-boot-starter-tomcat-runtime, spring-boot-tomcat, spring-boot-web-server, spring-boot-http-converter, spring-boot-webmvc, spring-boot-servlet, spring-boot-jackson, spring-web, spring-webmvc, tomcat-embed-core, tomcat-embed-el, tomcat-embed-websocket, jackson-databind, jackson-core, and jackson-annotations. This list was not obtained by running Gradle but decided by opening the pom files on Maven Central and following the dependencies (the poms of the starters and the Spring Boot modules, spring-web, spring-webmvc, Tomcat, and jackson-databind were checked, and jackson-core and jackson-annotations were not opened), and other libraries such as Spring Security and JPA are on the classpath in neither case. In Spring Boot 4 the name of the web starter is spring-boot-starter-webmvc (in the Starters table of the Build Systems section of the documentation, spring-boot-starter-web is marked as replaced by it), and it was not checked from a Gradle resolution result that the jars the web starter brings in are exactly this list. In the combination without a web library, HelloController does not compile (the error that the package org.springframework.web.bind.annotation does not exist was actually seen), so that class was removed too. What was checked is the three items of the result table and the facts that the step sentences rely on. These were also checked by execution: that SpringApplication decides it is a web application (servlet) if there is a web library and not if there is not, that the only servlet registered with Tomcat is DispatcherServlet and it handles "/", that HelloController and DispatcherServlet are beans of Spring, that our source has no text that starts Tomcat or a server, that after the server is up the main thread has ended but the threads of Tomcat (such as container-0) remain so the process stays alive, and the two ways of failing (without the run line, Spring does not start and the program ends right away, and without @SpringBootApplication but with a web library, it fails with exit code 1 with the exception that there is no ServletWebServerFactory bean that makes a web server). What the documentation defines is the section Using the @SpringBootApplication Annotation of the Spring Boot documentation (that it combines @EnableAutoConfiguration, @ComponentScan, and @SpringBootConfiguration), the Auto-configuration section (that it configures by looking at the jars on the classpath), the Web Environment section of SpringApplication (the rule that if Spring MVC is present it decides to use a servlet web context), and the Embedded Servlet Container Support section (that it supports Tomcat and Jetty and the default port is 8080). Splitting "scan the classes and make beans" and "start Tomcat and register DispatcherServlet" into two steps on the screen is a simplification. In the actual log, Tomcat is made while Spring is starting (Tomcat initialized), Tomcat starts accepting connections before the "Started App" log (Tomcat started), and DispatcherServlet was actually initialized when the first request arrived. That classes are not scanned when there is no @SpringBootApplication is defined by the documentation, and that the number of bean definitions is larger with @SpringBootApplication (7 and 50 in the combination without a web library) is a value observed on this version. Unlike what the documentation defines, "if a web server is needed but there is no configuration, it fails instead of ending quietly" and "if there is no web library, it ends without an error" are behaviors observed on this version. The code on the screen leaves out the package and import lines, assumes that App and HelloController are in the same package, and the line in build.gradle was not run with Gradle but the jars that the line means were put on the classpath. Maven and war deployment, using Jetty instead of Tomcat, and changing the port or the kind of web application by settings were not covered. The details of what is configured automatically are covered in the in-depth lab "Spring Boot auto-configuration".
Previous lab: @Transactional · Next lab: Test code
Struck-through text was removed from the first version of the code; highlighted text was added.