Course Introduction

Get a JDK and a generated project running, then meet the parts every Spring Boot app is made of.

Subsections of Course Introduction

Setup: JDK & Project

Install the JDK

Spring Boot 4 needs Java 17 or newer and supports Java 25. Take the newest LTS:

# macOS
brew install --cask temurin@25

# Linux
sudo apt install openjdk-25-jdk

# Windows
winget install EclipseAdoptium.Temurin.25.JDK

# any platform, several versions side by side
sdk install java 25-tem      # sdkman.io
java --version     # openjdk 25 …

No Maven or Gradle install needed — generated projects ship a wrapper.

Generate a project

Use start.spring.io in the browser, or the API:

curl https://start.spring.io/starter.zip \
  -d bootVersion=4.0.0 -d javaVersion=25 -d type=maven-project \
  -d groupId=com.example -d artifactId=demo -d name=demo \
  -d dependencies=web,data-jpa,h2,actuator,validation \
  -o demo.zip && unzip demo.zip -d demo

What you get:

demo/
  pom.xml
  mvnw  mvnw.cmd                     Maven wrapper — no local Maven needed
  src/main/java/com/example/demo/DemoApplication.java
  src/main/resources/application.properties
  src/test/java/com/example/demo/DemoApplicationTests.java

The build file

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>4.0.0</version>
</parent>

<properties>
    <java.version>25</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

A starter is a dependency that pulls in a whole topic. The parent pins every version, so your dependencies carry no <version> tag.

New in Spring Boot 4

The code base is fully modularized: auto-configuration now lives in many small, focused jars instead of one big spring-boot-autoconfigure. Starters keep working unchanged — you just ship fewer classes you never use.

Run it

cd demo
./mvnw spring-boot:run       # http://localhost:8080
./mvnw test
./mvnw package               # target/demo-0.0.1-SNAPSHOT.jar
java -jar target/demo-0.0.1-SNAPSHOT.jar

Editor

  • IntelliJ IDEA Community — open pom.xml, set the project SDK to 25
  • VS Code — install Extension Pack for Java and Spring Boot Extension Pack
Port already in use?

Another process holds 8080. Start with ./mvnw spring-boot:run -Dspring-boot.run.arguments=--server.port=8081.

★ Exercises

  1. Install a JDK and print java --version.
  2. Generate a project with the web and actuator dependencies.
  3. Start it and open http://localhost:8080/actuator/health.
  4. Run ./mvnw dependency:tree and find out what spring-boot-starter-web pulled in.

Your First Application

The entry point

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

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

@SpringBootApplication is three annotations in one:

AnnotationJob
@SpringBootConfigurationthis class may declare beans
@ComponentScanfind components in this package and below
@EnableAutoConfigurationconfigure what the classpath suggests
Warning

Component scanning starts at the application class’s package. Keep it at the root — classes in a sibling package are invisible.

A first endpoint

@RestController
public class HelloController {

    @GetMapping("/hello")
    public String hello(@RequestParam(defaultValue = "world") String name) {
        return "Hello, " + name + "!";
    }
}
curl "localhost:8080/hello?name=Ann"     # Hello, Ann!

No web.xml, no servlet registration: spring-boot-starter-web puts Tomcat on the classpath, and auto-configuration starts it.

Returning JSON

Return an object and Jackson serializes it.

public record Greeting(String message, Instant at) {}

@GetMapping("/greeting")
public Greeting greeting() {
    return new Greeting("Hello", Instant.now());
}
{"message":"Hello","at":"2026-03-01T10:15:30.00Z"}

Configuration

src/main/resources/application.properties:

server.port=8081
spring.application.name=demo
logging.level.com.example=DEBUG

Or YAML, in application.yaml:

server:
  port: 8081
logging:
  level:
    com.example: DEBUG

What happens on startup

  1. SpringApplication.run creates an application context
  2. component scan collects your @Component/@Service/@RestController classes
  3. auto-configuration adds what the classpath implies (web server, DataSource, …)
  4. beans are created and wired
  5. the embedded Tomcat starts and binds a port
./mvnw spring-boot:run -Ddebug           # prints the auto-configuration report

★ Exercises

  1. Add a /time endpoint returning the current time as JSON.
  2. Change the port to 9000 in application.properties.
  3. Move HelloController into com.example.other — what happens, and why?
  4. Run with -Ddebug and find three auto-configurations that matched.