Using Spring Boot DevTools for Faster Development and Live Reload

Spring Boot DevTools is a valuable tool for speeding up the development process by enabling features like automatic application restart and live reload of web content. It is specifically designed to improve the development experience by reducing the time required to restart the application during testing and debugging.

Here is a quick guide to using Spring Boot DevTools for faster development and live reload:


1. Add DevTools Dependency

To use Spring Boot DevTools, include it in your pom.xml (Maven) or build.gradle (Gradle) file.

Using Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-devtools</artifactId>
    <optional>true</optional>
</dependency>

Using Gradle:

implementation 'org.springframework.boot:spring-boot-devtools'

2. Automatic Restart

Spring Boot DevTools triggers an automatic application restart whenever files in the classpath are modified. It uses two classloaders—one for the static resources and one for the application classes—enabling a fast reload experience.

  • Restart Triggering: Files located under /src/main/resources/, /src/main/java/, or any other classpath resources automatically restart the application upon modification.
  • Excluding Certain Files from Restart: You can exclude specific file patterns using the property:
spring.devtools.restart.exclude=static/**,public/**

3. Live Reload (Optional with Browser)

Spring Boot DevTools integrates with LiveReload, so front-end changes (e.g., HTML, CSS, or JavaScript) trigger an automatic browser reload.

Steps for LiveReload:

  1. Install a LiveReload extension in your browser (available for Chrome, Firefox, etc.).
  2. DevTools will automatically enable LiveReload if the extension is active.

If you want to disable the LiveReload capability, use the following property:

spring.devtools.livereload.enabled=false

4. Property Defaults in Development vs. Production

DevTools provides sensible defaults for development environments that are different from production. For instance:

  • Caching is disabled for templates (e.g., Thymeleaf, FreeMarker, etc.).
  • Hibernate auto-detection for changes in the database schema is enabled.

If you want to customize DevTools properties, you can use a dedicated application-dev.properties profile.

5. How to Enable Conditional DevTools Behavior

To avoid shipping DevTools to production, mark it as optional=true in Maven or use a developmentOnly configuration in Gradle.

Example for Gradle:

developmentOnly 'org.springframework.boot:spring-boot-devtools'

6. Disable Restart in Specific Scenarios

If you don’t want restart functionality during your development, you can disable it with the property:

spring.devtools.restart.enabled=false

7. Trigger a Manual Restart

If you want to trigger a restart manually during development, you can:

  • Add or remove files in the /META-INF/spring-devtools.properties directory to trigger a restart.

8. Example Use Case: Thymeleaf or Front-End Modification

If you’re using Thymeleaf templates in a Spring Boot application for the web frontend:

  • Modify an HTML file under /src/main/resources/templates.
  • The browser will refresh automatically (if LiveReload is enabled). You’ll instantly see your changes without manually restarting or refreshing.

Important Notes:

  • Spring Boot DevTools is solely for development purposes and should not be packaged into your production build.
  • If you’re running in Docker or a cloud environment, ensure that file watchers are properly configured for file changes.

Incorporating Spring Boot DevTools provides a more efficient development experience by automating repetitive actions and making live coding efforts more seamless!

Building Your First REST API with Spring Boot in Under 10 Minutes

Creating a simple REST API using Spring Boot can be a smooth process, and it is entirely possible to get it done in under 10 minutes. Here’s a step-by-step guide to building your first REST API:

1. Setup Your Spring Boot Project

  1. Go to Spring Initializr.
  2. Configure the project:
    • Project: Maven.
    • Language: Java.
    • Spring Boot Version: Choose the latest stable version.
    • Dependencies: Add Spring Web (this adds support for creating a REST API).
  3. Click to download the project as a .zip file. Generate

  4. Extract the file, then open it in your favorite IDE like IntelliJ IDEA.

2. Create a REST Controller

A REST controller handles HTTP requests and maps them to methods. You will use the @RestController annotation to create a REST API in Spring Boot.
Create a file under src/main/java/com/example/demo/ named : HelloWorldController.java

package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api")
public class HelloWorldController {

    @GetMapping("/hello")
    public String helloWorld() {
        return "Hello, World!";
    }
}
  • Annotations Explained:
    • @RestController: Combines @Controller and @ResponseBody, enabling REST-specific behavior.
    • @RequestMapping: Specifies the base path for this controller (e.g., /api).
    • @GetMapping: Handles HTTP GET requests for the /hello sub-endpoint.

3. Run Your Application

  1. Run your application by navigating to the DemoApplication class and executing the method (Run button in IntelliJ). main
  2. By default, your application will start on port 8080.

4. Test Your REST API

Hello, World!

5. (Optional) Add Another Endpoint Returning JSON

If you want to return a JSON response, create a new endpoint:

@GetMapping("/greet")
public Greeting greetUser() {
    return new Greeting("Welcome to Spring Boot!");
}

Create a new class Greeting.java under the same package:

package com.example.demo;

public class Greeting {

    private String message;

    public Greeting(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
{
    "message": "Welcome to Spring Boot!"
}

6. Complete!

Congratulations, you’ve successfully created your first REST API with Spring Boot!

How Dependency Injection Works in Spring Boot Using @Autowired

Dependency Injection (DI) is a fundamental concept in Spring Boot that facilitates the management of dependencies between various components in your application. Spring Boot primarily uses the @Autowired annotation to enable automatic wiring of beans. Below, I’ll explain how Dependency Injection works using @Autowired in Spring Boot, step by step.

What is Dependency Injection?

Instead of creating dependencies manually within components, Spring’s IoC (Inversion of Control) container injects dependencies into an object automatically. This reduces tight coupling and makes code more reusable and flexible.

How Does @Autowired Work?

@Autowired is used to mark a dependency that Spring should handle automatically. It tells Spring, “Find the appropriate bean in the IoC container and inject it here.”

Here’s how it works:

  1. Mark the class as a Spring Bean using @Component, @Service, @Repository, or by defining it explicitly via @Bean in a configuration class.
  2. Use the @Autowired Annotation to inject a required dependency into a field, constructor, or setter method.

Approaches to Using @Autowired

1. Field Injection

This is the simplest form of dependency injection where the field is annotated with @Autowired.

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;

@Component
public class CarService {

    @Autowired
    private Engine engine;

    public void startCar() {
        engine.start();
    }
}
@Component
public class Engine {
    public void start() {
        System.out.println("Engine started!");
    }
}
  • Pros: Quick and readable.
  • Cons: Field injection is less testable and not recommended for complex applications because the dependency is hard to mock in unit tests.

2. Constructor Injection (Recommended)

Here, dependencies are injected via the constructor. This is the most preferred approach as it promotes immutability and easy testing.

import org.springframework.stereotype.Component;

@Component
public class CarService {

    private final Engine engine;

    @Autowired // Optional in Spring Boot since 4.3+
    public CarService(Engine engine) {
        this.engine = engine;
    }

    public void startCar() {
        engine.start();
    }
}
@Component
public class Engine {
    public void start() {
        System.out.println("Engine started!");
    }
}
  • Pros: Cleaner, better for unit testing, adheres to immutability principles.
  • Cons: Requires explicit constructors, but modern tools (e.g., Lombok) simplify this.

3. Setter Injection

Dependencies are injected via setter methods. This is helpful when a bean property is optional and not required during object creation.

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;

@Component
public class CarService {

    private Engine engine;

    @Autowired
    public void setEngine(Engine engine) {
        this.engine = engine;
    }

    public void startCar() {
        engine.start();
    }
}
@Component
public class Engine {
    public void start() {
        System.out.println("Engine started!");
    }
}
  • Pros: Useful when you want to inject optional dependencies.
  • Cons: Makes the class mutable and harder to test.

Behind the Scenes

  1. Bean Discovery: The Spring IoC container detects beans annotated with @Component, @Service, @Repository, @Controller, or those defined explicitly in configuration classes.
  2. Dependency Resolution: When @Autowired is detected on a field, constructor, or setter, Spring scans its ApplicationContext to find a matching bean (by type).
  3. Injection: The resolved bean (dependency) is injected into the target where @Autowired is present.

Handling Ambiguity

If multiple beans of the same type are defined, Spring would throw a NoUniqueBeanDefinitionException. You can resolve this by:

  • Using @Qualifier:
@Autowired
@Qualifier("specificEngine")
private Engine engine;
  • Marking a bean as a primary candidate:
@Primary
@Component
public class Engine { ... }

Example: A Working Spring Boot Application

Here’s a complete example of how @Autowired can be used in a Spring Boot application.

Application Entry Point

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

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

Service & Dependency

import org.springframework.stereotype.Service;

@Service
public class GreetingService {

    public String getGreeting() {
        return "Hello, Dependency Injection!";
    }
}
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class GreetingController {

    private final GreetingService greetingService;

    public GreetingController(GreetingService greetingService) {
        this.greetingService = greetingService;
    }

    @GetMapping("/greet")
    public String greet() {
        return greetingService.getGreeting();
    }
}

Run the application, and visiting http://localhost:8080/greet will give you the message:
Hello, Dependency Injection!

Best Practices

  1. Use Constructor Injection for mandatory dependencies.
  2. Avoid Field Injection, except for small applications or testing purposes.
  3. Annotate beans properly using stereotypes like @Service, @Component, etc.
  4. For optional beans, use @Autowired(required = false) or setter injection.
  5. Handle bean ambiguity with @Qualifier or @Primary.

Understanding @SpringBootApplication: The Heart of a Spring Boot App

The @SpringBootApplication annotation is a cornerstone of any Spring Boot application. It simplifies the configuration process and integrates core functionalities of Spring Boot in a single, convenient annotation. Here’s a comprehensive explanation to help you understand its importance and functionality:


What is @SpringBootApplication?

@SpringBootApplication is a composite annotation that combines three common Spring annotations to reduce configuration complexity. These annotations are:

  1. @SpringBootConfiguration
    • Denotes that this class is a configuration class.
    • Equivalent to Spring’s @Configuration annotation.
    • Allows the application to define @Bean definitions and Spring container settings.
  2. @EnableAutoConfiguration
    • Enables Spring Boot’s auto-configuration mechanism.
    • Automatically configures the Spring application based on the dependencies declared in the project.
    • For instance, if spring-boot-starter-web is in your dependencies, it will configure web-related beans like DispatcherServlet, ViewResolvers, etc.
  3. @ComponentScan
    • Scans the package where the annotated class resides and its sub-packages for Spring components (e.g., @Component, @Service, @Repository, @Controller, etc.).
    • This ensures that all required Spring-managed components are registered in the application context.

By combining these three annotations, @SpringBootApplication provides a streamlined way to configure and bootstrap Spring Boot applications.


Advantages of @SpringBootApplication

  1. Reduced Boilerplate Code
    Developers don’t need to explicitly annotate the main application class with @Configuration, @EnableAutoConfiguration, and @ComponentScan. The single annotation @SpringBootApplication takes care of it all.

  2. Auto-Configuration
    The @EnableAutoConfiguration part ensures that Spring Boot configures most components for you based on the classpath dependencies.

  3. Ease of Use
    Simplifies managing configurations and makes the application easier to understand and develop.


Where Should You Place @SpringBootApplication?

The @SpringBootApplication annotation is typically placed on the main class of the application, which is also the entry point for the main method. By convention, this main class should be located in the base package of the application. This ensures that the @ComponentScan directive will pick up all components, services, and controllers in sub-packages.

For example:

package org.kodejava.springboot.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);
    }
}

If your application’s main class is not located in the base package, you’ll need to manually configure the package path using the @ComponentScan annotation.


Customization Options of @SpringBootApplication

In some scenarios, you might want to override the default behavior of @SpringBootApplication by customizing its inner behavior:

  • Excluding Certain Auto-Configurations
    If you want to disable specific parts of Spring Boot’s auto-configuration:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
  • Setting Scanning Packages
    You can explicitly define scanning behavior using the @ComponentScan annotation:
@SpringBootApplication
@ComponentScan(basePackages = {"org.kodejava.springboot.demo.service", "org.kodejava.springboot.demo.dao"})
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

Keynotes

  1. Auto-Configuration Priority:
    • Auto-configuration mechanisms can be fine-tuned or overridden through application.properties or custom configuration classes.
  2. SpringApplication.run:
    • This method in the main method initializes the Spring application context and launches it.
  3. Custom Beans:
    • @SpringBootApplication does not prevent you from defining custom Beans or configurations if needed. You can still use annotations like @Bean and @Configuration alongside it.

Conclusion

@SpringBootApplication eliminates a lot of boilerplate code, making Spring Boot applications easier to configure and start. It combines the functionality of several essential Spring annotations into one. For most Spring Boot applications, simply annotating the main class with @SpringBootApplication is sufficient to bootstrap the application with sensible defaults, making it the “heart” of any Spring Boot app!


Maven Dependencies

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

Maven Central

How to Create Your First Spring Boot Project Using Spring Initializr

Here’s a step-by-step guide for creating your first Spring Boot project using Spring Initializr:

Step 1: Go to Spring Initializr

  1. Open the Spring Initializr website: https://start.spring.io/.
  2. You will see a friendly interface that allows you to configure your new Spring Boot project.

Step 2: Configure Your Project

  1. Project Settings:
    • Project Type: Choose either Maven or Gradle (Maven is common for beginners).
    • Language: Select Java, Kotlin, or Groovy. Use Java for now to keep it simple.
    • Spring Boot Version: Select the latest stable version (e.g., 3.x.x).
  2. Project Metadata:
    • Group: Enter your domain or namespace (e.g., com.example).
    • Artifact: This is the name of your project (e.g., demo).
    • Name and Description: Optional, but you can customize these values.
    • Package Name: Auto-generated from Group and Artifact but can be edited.
    • Packaging: Choose Jar.
    • Java Version: Select the Java version installed on your machine (e.g., Java 23 for compatibility).
  3. Dependencies:
    • Click Add Dependencies and search for the necessary modules, such as:
      • Spring Web for building web applications (REST APIs, etc.).
      • Spring Data JPA if you want database integration.
      • H2 Database for testing with an in-memory database.
      • Spring Boot DevTools for automatic application reload during development.

Add any additional dependencies you need for your project.

Step 3: Download the Project

  1. After configuring your project, click on the Generate button.
  2. A .zip file containing your project will be downloaded.

Step 4: Import the Project into IntelliJ IDEA

  1. Open IntelliJ IDEA.
  2. Go to File > Open and select the folder where you extracted your project.
  3. If IntelliJ suggests importing the project as a Maven/Gradle project, confirm the selection.
  4. Upon importing the project, IntelliJ will automatically resolve and download the dependencies.

Step 5: Run the Spring Boot Application

  1. Locate the main class in the project. It is usually located in src/main/java/<package-name> and has an @SpringBootApplication annotation.
  2. Right-click on the main class and select Run .
  3. Once the application starts, you will see the Spring Boot banner in the console and a log message indicating that the application started successfully.

Example Project Structure

Here’s a high-level view of what your project structure will look like:

src
├── main
|   ├── java
|   │   └── com.example.demo
|   │       └── DemoApplication.java (Main class)
|   └── resources
|       ├── application.properties (Configuration file)
|       ├── static
|       └── templates
└── test

Next Steps

  • Open the application.properties file in the src/main/resources/ directory to specify configuration data, such as database properties.
  • Start building your business logic, controller classes, and database entities.

Congratulations! 🎉 You’ve successfully created your first Spring Boot project using Spring Initializr.