Spring Boot Basics

Rapid application development with Spring Boot

← Back to Index

What is Spring Boot?

Think of Spring Boot like a pre-configured development kit:

Spring Boot is an opinionated framework that makes it easy to create stand-alone, production-grade Spring applications. It provides:

  • Auto-configuration: Automatically configures your application based on dependencies
  • Embedded servers: No need to deploy to external servers (Tomcat, Jetty, Undertow)
  • Starter dependencies: Curated dependency bundles for common use cases
  • Production-ready features: Metrics, health checks, externalized configuration
Feature Traditional Spring Spring Boot
Configuration Manual XML or Java config Auto-configuration
Dependencies Manage each individually Starters bundle common deps
Server Deploy to external server Embedded server included
Packaging WAR file Executable JAR
Setup Time Hours of configuration Minutes to running app

Creating a Spring Boot Application

1. Using Spring Initializr

The easiest way: Visit start.spring.io

2. Maven Project Structure

my-app/
├── pom.xml
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/myapp/
│   │   │       ├── MyAppApplication.java     // Main class
│   │   │       ├── controller/
│   │   │       ├── service/
│   │   │       ├── repository/
│   │   │       └── model/
│   │   └── resources/
│   │       ├── application.properties        // Configuration
│   │       ├── static/                       // Static files (CSS, JS)
│   │       └── templates/                    // View templates
│   └── test/
│       └── java/
│           └── com/example/myapp/
└── target/

3. pom.xml with Spring Boot Parent

<?xml version="1.0" encoding="UTF-8"?>
<project>
    <modelVersion>4.0.0</modelVersion>

    <!-- Spring Boot Parent - manages versions -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.0</version>
    </parent>

    <groupId>com.example</groupId>
    <artifactId>my-app</artifactId>
    <version>1.0.0</version>

    <properties>
        <java.version>21</java.version>
    </properties>

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

        <!-- Testing starter -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

The Main Application Class

package com.example.myapp;

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

@SpringBootApplication  // The magic annotation!
public class MyAppApplication {

    public static void main(String[] args) {
        // Starts the application
        SpringApplication.run(MyAppApplication.class, args);
    }
}

// @SpringBootApplication is a shortcut for:
@Configuration           // This class provides beans
@EnableAutoConfiguration // Auto-configure based on classpath
@ComponentScan           // Scan for components in this package and below

Running the Application

# Using Maven
mvn spring-boot:run

# Or build and run the JAR
mvn clean package
java -jar target/my-app-1.0.0.jar

# With specific profile
java -jar my-app.jar --spring.profiles.active=prod

# With system properties
java -Dserver.port=9090 -jar my-app.jar

Auto-Configuration

Spring Boot automatically configures your application based on what's on the classpath:

// If you add spring-boot-starter-web:
// - Embedded Tomcat server is configured
// - DispatcherServlet is registered
// - Jackson for JSON serialization

// If you add spring-boot-starter-data-jpa + H2:
// - DataSource is auto-configured
// - EntityManagerFactory is created
// - Transaction manager is set up

// You can disable specific auto-configurations:
@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,
    SecurityAutoConfiguration.class
})
public class MyApp { }

Viewing Auto-Configuration Report

# Run with debug to see what was auto-configured
java -jar my-app.jar --debug

# Or in application.properties:
debug=true

Building a Simple REST API

Model

package com.example.myapp.model;

public class User {
    private Long id;
    private String name;
    private String email;

    // Constructors
    public User() {}

    public User(Long id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }

    // Getters and setters
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

Service

package com.example.myapp.service;

import org.springframework.stereotype.Service;
import java.util.*;

@Service
public class UserService {

    private Map<Long, User> users = new HashMap<>();
    private Long nextId = 1L;

    public List<User> findAll() {
        return new ArrayList<>(users.values());
    }

    public Optional<User> findById(Long id) {
        return Optional.ofNullable(users.get(id));
    }

    public User save(User user) {
        if (user.getId() == null) {
            user.setId(nextId++);
        }
        users.put(user.getId(), user);
        return user;
    }

    public void deleteById(Long id) {
        users.remove(id);
    }
}

Controller

package com.example.myapp.controller;

import org.springframework.web.bind.annotation.*;
import org.springframework.http.*;

@RestController
@RequestMapping("/api/users")
public class UserController {

    private final UserService userService;

    // Constructor injection (recommended)
    public UserController(UserService userService) {
        this.userService = userService;
    }

    // GET /api/users
    @GetMapping
    public List<User> getAllUsers() {
        return userService.findAll();
    }

    // GET /api/users/123
    @GetMapping("/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
        return userService.findById(id)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    // POST /api/users
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }

    // PUT /api/users/123
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id,
                                            @RequestBody User user) {
        return userService.findById(id)
            .map(existing -> {
                user.setId(id);
                return ResponseEntity.ok(userService.save(user));
            })
            .orElse(ResponseEntity.notFound().build());
    }

    // DELETE /api/users/123
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.deleteById(id);
    }
}

Application Properties

# src/main/resources/application.properties

# Server configuration
server.port=8080
server.servlet.context-path=/myapp

# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG
logging.file.name=app.log

# Database (H2 example)
spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.username=sa
spring.datasource.password=
spring.h2.console.enabled=true

# JPA
spring.jpa.hibernate.ddl-auto=create-drop
spring.jpa.show-sql=true

# Custom properties
app.name=My Application
app.version=1.0.0

YAML Alternative

# src/main/resources/application.yml

server:
  port: 8080
  servlet:
    context-path: /myapp

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password:
  jpa:
    hibernate:
      ddl-auto: create-drop
    show-sql: true

logging:
  level:
    root: INFO
    com.example: DEBUG

app:
  name: My Application
  version: "1.0.0"

Accessing Properties

@Component
public class AppConfig {

    // Direct injection
    @Value("${app.name}")
    private String appName;

    @Value("${app.version:1.0}")  // With default value
    private String version;

    @Value("${server.port}")
    private int serverPort;
}

// Or use @ConfigurationProperties for groups
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
    private String name;
    private String version;
    // Getters and setters
}

DevTools for Development

<!-- Add to pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <scope>runtime</scope>
    <optional>true</optional>
</dependency>

DevTools provides:

Actuator (Production Monitoring)

<!-- Add to pom.xml -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
# application.properties
management.endpoints.web.exposure.include=health,info,metrics,env
management.endpoint.health.show-details=always

Actuator Endpoints:

Best Practices

DO:

  • Use constructor injection - More testable, final fields
  • Follow layered architecture - Controller > Service > Repository
  • Externalize configuration - Use application.properties
  • Use profiles - Different configs for dev, test, prod
  • Enable Actuator - For monitoring and health checks
  • Use starters - They manage compatible versions
  • Write tests - Use spring-boot-starter-test

DON'T:

  • Don't use field injection - Harder to test
  • Don't hardcode configuration - Use properties
  • Don't ignore auto-configuration - Understand what it does
  • Don't deploy as WAR unless necessary - JAR is simpler
  • Don't mix configuration styles - Pick one (properties or YAML)

Summary

  • Spring Boot: Opinionated, rapid application development
  • @SpringBootApplication: Main annotation, enables auto-configuration
  • Auto-configuration: Automatic setup based on classpath
  • Starters: Curated dependency bundles
  • Embedded server: Tomcat, Jetty, or Undertow included
  • application.properties: Externalized configuration
  • DevTools: Development-time features
  • Actuator: Production monitoring endpoints
  • Executable JAR: java -jar app.jar to run