Spring Boot

The key features that make Spring Boot stand out include:

  1. Auto-Configuration: Automatically configures your Spring application based on the dependencies you have added (the "magic" of Spring Boot).
  2. Standalone: Applications can run independently without needing to be deployed to an external web server.
  3. Opinionated: It makes "opinions" about which packages and configurations to use, reducing the number of decisions developers need to make.
  4. Starters: Provides a set of convenient dependency descriptors (e.g., spring-boot-starter-web) to simplify build configurations.
  5. Actuator: Provides production-ready features like health checks, metrics, and auditing to monitor your app.

  1. Rapid Development: Drastically reduces the time spent on boilerplate code and configuration.
  2. Embedded Server: No need to install or configure Tomcat, Jetty, or Undertow separately.
  3. No XML Configuration: Eliminates the need for complex XML files; everything is handled via Java Annotations or properties.
  4. Microservices Ready: Its lightweight nature and standalone capabilities make it the go-to framework for microservices architecture.
  5. Easier Dependency Management: Using "Starters" prevents version conflicts between different libraries.

To start a Spring Boot project:

  1. Install Java: Ensure JDK 17 or later is installed.
  2. Spring Initializr: Visit start.spring.io to generate a project structure.
  3. Choose Dependencies: Add "Spring Web," "Spring Data JPA," or others as needed.
  4. Download & Extract: Download the generated ZIP, extract it, and open it in an IDE (like IntelliJ IDEA or Eclipse).
  5. Run: Execute the main method in the generated ...Application.java file.

As of January 2026, the latest stable version is Spring Boot 4.0.2. This version requires Java 17 as a minimum and provides enhanced support for modern Java features and cloud-native deployments.

A Starter is a set of convenient dependency descriptors you can include in your application. Instead of manually adding 10 different libraries for a web app, you just add spring-boot-starter-web.

  • Example: spring-boot-starter-data-jpa pulls in everything needed for database interaction, including Hibernate and Spring Data.

The Actuator is a sub-project that adds several production-grade services to your application. It provides HTTP endpoints that allow you to "look inside" your running app.

  • /actuator/health: Shows application health status.
  • /actuator/metrics: Shows memory usage, CPU usage, etc.
  • /actuator/env: Returns current environment properties.

Spring Boot looks at the classpath (the libraries you've added). If it sees a specific library, it assumes you want to use it and configures it automatically.

Example: If h2.jar is on the classpath and you haven't configured a database connection, Spring Boot automatically configures an in-memory database for you.

Spring Data JPA is a layer that makes it easy to implement JPA-based (Java Persistence API) repositories. It reduces the amount of "boilerplate" code required to interact with databases.

  • Magic Methods: You can define an interface like findByLastName(String name), and Spring Data JPA will automatically generate the SQL query for you.

You use the @RestController and @RequestMapping annotations.

In this example, visiting localhost:8080/api/greet would return the string "Hello, Spring Boot!".

Feature Spring Framework Spring Boot
Goal Provides a comprehensive programming model Simplifies Spring development
Configuration Requires manual XML or Java config Auto-configuration (Convention over Configuration)
Server Needs an external server (Tomcat) Built-in embedded server
Complexity High (lots of boilerplate) Low (Rapid Application Development)

Definition and Function

The @SpringBootApplication annotation is a "meta-annotation" used to mark the main class of a Spring Boot application. It serves as the entry point and triggers the framework's automatic setup processes. By placing this on your main class, you enable the fundamental features required to run a standalone Spring application.


The Three Combined Annotations

This single annotation is a convenience wrapper that combines the following three core functionalities:

  • @SpringBootConfiguration:
    • Indicates that the class provides Spring Boot application configuration.
    • It is a specialized version of the standard @Configuration annotation, allowing the framework to automatically find and load your bean definitions.
  • @EnableAutoConfiguration:
    • Tells Spring Boot to start adding beans based on the libraries found on the classpath.
    • Example: If spring-boot-starter-web is present, this annotation triggers the setup of an embedded Tomcat server and Spring MVC.
  • @ComponentScan:
    • Directs Spring to search the current package and its sub-packages for components, configurations, and services (classes marked with @Component, @Service, @Repository, or @RestController).
    • This allows the framework to automatically register your classes as Spring Beans.

Core Differences

Both application.properties and application.yml (YAML) are used to configure Spring Boot applications. While they achieve the same end goal of providing configuration metadata, they differ significantly in syntax and structure.

Feature application.properties application.yml
Format Key-Value pairs. Hierarchical/Tree structure.
Readability Can become repetitive with long keys. Highly readable due to indentation.
Repetition Requires full prefix for every line. Uses indentation to group related settings.
List Support Uses indexed keys (e.g., list[0]). Uses native YAML list syntax (-).
Profiles Requires separate files (e.g., application-dev.properties). Supports multi-profile documents in a single file using --- separators.


Syntax Comparison

application.properties Properties files use a flat structure. This can lead to significant redundancy as the application grows:

application.yml YAML uses indentation (spaces) to represent hierarchy, which is more concise and visually organized:

Key Technical Considerations

  • Loading Order: If both files exist in the same location, Spring Boot will load application.properties after application.yml, meaning the properties file will override the YAML file.
  • Limitations: Unlike properties files, YAML files cannot be loaded using the @PropertySource annotation; they must be loaded via the main Spring Boot application configuration.

Definition and Purpose

Spring Boot Profiles provide a way to segregate parts of your application configuration and make it available only in certain environments (e.g., Development, Testing, Production). This prevents the need to change code when deploying to different infrastructures.


Configuration Methods

You can define profile-specific properties using two primary naming conventions:

  • Properties Files: Create files named application-{profile}.properties.
    • Example: application-dev.properties and application-prod.properties.
  • YAML Files: Use a single application.yml file with document separators (---) to define blocks for different profiles.

How to Activate Profiles

There are several ways to tell Spring Boot which profile to use at runtime:

  • Application Properties: Set spring.profiles.active=prod inside the default application.properties file.
  • Command Line: Pass an argument when running the JAR file:
    • java -jar app.jar --spring.profiles.active=prod
  • JVM System Parameter: Use the -D flag:
    • java -Dspring.profiles.active=prod -jar app.jar
  • Environment Variables: Set an OS environment variable named SPRING_PROFILES_ACTIVE.
  • Programmatically: Use SpringApplication.setAdditionalProfiles("dev") in the main method before running the app.

Usage in Code

Beyond configuration files, you can use profiles to control bean creation:

  • @Profile Annotation: Apply @Profile("dev") to a class or a @Bean method. That bean will only be loaded into the Application Context if the "dev" profile is active.

Role and Purpose

The CommandLineRunner and ApplicationRunner interfaces are used to execute a specific block of code immediately after the Spring ApplicationContext is loaded and the application has started, but before it begins handling requests.

They are commonly used for "startup" tasks such as:

  • Seeding a database with initial data.
  • Checking if specific environment variables are set.
  • Starting background processes or messaging listeners.

Key Differences

The primary difference between the two is how they handle command-line arguments.

Feature CommandLineRunner ApplicationRunner
Method Signature run(String... args) run(ApplicationArguments args)
Argument Type Raw String array. Sophisticated ApplicationArguments object.
Data Parsing Requires manual parsing of strings. Provides built-in methods to access "option" (e.g., --key=value) and "non-option" arguments.
Implementation Details
  • Registration: You can implement these interfaces in a class marked with @Component, or define them as a @Bean in a configuration class.
  • Ordering: If multiple runners are defined, you can control their execution sequence using the @Order annotation or the Ordered interface.
  • Exception Handling: If the run method throws an exception, the application will fail to start and shut down.

Overview

Spring Boot uses Externalized Configuration allow the same application code to work in different environments. You can use properties files, YAML files, environment variables, and command-line arguments to feed configuration into your beans.

The Hierarchy of Overriding

Spring Boot uses a specific order of precedence to resolve configuration conflicts. If a property is defined in multiple places, the higher-priority source wins.

Order of Precedence (from highest to lowest):
  1. Command-line arguments (e.g., --server.port=9000).
  2. Java System properties (-Dserver.port=9000).
  3. OS Environment variables.
  4. Profile-specific application properties (e.g., application-dev.properties) outside of the packaged JAR.
  5. Profile-specific application properties inside the packaged JAR.
  6. Application properties (application.properties) outside of the packaged JAR.
  7. Application properties inside the packaged JAR.
Methods for Accessing Configuration

To inject these external values into your Java code, Spring Boot provides two primary mechanisms:

  • @Value("${property.name}"): Used for injecting individual values directly into fields. It is simple but can become disorganized if you have many properties.
  • @ConfigurationProperties:
    • Provides type-safe configuration by mapping groups of properties to a Java object.
    • Supports hierarchical structures and validation.
    • Example: Mapping all properties starting with mail.* to a MailProperties class.
Relaxed Binding

Spring Boot uses "relaxed binding," meaning the property name in the configuration file doesn't have to be an exact match with the field name in the code.

  • Property source<: spring.my-example.url, SPRING_MYEXAMPLE_URL, or spring.myExample.url
  • Java field: myExampleUrl
  • All of the above will successfully bind to the same field.

Overview

Spring Initializr is a web-based service (accessible via start.spring.io) that acts as a project bootstrapping tool. It allows developers to generate a pre-configured Spring Boot project structure with all the necessary dependencies and build settings.

Key Features
  • Build Tool Selection: Choose between Maven or Gradle.
  • Language Support: Supports Java, Kotlin, and Groovy.
  • Version Management: Automatically selects compatible versions of Spring Boot and the selected Java version (e.g., Java 17, 21).
  • Dependency Management: Offers a searchable directory of "Starters" (Web, Security, Data JPA, etc.), which are then automatically added to the pom.xml or build.gradle file.
  • Metadata Configuration: Allows customization of Group ID, Artifact ID, and Package name.
How it Speeds Up Development
  • Eliminates Boilerplate: You don't have to manually create the directory structure (src/main/java, src/main/resources, etc.).
  • Automates Dependency Resolution: It handles the complex "dependency hell" by ensuring all selected libraries are compatible with the specific Spring Boot version chosen.
  • Ready-to-Run: The generated project includes the @SpringBootApplication main class and an empty configuration file, allowing you to run the app immediately after downloading.
  • IDE Integration: Most modern IDEs (IntelliJ IDEA, Eclipse, VS Code) have Spring Initializr built-in, allowing you to create projects without leaving the editor.

Core Definitions

All three annotations—@Component, @Service, and @Repository—are specialized versions of the same base annotation. They serve as "markers" that tell Spring to automatically detect the class during component scanning and register it as a Spring Bean in the Application Context.


Comparison Table
Annotation Purpose Architectural Layer Special Functionality
@Component Generic stereotype. Any None; used when the class doesn't fit a specific layer.
@Service Marks a service bean. Service Layer None; used to indicate that the class contains business logic.
@Repository Marks a data access bean. Persistence Layer Exception Translation: Converts low-level database exceptions into Spring's DataAccessException.

Key Distinctions
  • @Component (The Parent): This is the most general annotation. Technically, you could use @Component for every bean in your application, and it would function correctly. However, it is considered poor practice because it lacks semantic meaning.
  • @Service (Semantic Naming): Like @Component, it has no extra specialized behavior. It is used strictly for readability and to define the middle tier of your application where the business rules reside.
  • @Repository (The Exception Handler): This is more than just a label. It tells Spring to catch platform-specific exceptions (like SQLException) and re-throw them as consistent, unchecked Spring exceptions. This makes your data access code more robust and portable across different database technologies.
Usage Recommendation

Always use the most specific annotation possible. Use @Repository for DAO classes, @Service for business logic classes, and only fall back to @Component for utility classes or cross-cutting concerns that don't belong to a specific layer.

Methods for Exclusion

Even though Auto-Configuration is one of Spring Boot's most powerful features, there are scenarios—such as using a custom database setup or a specific security configuration—where you may need to disable a specific auto-configured bean or class.


  1. Using the @SpringBootApplication Annotation
  2. The most common way to exclude a class is via the exclude attribute on the main application class. This tells Spring Boot to ignore specific auto-configuration classes during the startup process.

  3. Using the @EnableAutoConfiguration Annotation
  4. If you are using @EnableAutoConfiguration separately (rather than through the @SpringBootApplication wrapper), you can use the same exclude attribute:

    • By Class: @EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class})
    • By Class Name (String): @EnableAutoConfiguration(excludeName = {"org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration"})
      • Note: Use excludeName if the class is not on your current compile-time classpath.
  5. Via Application Properties
  6. You can also exclude auto-configuration classes externally without changing the source code. This is particularly useful for environment-specific exclusions.

    • In application.properties:
    • In application.yml:
  • Why Exclude Auto-Configuration?
    • Custom Implementations: You want to provide your own complex bean definition and prevent Spring from creating its default version.
    • Performance: Disabling unnecessary features (like embedded MongoDB or Mail services) can slightly improve startup time.
    • Troubleshooting: Temporarily disabling a specific module to isolate a configuration error.

    Core Definitions

    In Spring Boot, both annotations are used to define classes that handle incoming HTTP requests. However, they differ in how they process the data and what they return to the client.


    Comparison Table
    Feature @Controller @RestController
    Purpose Used for traditional web applications with views. Used for RESTful web services (APIs).
    Return Value Typically returns a String (the name of a View/HTML template). Returns Data (JSON or XML) directly in the HTTP response body.
    Response Body Requires @ResponseBody on every method to return data. Includes @ResponseBody by default for all methods.
    Model Support Frequently uses the Model object to pass data to a template. Does not use a View model; serializes objects directly.

    Key Distinctions
    • @Controller (Traditional Web):
      • It is a stereotype for the presentation layer.
      • When a method returns a String like "home", the Spring ViewResolver looks for a file named home.html (if using Thymeleaf) to render.
      • To return data (like a JSON object) from a specific method in a @Controller, you must manually add the @ResponseBody annotation to that method.
    • @RestController (API Development):
      • This is a convenience annotation that combines @Controller and @ResponseBody.
      • It assumes that every method in the class will return a data object rather than a visual template.
      • Spring automatically uses HttpMessageConverters (like Jackson for JSON) to convert your Java objects into the format requested by the client.
    Code Comparison
    Using @Controller:
    Using @RestController:

    Overview

    In Spring Boot, @ControllerAdvice is a specialized interceptor that allows you to handle exceptions across the entire application in one global, centralized location. Instead of using try-catch blocks in every controller method, you can define how to respond to specific errors once.

    Mechanism: How It Works

    A class annotated with @ControllerAdvice acts as a "global interceptor" for exceptions thrown by any method in any @Controller or @RestController. When an exception occurs, Spring searches this class for a matching handler method.

    • @ExceptionHandler: Used inside the advice class to define which specific exception type the method should catch (e.g., EntityNotFoundException.class).
    • @ResponseStatus: Optionally used to define the specific HTTP status code (like 404 or 500) that should be returned.

    Implementation Example

    Below is a standard implementation for a global error handler that returns a structured JSON error response.

    Key Benefits
    • Consistency: Ensures that every error response follows the same data structure (e.g., always including a timestamp and error code).
    • Code Cleanliness: Removes error-handling logic from business controllers, making them easier to read and maintain.
    • Centralization: Allows for easy updates to error-handling logic in a single file rather than hunting through dozens of controllers.
    • Type Safety: You can target specific exception hierarchies, allowing for different responses for validation errors versus database errors.

    Difference: @ControllerAdvice vs @RestControllerAdvice

    Just like @Controller vs @RestController, @RestControllerAdvice is a convenience annotation that combines @ControllerAdvice and @ResponseBody. It ensures that the return value of the error handler is automatically converted into JSON/XML for the response body.

    Core Purpose

    The spring-boot-starter-web is a "starter" dependency that bundles all the necessary libraries to build web applications, including RESTful services, using Spring MVC. It follows the "opinionated" approach of Spring Boot by providing a pre-configured stack so you don't have to manually import individual dependencies for routing, JSON parsing, or server management.


    Key Components Included

    When you add this single dependency to your pom.xml or build.gradle, it transitively pulls in the following core modules:

    • Spring MVC: The framework used to build web components like Controllers and View Resolvers.
    • Embedded Tomcat: By default, it includes an Apache Tomcat server, allowing the application to run as a standalone .jar file without an external server installation.
    • Jackson: A library used for automatic serialization and deserialization of Java objects to and from JSON.
    • Validation: Provides Hibernate Validator for handling @Valid and JSR-303 bean validation.
    • Spring Boot Starter: The base starter that includes auto-configuration support, logging (Logback), and YAML support.

    Usage Scenarios

    This dependency is required for:

    1. REST APIs: Building endpoints that return JSON or XML data.
    2. Traditional Web Apps: Serving HTML pages using template engines like Thymeleaf or FreeMarker.
    3. Microservices: Creating the web-based communication layer for service-to-service interaction.

    Comparison: Web vs. WebFlux
    Feature spring-boot-starter-web spring-boot-starter-webflux
    Model Blocking / Synchronous (One thread per request). Non-blocking / Asynchronous (Event-loop).
    Stack Servlet-based (Spring MVC). Reactive-stack (Project Reactor).
    Server Default: Tomcat. Default: Netty.

    Overview

    Spring Data JPA provides built-in support for Pagination and Sorting through the PagingAndSortingRepository interface (which JpaRepository extends). This allows you to retrieve large datasets in smaller, manageable chunks and organize them by specific fields without writing manual SQL.


    1. Repository Interface
    2. To enable these features, your repository must extend JpaRepository or PagingAndSortingRepository.

    3. Using Pageable and Sort
    4. The core of the implementation lies in the Pageable interface and the PageRequest implementation.

      • Sorting Only: Use the Sort class to define fields and directions.
        • Example: Sort.by("price").descending()
      • Pagination: Use PageRequest.of(pageNumber, pageSize).
      • Combined: PageRequest.of(pageNumber, pageSize, Sort.by("price").ascending()).

    5. Implementation in the Service Layer
    6. The service layer typically converts raw parameters (from a controller) into a PageRequest object.

      Component Description
      Page Number The zero-based index of the page to retrieve (e.g., 0 for the first page).
      Page Size The number of records to return per page.
      Page Object The returned container that includes the data (List) plus metadata (total elements, total pages, current page).
      Example Service Method:
    7. The Page Response
    8. When you return a Page object, Spring Boot serializes it into a JSON structure that helps frontend clients manage navigation:

      • content: The list of items for the current page.
      • totalElements: Total number of rows in the database.
      • totalPages: Total pages calculated based on size.
      • number: Current page index.

    Core Definitions

    A Standalone Server is a separate software installation (like Tomcat, WildFly, or GlassFish) that exists independently of your application. You must deploy your application code (usually as a .war file) into this pre-installed environment.

    An Embedded Server is a library (like tomcat-embed-core) that is bundled directly inside your application’s .jar file. When you run your application, the server starts as part of the application process.


    Key Comparison
    Feature Embedded Server (Spring Boot Default) Standalone Server (Traditional)
    Packaging Packaged as a FAT JAR. Packaged as a WAR file.
    Installation No server installation required on the host. Server must be installed and configured on the host.
    Deployment Run via simple command: java -jar app.jar. Copy WAR file to the server's webapps folder.
    Versions Server version is managed via project dependencies. Server version is fixed by the infrastructure team.
    Configuration Configured via application.properties. Configured via server-specific files (e.g., server.xml).
    Isolation Each app has its own dedicated server process. Multiple apps often share one server instance.

    Advantages of Embedded Servers
    • Simplified Deployment: You only need a Java Runtime Environment (JRE) on the target machine. This is ideal for Docker containers and cloud-native environments.
    • Consistency: The server version is exactly the same in Development, Testing, and Production, eliminating "it works on my machine" issues.
    • Easy Scaling: Since each instance is self-contained, you can easily spin up multiple instances of a microservice on different ports or containers.
    • Version Control: Server configurations and version upgrades are handled in your code (e.g., pom.xml), making them part of your version control history.
    When to Use a Standalone Server
    • When your organization has a dedicated operations team that manages large, centralized application server clusters.
    • When you need to deploy multiple different applications into a single shared environment to save memory resources (though this is becoming less common with the rise of Microservices).

    Overview

    In Spring Boot, both RestTemplate and WebClient are used to make HTTP requests to external services. While RestTemplate has been the standard for years, WebClient is the modern, preferred alternative introduced in Spring 5.


    Key Comparison
    Feature RestTemplate WebClient
    Programming Model Synchronous / Blocking. Asynchronous / Non-blocking (Reactive).
    Library Spring Web (Servlet API). Spring WebFlux (Project Reactor).
    Efficiency One thread per request; scales poorly. High concurrency with fewer threads.
    Status Maintenance Mode (no new features). Active Development (Modern standard).
    API Style Template-based (Method-heavy). Functional / Fluent API (Chainable).

    1. RestTemplate (Legacy/Standard)
    2. RestTemplate blocks the executing thread until the response is received. It is simple to use for traditional applications where high concurrency is not a primary concern.

      Example Usage:
    3. WebClient (Modern/Recommended)
    4. WebClient belongs to the WebFlux library but can be used in both synchronous and asynchronous applications. It supports streaming and is highly efficient under heavy load.

      Example Usage (Non-blocking):

      Example Usage (Synchronous/Blocking): If you are in a standard Spring Boot Web app but want to use WebClient synchronously, you can append .block():

      Why Switch to WebClient?
      • Future-Proof: Spring has officially placed RestTemplate in maintenance mode.
      • Functional API: The builder-style syntax is more readable and flexible
      • Error Handling: Provides better built-in mechanisms for retries and status code handling.

    Overview

    Spring WebFlux is a non-blocking, reactive-stack web framework introduced in Spring 5. It is designed to handle a massive number of concurrent connections with very few threads, unlike the traditional Spring MVC, which uses a "one thread per request" model.

    It is built on Project Reactor and uses reactive types like Mono (for 0–1 elements) and Flux (for 0–N elements).


    Key Comparison: Spring MVC vs. Spring WebFlux
    Feature Spring MVC Spring WebFlux
    Model Blocking / Synchronous. Non-blocking / Asynchronous.
    Stack Servlet API (Thread-per-request). Event-loop (Event-driven).
    Concurrency Limited by thread pool size. Highly scalable with fixed threads.
    Default Server Apache Tomcat. Netty.
    Data Types Imperative (List<T>, Object). Reactive (Mono<T>, Flux<T>).

    When to Use Reactive Programming

    Reactive programming introduces complexity in debugging and a steep learning curve. Therefore, it should only be used in specific scenarios:

    • High Concurrency: When your application needs to handle thousands of simultaneous connections without consuming massive amounts of RAM for thread stacks.
    • I/O Intensive Tasks: When your service spends a lot of time waiting for other services (Microservices) or slow database queries. Reactive programming allows the thread to perform other work while waiting for the I/O to complete.
    • Streaming Data: When you need to push data to clients in real-time (e.g., live stock tickers, chat applications, or telemetry data).
    • Limited Resources: When running in environments with constrained CPU and memory, as WebFlux utilizes resources more efficiently than blocking frameworks.
    When to Avoid It
    • If your application is a simple CRUD app with a small user base.
    • If you are using blocking drivers (like traditional JDBC for relational databases). Since the "chain" is only as strong as its weakest link, one blocking call in a reactive flow will block the entire event loop.
    • If your team is not experienced with functional programming and the Reactor API, as stack traces in reactive code are significantly harder to read.

    Overview

    Spring Security is integrated into Spring Boot through Auto-Configuration. By simply adding the security starter, Spring Boot secures all HTTP endpoints by default using Basic Authentication.

    1. Dependency Integration
    2. To start, add the spring-boot-starter-security dependency. This automatically triggers the security filter chain.

      • Maven:
    3. Default Security Behavior
    4. Once the dependency is added, Spring Boot:

      • Generates a default user with the username user.
      • Prints a random password to the console at startup.
      • Protects all URLs; any request will result in a 401 Unauthorized or a redirect to a login page.
      • Enables CSRF (Cross-Site Request Forgery) protection and Security Headers (like XSS protection).

    5. Custom Configuration
    6. To customize security (e.g., defining which URLs are public vs. private), you create a configuration class and define a SecurityFilterChain bean.

      Example Configuration:
    7. User Authentication Strategies
    8. You can define how users are authenticated using different beans:

      • In-Memory: Using InMemoryUserDetailsManager for simple testing.
      • Database (JPA): Implementing the UserDetailsService interface to load user data from a database.
      • OAuth2/JWT: Using spring-boot-starter-oauth2-resource-server for modern token-based security.

      Comparison of Authentication Methods
      Method Use Case Implementation Complexity
      Basic Auth Simple internal tools / APIs. Low (Default).
      Form Login Traditional Web Apps (browser). Low.
      JWT (Tokens) Stateless Microservices / SPAs. High (Requires Token logic).
      OAuth2 / OIDC Social Login (Google/GitHub) / SSO. Medium (Standardized).

    Overview

    In modern Spring Boot applications, OAuth2 is the industry-standard protocol for authorization, while JWT (JSON Web Token) is the format used to represent claims between two parties. Spring Boot provides seamless integration for these through the spring-boot-starter-oauth2-resource-server and spring-boot-starter-oauth2-client dependencies.


    1. OAuth2 Roles in Spring Boot
    2. Spring Boot allows you to implement different parts of the OAuth2 ecosystem:

      • Resource Server: The application that hosts the protected data (API). It validates incoming JWTs to grant access.
      • Client: The application that requests access to the user's account (e.g., a "Login with Google" button).
      • Authorization Server: The server that issues the tokens (e.g., Okta, Keycloak, or Auth0).
    3. JWT (JSON Web Token) Support
    4. JWTs are stateless, meaning the server doesn't need to store session data. A JWT consists of three parts: Header, Payload (Claims), and Signature.

      • Self-Contained: The token contains all the necessary user information (roles, username, expiration).
      • Verification: Spring Boot uses a Public Key (provided by the Authorization Server) to verify that the token's signature is valid and hasn't been tampered with.

    5. Implementation and Configuration
    6. To configure a Spring Boot app as a Resource Server using JWT, you define the Issuer URI in your properties file:

      application.yml

      Security Configuration: You must configure the SecurityFilterChain to enable JWT validation.

    7. Key Differences
    8. Feature OAuth2 JWT
      Type A framework/protocol for authorization. A data format/token standard.
      Purpose To define how access is granted. To define what the access credentials look like.
      Storage Often requires a database for session/tokens. Stateless (no server-side storage required).
      Usage Used to coordinate between User, Client, and Server. Used as the actual "key" passed in HTTP headers.

    To secure REST API endpoints in Spring Boot, you must implement multiple layers of protection, ranging from authentication to transport-level security.

    1. Authentication and Authorization
    2. This is the first line of defense, ensuring you know who the user is and what they are allowed to do.

      • Stateless Authentication (JWT): For REST APIs, use JSON Web Tokens instead of sessions. This ensures the server doesn't have to store state, making it scalable.:
      • Role-Based Access Control (RBAC): Use @PreAuthorize or requestMatchers to restrict specific endpoints to specific roles (e.g., ADMIN, USER).
    3. Transport Layer Security (TLS/SSL)
      • HTTPS: Always serve your API over HTTPS to encrypt data in transit, preventing Man-in-the-Middle (MITM) attacks.
      • HSTS: Enable HTTP Strict Transport Security to force browsers to use secure connections.
    4. Common Attack Protections
    5. Spring Security provides built-in protection for several common vulnerabilities:

      • CORS (Cross-Origin Resource Sharing): Define which domains are allowed to access your API. Restrict this to your frontend's domain rather than using a wildcard (*).
      • CSRF (Cross-Site Request Forgery): Generally disabled for stateless REST APIs using JWT, but critical if your API uses session cookies.
      • Input Validation: Use @Valid and JSR-303 annotations (e.g., @NotNull, @Size) to prevent SQL injection and cross-site scripting (XSS) via malicious payloads.
    6. Rate Limiting and Throttling
    7. To prevent Denial of Service (DoS) attacks or API abuse:

      • Bucket4j: A common Java library used with Spring Boot to limit the number of requests a user can make in a specific timeframe.
      • API Gateway: In a microservices architecture, handle rate limiting at the Gateway level (e.g., Spring Cloud Gateway).

      Security Best Practices Comparison
      Security Feature Purpose Implementation Tool
      Authentication Verifies user identity. OAuth2 / JWT
      Authorization Checks permissions. @PreAuthorize("hasRole('ADMIN')")
      Data Integrity Prevents tampering. Digital Signatures (JWT)
      Availability Prevents service outages. Rate Limiting / Throttling
      Audit Tracks access and changes. Spring Data Envers / Actuator

    Overview

    Spring Boot Actuator is a sub-project of Spring Boot that provides production-ready features to help you monitor and manage your application. It uses HTTP endpoints or JMX beans to expose operational information about the running application’s health, metrics, and state.

    Commonly Used Endpoints

    By default, only /health is exposed over HTTP for security reasons. Other endpoints must be enabled in your configuration.

    Endpoint Description
    /actuator/health Shows application health information (UP, DOWN, or OUT_OF_SERVICE).
    /actuator/metrics Shows various metrics (JVM memory, CPU usage, HTTP request counts).
    /actuator/env Exposes properties from Spring's Environment (config sources).
    /actuator/loggers Allows you to view and change logging levels at runtime without restarting.
    /actuator/info Displays arbitrary application information (e.g., build version, git commit).
    /actuator/beans Returns a complete list of all Spring beans initialized in the Application Context.
    /actuator/mappings Displays a collated list of all @RequestMapping paths and their controllers.
    /actuator/threaddump Performs a thread dump for diagnosing performance bottlenecks or deadlocks.
    Configuration and Security

    To expose endpoints via HTTP, you must configure them in your properties file. It is a critical best practice to secure these endpoints using Spring Security, as they expose sensitive internal data.

    Example application.yml:
    Custom Health Indicators

    You can create your own health checks by implementing the HealthIndicator interface. This is useful for monitoring specific business logic or custom downstream service dependencies.

    To create a Custom Health Indicator, you implement the HealthIndicator interface or extend the AbstractHealthIndicator class. This allows you to integrate specific business logic or external system checks into the standard /actuator/health endpoint.


    Implementation Steps
    1. Implement the Interface: Define a class and implement the health() method.
    2. Register as a Bean: Annotate the class with @Component so Spring Boot's Actuator can discover it.
    3. Return a Health Object: Use the Health builder to return a status (UP, DOWN, OUT_OF_SERVICE, or UNKNOWN) along with optional details.

    Code Example

    In this example, we check if a specific external service or internal file system is accessible.


    Key Components of the Health Response
    Component Description
    Status The primary state (e.g., UP or DOWN).
    Details Key-value pairs providing context (e.g., free disk space, DB version).
    Aggregate Health If any single indicator is DOWN, the overall /health status becomes DOWN.
    Advanced: Reactive Health Indicators

    If you are using Spring WebFlux, you should implement the ReactiveHealthIndicator interface. This ensures that the health check does not block the event loop, returning a Monoinstead of a plain Health object.


    Visibility Configuration

    By default, the details of your custom health indicator might be hidden. To see the custom details you added with .withDetail(), ensure your configuration allows it:

    application.properties

    Overview

    Micrometer is an open-source instrumentation library that acts as a facade (like SLF4J, but for metrics). It allows you to instrument your application code with dimensional metrics once, and then export those metrics to various monitoring systems without changing your code.

    In the Spring Boot ecosystem, Micrometer is the default metrics-collection engine used by Spring Boot Actuator.


    Core Functionality

    Micrometer serves as the "middleman" between your application and your monitoring backend.

    • Vendor-Neutral API: It provides a consistent interface to record timers, counters, and gauges.
    • Meter Registry: Each monitoring system has a specific MeterRegistry implementation (e.g., PrometheusMeterRegistry, DatadogMeterRegistry).
    • Dimensionality: It supports tags (key-value pairs), allowing you to drill down into metrics (e.g., viewing HTTP requests filtered by status_code or uri).

    Key Concepts: Meter Types

    Micrometer provides several "Meters" to track different types of data:

    Meter Type Description Use Case
    Counter A value that only increases (or resets to zero). Number of HTTP requests, tasks completed, or errors.
    Timer Measures short-duration latencies and counts. Measuring how long a database query or API call takes.
    Gauge A value that can go up and down (a "snapshot"). Current memory usage, thread count, or queue size.
    Distribution Summary Tracks the distribution of events (not necessarily time). Size of payloads or number of items in a shopping cart.

    Integration with Spring Boot

    To monitor your application with a specific tool (e.g., Prometheus), you simply add the corresponding Micrometer dependency.

    1. Dependency (Example for Prometheus):
    2. Automatic Exposure: Spring Boot automatically configures a /actuator/prometheus endpoint that formats all collected metrics into a format Prometheus can scrape.
    Why Use Micrometer?
    • Portability: If you decide to switch from Prometheus to New Relic, you only change a dependency, not your business logic.
    • Rich Ecosystem: It includes "binders" that automatically collect metrics for JVM, Hibernate, Kafka, and the OS.
    • Low Overhead: It is designed to be highly efficient, ensuring that gathering metrics doesn't significantly impact application performance.

    Overview

    Virtual Threads, introduced as a stable feature in Java 21 (Project Loom), are lightweight threads that significantly reduce the effort of writing, maintaining, and observing high-throughput concurrent applications. Unlike traditional Platform Threads, which are mapped 1:1 to Operating System (OS) threads, virtual threads are managed by the Java Virtual Machine (JVM).

    While your question mentions Spring Boot 4.0, it is important to note that full, first-class support for virtual threads actually began in Spring Boot 3.2. Spring Boot 4.0 (the next major generation) is expected to build upon this by potentially making virtual threads the default concurrency model.


    Platform Threads vs. Virtual Threads
    Feature Platform Threads (Traditional) Virtual Threads (Project Loom)
    Mapping 1:1 with OS threads. Many-to-one (M:N) with carrier threads.
    Resource Cost Expensive (approx. 1MB per thread). Very cheap (approx. a few hundred bytes).
    Creation Limit Thousands (limited by OS memory). Millions (limited by heap memory).
    Blocking Blocks the OS thread (wasteful). "Parks" the virtual thread; releases carrier thread.

    How Spring Boot Leverages Virtual Threads

    In a traditional Spring Boot (MVC) application, the server uses a "thread-per-request" model. With platform threads, a slow database call blocks an expensive OS thread. With virtual threads enabled:

    • Tomcat/Jetty Integration: Spring Boot configures the underlying web server to use a VirtualThreadExecutor. Each incoming HTTP request is handled by a new virtual thread.
    • Non-Blocking Logic without Complexity: You can write simple, imperative code (like Spring MVC) that performs as efficiently as complex reactive code (WebFlux).
    • Task Execution: Annotations like @Async and scheduled tasks can be configured to run on virtual threads automatically.

    Enabling Virtual Threads

    As of Spring Boot 3.2+, you don't need complex bean definitions. You can enable them with a single property:

    application.properties
    Why it Matters for Spring Boot 4.0

    As we look toward Spring Boot 4.0, the framework is moving toward a "Virtual-Thread-First" approach. This means:

    • Scalability: Applications can handle massive traffic spikes with much lower memory footprints.
    • Simplified Programming: The need for reactive programming (WebFlux) may decrease for many standard use cases, as virtual threads solve the "blocking I/O" problem without the overhead of Flux/Mono.

    To enable Virtual Threads in a Spring Boot application, you primarily need to ensure you are running on a compatible environment and then toggle a simple configuration property.


    Prerequisites

    Before enabling the feature, ensure your environment meets these minimum requirements:

    • Java Version: Java 21 or higher (Loom is not available in earlier LTS versions).
    • Spring Boot Version: Spring Boot 3.2 or higher.

    1. The Configuration Property
    2. Starting with Spring Boot 3.2, you do not need to manually define executors or bean overrides. You can enable virtual threads globally for the web server (Tomcat, Jetty, or Undertow) and for asynchronous task execution by adding this to your configuration:

      application.properties
      application.yml

    3. What This Property Changes Automatically
    4. When this property is set to true, Spring Boot auto-configures the following:

      • Tomcat/Jetty: The web server uses a virtual thread for every incoming HTTP request instead of a pool of platform threads.
      • @Async Methods: Methods annotated with @Async will run on virtual threads.
      • Task Execution: The applicationTaskExecutor bean is configured to use virtual threads.
      • Scheduled Tasks: The TaskScheduler will utilize virtual threads for @Scheduled tasks.

    5. Manual Configuration (Advanced)
    6. If you are using a version of Spring earlier than 3.2 (but still on Java 21) or need a specific executor for a custom task, you can define a bean manually:


      Impact Analysis
      Feature Platform Threads (Traditional) Virtual Threads (Project Loom)
      Mapping 1:1 with OS threads. Many-to-one (M:N) with carrier threads.
      Resource Cost Expensive (approx. 1MB per thread). Very cheap (approx. a few hundred bytes).
      Creation Limit Thousands (limited by OS memory). Millions (limited by heap memory).
      Blocking / I/O Blocking Blocks the OS thread (wasteful); requires more memory. "Parks" the virtual thread; negligible resource cost.
      Max Concurrent Requests Limited by the thread pool size (default 200). Limited only by CPU and heap memory (thousands+).
      Memory Usage High (~1MB per thread stack). Very low (bytes to kilobytes per stack).
      Programming Style Requires Reactive (WebFlux) for high scale. Uses simple Imperative (MVC) for high scale.
      A Note on "Pinning"

      While virtual threads are powerful, you should avoid synchronized blocks or native calls that take a long time. These can "pin" the virtual thread to its carrier thread, preventing the JVM from switching it out and effectively turning it back into a blocking platform thread. Use ReentrantLock instead of synchronized where possible.

    Overview

    GraalVM Native Image is a technology that compiles Java applications ahead-of-time (AOT) into a standalone executable (a native binary). Unlike a standard JVM application that runs on a Java Runtime Environment (JRE) and compiles code at runtime (JIT), a Native Image includes the application classes, dependencies, and a specialized "Substrate VM" runtime all in one file.


    How It Improves Startup Time

    The dramatic improvement in startup performance is driven by three primary factors:

    • Ahead-of-Time (AOT) Compilation: Most of the heavy lifting (class loading, linking, and initializing) happens at build time. When you start the app, the machine code is ready to execute immediately.
    • Static Analysis: During the build, GraalVM performs a "reachability analysis" to find and include only the code that is actually reachable. This results in a much smaller memory footprint.
    • No JIT Overhead: In a standard JVM, the first few minutes are spent "warming up" while the Just-In-Time (JIT) compiler optimizes the code. Native images start at peak performance immediately.

    Performance Comparison
    Metric Standard JVM (Spring Boot) GraalVM Native Image
    Startup Time Seconds (e.g., 2–5s) Milliseconds (e.g., < 100ms)
    Memory (RSS) High (e.g., 250MB+) Low (e.g., 30MB - 50MB)
    Executable Size Small (.jar) + JRE (~200MB) Larger (~70MB standalone binary)
    Peak Throughput Very High (JIT optimizations) Slightly lower than tuned JIT

    Use Cases

    Native Images are specifically beneficial for:

    • Serverless/Function-as-a-Service (FaaS): Ideal for AWS Lambda or Google Cloud Functions where "Cold Start" times are critical.
    • Microservices in Kubernetes: Allows for rapid scaling and lower resource costs (packing more containers onto a single node).
    • CLI Tools: Provides the instant-on experience expected of command-line utilities.
    Trade-offs and Challenges
    1. Build Time: Compiling a native image is resource-intensive and can take several minutes.
    2. Reflection & Proxies: Since GraalVM needs to know everything at build time, dynamic features like Reflection, Dynamic Proxies, and JNI require extra configuration (hints).
    3. No Warm-up: While it starts fast, it lacks the runtime profile-guided optimizations (PGO) that a JIT compiler uses to reach maximum throughput, unless using the Enterprise edition.

    How to enable in Spring Boot

    Spring Boot 3.x provides native support out of the box. You can build a native image using the Maven or Gradle plugins:

    Overview

    The spring-boot-starter-ai (part of the Spring AI project) is a foundational dependency designed to streamline the integration of Artificial Intelligence and Large Language Models (LLMs) into Spring applications. It applies the familiar Spring philosophy of portability and dependency injection to the world of AI, allowing developers to switch between different AI providers (like OpenAI, Azure, or local models) with minimal code changes.


    Core Capabilities

    Spring AI provides a standardized API for interacting with various AI models. Key features include:

    • Model Agnostic API: Use a single interface (ChatClient or EmbeddingClient) to interact with different providers like OpenAI, Anthropic (Claude), Google Vertex AI (Gemini), and Meta (Llama).
    • Prompt Management: Tools to manage complex prompts using templates, ensuring consistent input formatting.
    • Structured Outputs: Automatically maps AI-generated JSON responses directly into Java POJOs (Plain Old Java Objects).
    • RAG (Retrieval-Augmented Generation): Built-in support for connecting to Vector Databases (like Pinecone, Milvus, or Weaviate) to provide the AI with private, custom data.

    Comparison: Traditional vs. Spring AI Integration
    Feature Manual API Integration Spring Boot Starter AI
    Vendor Lock-in High (using proprietary SDKs). Low (swappable via configuration).
    Boilerplate Extensive (manual HTTP clients). Minimal (uses Auto-configuration).
    Data Parsing Manual JSON deserialization. Automatic Mapping to Java Objects.
    Observability Requires custom logging. Integrates with Actuator and Micrometer.

    Implementation Example

    To use it, you add the starter and inject the ChatClient.

    1. Dependency:
    2. Usage in a Service:

    Key Components within the Starter
    • Chat Models: For conversational AI and text generation.
    • Embedding Models: For converting text into numerical vectors for search and similarity.
    • Image Models: Integration with DALL-E or Midjourney for text-to-image generation.
    • Vector Stores: Abstractions to store and query high-dimensional data efficiently.

    Overview

    In Spring Boot 3.x and moving into Spring Boot 4.0, the framework has moved away from the legacy Spring Cloud Sleuth in favor of Micrometer Observation. This API provides a single, unified way to instrument your application for both Metrics (numbers) and Tracing (spans/IDs).

    The philosophy is "Instrument Once, Observe Everywhere." When you instrument a piece of code, Spring automatically handles the recording of metrics and the creation of trace spans simultaneously.


    Key Concepts in Distributed Tracing

    To understand the 4.0 approach, it is essential to distinguish between the two pillars of observability:

    Term Description Role in Observation
    Trace The complete journey of a request as it moves through multiple microservices. Provides the "Big Picture" of a request's path.
    Span A single unit of work within a trace (e.g., a specific method call or DB query). Provides the "Granular Detail" of a specific step.
    Baggage Key-value pairs propagated across service boundaries. Useful for passing metadata like tenant-id.
    Observation A wrapper around a block of code that emits both metrics and traces. The core API used in Spring Boot 4.0.

    1. Unified Observation API
    2. Instead of using separate APIs for timers (metrics) and spans (tracing), you use the Observation class.

    3. Automatic Propagation (W3C Trace Context)
    4. Spring Boot 4.0 defaults to the W3C Trace Context standard for propagating trace information across network boundaries (e.g., from Service A to Service B). This ensures interoperability with other frameworks and languages.

    5. Integration with OTLP
    6. The industry is standardizing on OpenTelemetry (OTLP). Spring Boot 4.0 simplifies the export of your data to backends like Zipkin, Jaeger, or Grafana Tempo by providing native OTLP exporters.

      application.properties Example:

      Evolution: Sleuth vs. Micrometer Tracing
      Feature Spring Cloud Sleuth (Legacy) Micrometer Tracing (Spring Boot 3/4)
      Dependency spring-cloud-starter-sleuth micrometer-tracing-bridge-otel (or Brave)
      Logic Manual span management. Automated through the Observation API.
      Flexibility Tied heavily to Spring Cloud. Decoupled; can be used in any Java app.
      Standard Proprietary B3 headers. W3C Trace Context (standard).

      Summary of Benefits
      • Reduced Overhead: Running one instrumentation logic for both metrics and traces saves CPU cycles.
      • Consistency: Your metrics (e.g., request count) will perfectly align with your traces (e.g., which requests were slow).
      • Future-Proof: Full alignment with the OpenTelemetry ecosystem.

    Overview

    Spring Modulith is an opinionated framework designed to help developers build Modular Monoliths. It provides the tools to define, enforce, and test the boundaries between different functional parts of a single Spring Boot application.

    While a traditional "big ball of mud" monolith allows any class to call any other class, Spring Modulith ensures that modules remain decoupled, making it significantly easier to maintain the code or eventually split a module into a separate microservice.


    Core Concepts
    • Application Modules: In Spring Modulith, a "module" is a package located directly below the main application class's package.
    • Encapsulation: By default, only the classes in the top-level package of a module are considered "public" (API) to other modules. All sub-packages are considered internal and inaccessible.
    • Verification: It provides tests that fail if a developer tries to create an illegal dependency between modules (e.g., the Billing module trying to access internal classes of the Inventory module).

    Key Features
    Feature Description
    Module Detection Automatically identifies modules based on your package convention.
    Architectural Wire-tapping Uses tests to verify that the code structure follows the defined module boundaries.
    Document Generation Automatically generates C4 or PlantUML diagrams based on your code's actual dependencies.
    Event Publication Registry Ensures that events sent between modules are persisted, guaranteeing that a module's failure doesn't lose data intended for another.

    Managing Inter-Module Communication

    Spring Modulith encourages Asynchronous Events instead of direct method calls. This prevents "Tight Coupling."

    1. Direct Call (Bad): Module A calls a method in Module B. If Module B is slow, Module A waits.
    2. Events (Good): Module A publishes a OrderCompletedEvent. Module B listens to it. Module A doesn't care if or when Module B processes it.

    Comparison: Traditional Monolith vs. Spring Modulith
    Feature Traditional Monolith Spring Modulith
    Package Privacy Often ignored; everything is public. Strictly enforced via ArchUnit integration.
    Dependency Graph Can become a tangled "spaghetti" mess. Clean, directed, and verified by tests.
    Ease of Extraction Very difficult to move to Microservices. High; boundaries are already established.
    Documentation Usually outdated or manual. Self-documenting via generated diagrams.

    How to verify your structure

    You can add a simple test case to your project that verifies the entire architecture:

    Official Requirements

    As of the current roadmap for Spring Framework 7.0 and Spring Boot 4.0, the baseline has been shifted upward to keep pace with modern Java features.

    • Minimum Version: Java 17. This is the absolute baseline required to run the framework.
    • Recommended Version: Java 21 or higher.

    Why Java 21+ is Recommended

    While Java 17 is the minimum, the Spring team strongly advocates for Java 21 (and soon Java 25) because Spring Boot 4.0 is specifically optimized for features introduced in recent Long-Term Support (LTS) releases.

    Feature Java 17 (Minimum) Java 21 (Recommended)
    Virtual Threads Not Available. Full Support. Enables high-scale concurrency with simple code.
    Scoped Values Not Available. Preview/Full Support. Safer and more efficient than ThreadLocal.
    Record Patterns Basic support. Advanced Support. Allows for cleaner data processing in patterns.
    Sequenced Collections Not Available. Full Support. Provides a uniform API for collections with a defined order.

    Key Compatibility Considerations
    • Jakarta EE 10/11: Spring Boot 4.0 is aligned with the latest Jakarta EE specifications. Running on Java 21 ensures better compatibility with the modern jakarta.* namespace and underlying container optimizations.
    • GraalVM Compatibility: If you plan on using Native Images, Java 21+ provides significantly better AOT (Ahead-of-Time) compilation results and reduced memory footprints compared to Java 17.
    • Performance: Java 21 introduced improvements in Generational ZGC (Z Garbage Collector), which Spring Boot 4.0 can leverage to maintain sub-millisecond pauses in high-traffic applications.

    Summary of Version Dependencies
    • Spring Boot 2.x: Java 8 (Minimum).
    • Spring Boot 3.x: Java 17 (Minimum).
    • Spring Boot 4.x: Java 17 (Minimum), but the internal engine is tuned for the Java 21+ runtime.

    Overview

    One of the most powerful features of Spring Boot is the Executable JAR (also known as a "Fat JAR"). Unlike traditional Java applications that require an external web server like Tomcat to be installed, a Spring Boot JAR contains all its dependencies and the embedded web server inside a single file.


    1. The Packaging Process
    2. The packaging is handled by the Spring Boot Maven or Gradle Plugin. When you run the build command, the plugin repackages your compiled code and its libraries into a specific structure that the Spring Boot JarLauncher understands.

    3. Commands to Package
    4. Depending on your build tool, use the following commands in your terminal:

      Build Tool Command Output Location
      Maven ./mvnw clean package target/*.jar
      Gradle ./gradlew bootJar build/libs/*.jar

    5. How to Run the JAR
    6. Once the file is generated, you can run it on any machine that has the minimum required Java version installed (e.g., Java 17 for Spring Boot 3/4) using the standard Java command:


    7. Internal Structure of a Fat JAR
    8. The executable JAR is not a standard JAR file. It uses a custom layout to allow nested JARs (dependencies) to be loaded:

      • META-INF/MANIFEST.MF: Contains the Main-Class (Spring Boot's JarLauncher) and the Start-Class (your @SpringBootApplication class).
      • BOOT-INF/classes/: Your compiled application code and resource files.
      • BOOT-INF/lib/: All your third-party dependencies (the "nested" JARs).
      • org/springframework/boot/loader/ The Spring Boot loader classes that enable the application to boot from a nested structure.

    9. Comparison: Executable JAR vs. Standard WAR
    10. Feature Executable JAR Standard WAR
      Deployment Standalone (java -jar). Requires external Servlet Container (Tomcat/Wildfly).
      Ease of Use Extremely high; ideal for Cloud/Docker. Moderate; requires server configuration.
      Embedded Server Included (Tomcat/Jetty/Undertow). Excluded (uses the host server).
      Microservices Standard practice. Rarely used in modern microservices.

    11. Production Best Practice: Layered JARs
    12. For Docker environments, you can enable Layered JARs. This breaks the JAR into layers (dependencies, spring-boot-loader, snapshot-dependencies, application) so that Docker can cache the layers that change less frequently, leading to faster image builds and smaller deployments.

      pom.xml configuration:

    Overview

    The terms "Fat JAR" and "Thin JAR" refer to how an application's dependencies (libraries like Spring, Hibernate, etc.) are packaged relative to the application's own compiled code.


    1. Fat JAR (The Spring Boot Default)
    2. A Fat JAR (also known as anExecutable JAR or Uber JAR) contains everything your application needs to run. It bundles the compiled bytecode, resources, and all third-party dependency JARs into a single archive.

      • Primary Advantage: Portability. You only need to move one file to a server, and it’s ready to run via java -jar.
      • Embedded Server: It usually includes an embedded web server (like Tomcat).
    3. Thin JAR
    4. A Thin JAR contains only the compiled bytecode and resources of your specific application. It does not include third-party dependencies. Instead, it relies on an external library folder or a local Maven/Gradle repository to provide the necessary dependencies at runtime.

      • Primary Advantage: Size. The file is very small (often just a few hundred KBs).
      • Deployment: Requires a pre-configured environment where dependencies are already present or can be downloaded.

      Key Comparison
      Feature Fat JAR Thin JAR
      File Size Large (e.g., 50MB – 200MB+). Small (e.g., 100KB – 2MB).
      Self-Contained Yes. Includes all libraries. No. Dependencies must be provided externally.
      Ease of Deployment High. Single file to copy. Lower. Must manage dependencies separately.
      Docker Efficiency Lower (one big layer). Higher (if layers are used correctly).
      Cloud/Serverless Standard for most deployments. Useful for "Warm" environments like AWS Lambda.

      Which one should you use?

      Use Fat JAR when:

      • You are building Microservices for Docker or Kubernetes.
      • You want a simple "Copy and Run" deployment strategy.
      • You are using the default Spring Boot Maven/Gradle plugins.

      Use Thin JAR when:

      • You have a very slow network connection and only want to upload code changes.
      • You are deploying to a Serverless platform (like AWS Lambda) where you want to minimize the package size to reduce cold start times.
      • You use a tool like Spring Cloud Function with a "Thin Wrapper" to manage dependencies on the host.
      Pro-Tip: The Hybrid Approach (Layered JARs)

      Modern Spring Boot (3.x/4.x) solves the "Fat JAR" inefficiency in Docker by using Layered JARs. This allows you to create a Fat JAR but extract it into layers in your Dockerfile. This keeps your dependencies in a cached Docker layer and only updates the "Thin" application layer when you change your code.

    Overview

    Containerizing a Spring Boot application with Docker allows you to package the application, its runtime (JRE), and its configuration into a single image. This ensures the app runs identically in development, testing, and production environments.


    1. The Traditional Dockerfile Approach
    2. The most common method is creating a Dockerfile in the root of your project. For modern Spring Boot apps (3.x/4.x), using a multi-stage build is the best practice to keep the final image size small.

      Example Multi-Stage Dockerfile:

    3. Using Cloud Native Buildpacks (No Dockerfile)
    4. Spring Boot has built-in support for Buildpacks, which allows you to create an optimized, production-ready Docker image without writing a Dockerfile.

      • Maven: ./mvnw spring-boot:build-image
      • Gradle: ./gradlew bootBuildImage

    5. Optimized Layering
    6. To improve build times and reduce deployment bandwidth, you should "layer" your JAR. This separates dependencies (which rarely change) from your code (which changes often).

      Layer Content Frequency of Change
      Dependencies External JARs (Spring, Hibernate). Low
      Spring Boot Loader Internal loader classes. Very Low
      Snapshot Dependencies Unstable internal dependencies. Medium
      Application Your compiled .class files. High

    7. Running the Container
    8. Once built, you can run your application using the following command:


      Best Practices
      • Use JRE, not JDK: The runtime (JRE) is much smaller and more secure for the final image.
      • Don't run as root: Use the USER command in your Dockerfile to run the application as a non-privileged user.
      • Environment Variables: Pass secrets and configuration (like DB URLs) via environment variables rather than hardcoding them in application.properties.

    Overview

    Cloud Native Buildpacks (CNB) are a modern standard for transforming application source code into OCI-compliant container images without the need for a Dockerfile. Spring Boot integrates this technology via the Paketo Buildpacks project, allowing you to build production-ready, highly optimized images directly from your build tool (Maven or Gradle).


    How bootBuildImage (Gradle) or spring-boot:build-image (Maven) Works

    When you execute the build-image command, Spring Boot initiates a process that communicates with a Docker daemon to build an image using a "Builder."


    The process follows these steps:
    1. Detect: The builder examines your project to determine which buildpacks are needed (e.g., Java, Maven, or GraalVM).
    2. Build: The buildpack downloads the appropriate JRE and compiles your code.
    3. Layering: It automatically organizes the image into distinct layers (dependencies, loader, resources, and application).
    4. Export: It packages everything into a secure, minimal container image (usually based on a hardened Linux distribution like Ubuntu or Alpine).

    Comparison: Dockerfile vs. Buildpacks
    Feature Manual Dockerfile Spring Boot Buildpacks
    Effort Requires writing and maintaining a script. Zero-config; works out of the box.
    Security You are responsible for OS updates. Automatically uses secure, updated base images.
    Layering Must be manually optimized for cache. Automatically optimized for Docker caching.
    JRE Management Manual versioning in FROM clause. Detects the required Java version automatically.
    BOM Support None. Generates a Software Bill of Materials (SBOM).

    Key Benefits of Buildpacks
    • Security (SBOM): Buildpacks generate a list of every library and OS package included in the image. This is critical for vulnerability scanning (e.g., finding instances of Log4j).
    • Automatic OS Patching: Because the layers are standardized, tools can "rebase" your image to update the underlying Operating System without rebuilding the entire application.
    • Best Practices by Default: It automatically handles memory settings for the JVM inside a container (calculating heap size based on container limits), which is a common source of "OOM Kill" errors in manual Dockerfiles.

    Usage Example

    If you have Docker running locally, you can create your image with one command:

    Maven:
    Gradle:

    Overview

    In a Spring Boot environment, Database Migration tools like Flyway and Liquibase allow you to manage schema changes (adding tables, altering columns) in a version-controlled, automated way. Instead of running SQL scripts manually, the application applies them automatically during startup.


    1. Flyway: Simplicity and SQL-First
    2. Flyway uses a "migration-by-convention" approach. It tracks which scripts have been executed using a metadata table (schema_version,).

      • Mechanism: You write plain SQL files.
      • Naming Convention: Files must follow a pattern like V1__Initial_Setup.sql, V2__Add_Users_Table.sql.
      • Location: Scripts are placed in src/main/resources/db/migration.
      Example SQL (V1__Create_Tables.sql):

    3. Liquibase: Flexibility and Abstraction
    4. Liquibase is more complex but offers powerful features like database-agnostic changes and rollbacks.

      • Mechanism: Changes are defined in a Changelog (XML, YAML, JSON, or SQL).
      • Database Agnostic: If you define a change in YAML, Liquibase generates the correct SQL for PostgreSQL, MySQL, or Oracle automatically.
      • Control: Offers "Contexts" and "Labels" to run specific scripts only in certain environments (e.g., test vs. prod).
      Example YAML ChangeSet:

      Key Comparison
      Feature Flyway Liquibase
      Primary Format Plain SQL. XML, YAML, JSON, or SQL.
      Learning Curve Low (if you know SQL). Moderate to High.
      Rollbacks Only in Pro/Enterprise version. Built-in support.
      Best For Teams who prefer pure SQL control. Complex enterprise apps with multiple DB types.
      Spring Integration spring-boot-starter-flyway spring-boot-starter-liquibase

    How Spring Boot Executes Migrations
    1. Dependency: Add the starter to your pom.xml or build.gradle.
    2. Auto-Configuration: Spring Boot detects the library on the classpath.
    3. Execution: On startup, before the Hibernate SessionFactory or JPA EntityManager is created, the migration tool scans the migration folder.
    4. Validation: It compares the checksums of existing scripts to ensure no history has been tampered with.
    5. Update: It executes any new scripts and updates the tracking table.

    Important Tip: In production, always set spring.jpa.hibernate.ddl-auto=validate (or none) to ensure Hibernate doesn't interfere with your migration tool.

    Overview

    Graceful Shutdown is a feature that ensures an application closes down cleanly without abruptly cutting off active requests. When a shutdown signal is received (like a SIGTERM in a Kubernetes cluster), the application stops accepting new traffic but allows currently processing requests a "grace period" to finish.

    Without graceful shutdown, a process might terminate while a user is mid-purchase or mid-file upload, leading to data inconsistency or a poor user experience.


    How it Works in Spring Boot

    When enabled, the shutdown process follows a specific sequence:

    1. Transition to "Shutting Down": The web server (Tomcat, Jetty, etc.) stops accepting new incoming HTTP requests.
    2. Grace Period: The server waits for active requests to complete.
    3. Timeout: If requests don't finish within a pre-configured time limit, the server kills them and the application shuts down.

    Configuration

    Graceful shutdown is supported on all four major embedded web servers (Tomcat, Jetty, Undertow, and Netty). To enable it, you must configure two properties in your application.properties or application.yml:

    Property Value Description
    server.shutdown graceful Enables the graceful shutdown mode (default is immediate).
    spring.lifecycle.timeout-per-shutdown-phase e.g., 30s The maximum time the app waits for active tasks to finish.
    Example application.yml:

    Graceful Shutdown vs. Immediate Shutdown
    Feature Immediate (Default) Graceful
    New Requests Rejected immediately. Rejected immediately.
    Active Requests Terminated instantly (HTTP 500 or connection reset). Allowed to complete.
    Data Integrity High risk of partial writes. Low risk; transactions finish.
    Shutdown Speed Very Fast. Slower (up to the timeout limit).

    Use Case: Kubernetes & Cloud

    In modern cloud environments, graceful shutdown is essential. When Kubernetes scales down a pod or performs a rolling update:

    1. It sends a SIGTERM to the container.
    2. The Load Balancer stops routing traffic to that pod.
    3. Spring Boot’s Graceful Shutdown ensures that the "last" users routed to that pod aren't disconnected while the new version of the app is spinning up.

    Overview

    Spring Boot DevTools is a module designed specifically to improve the developer experience by reducing the time spent waiting for the application to restart after code changes. It provides Hot Reloading through a combination of automatic restarts and "LiveReload" functionality.


    1. Key Features of DevTools
    2. Feature Description
      Automatic Restart Restarts the application context whenever files on the classpath change.
      LiveReload Automatically refreshes the browser when resources (HTML, CSS, JS) are updated.
      Property Defaults Disables caching (e.g., Thymeleaf templates) so changes are visible instantly.
      Remote Update Allows pushing code changes to a remote application (e.g., running in a cloud dev environment).

    3. How Automatic Restart Works
    4. DevTools uses a two-classloader approach to make restarts faster than a standard cold start:

      • Base Classloader: Loads third-party JARs (which don't change often).
      • Restart Classloader: Loads your application code. When a change is detected, only the Restart Classloader is discarded and recreated, making the "restart" significantly quicker.

    5. Enabling DevTools
    6. To use it, simply add the dependency to your project. It is automatically disabled when the application is packaged as a "Fat JAR" for production.

      Maven:
      Gradle:

    7. Triggering the Reload
    8. Depending on your IDE, the trigger for the reload varies:

      • IntelliJ IDEA: You must trigger a "Build" (Ctrl+F9 or Cmd+F9). You can also enable "Build project automatically" in settings.
      • Eclipse: Saving a file (Ctrl+S) triggers the build and restart by default.
      • VS Code: Saving the file triggers the reload if "Auto Build" is enabled in the Java extension.

    9. LiveReload (Browser Integration)
    10. DevTools includes an embedded LiveReload server. To see your UI changes reflected without hitting the refresh button:

    1. Install the LiveReload browser extension (Chrome/Firefox).
    2. Click the extension icon to connect to your running Spring Boot app.
    3. Modify an HTML or CSS file; the browser will refresh the moment you save/build.

    Comparison: DevTools vs. JRebel
    Metric Spring Boot DevTools JRebel (Commercial)
    Cost Free (Open Source). Paid Subscription.
    Mechanism Context Restart (fast). Bytecode manipulation (instant).
    State Retention Loses in-memory state (sessions, etc). Maintains in-memory state.

    Overview

    The @SpringBootTest annotation is the primary annotation used for Integration Testing in Spring Boot. Unlike a unit test (which might only test a single class in isolation), @SpringBootTest tells Spring to bootstrap the entire Application Context (or a significant portion of it) for your test.


    Key Functions
    • Context Loading: It creates the ApplicationContext that will be used in your test, ensuring all beans are wired together just as they would be in a running application.
    • Search for Configuration: It starts from the package of the test and searches upward until it finds a class annotated with @SpringBootConfiguration (usually your @SpringBootApplication class).
    • Support for Web Environments: It can start a real or mock web server to test your API endpoints.

    Web Environment Modes

    You can configure how the test environment is set up using the webEnvironment attribute:

    Mode Description Use Case
    MOCK (Default) Loads a web ApplicationContext and provides a mock web environment. Testing controllers with MockMvc.
    RANDOM_PORT Loads a real EmbeddedWebApplicationContext and starts a real server on a random port. End-to-end testing with RestTemplate or WebTestClient.
    DEFINED_PORT Starts a real server on your configured port (usually 8080). Manual testing or specific port requirements.
    NONE Loads the ApplicationContext but does not provide any web environment. Testing non-web components like services or repositories.

    Comparison: @SpringBootTest vs. @WebMvcTest
    Feature @SpringBootTest @WebMvcTest
    Scope Full Application Context. Only Web Layer (Controllers).
    Performance Slower (starts everything). Faster (loads only what's needed).
    Dependency Injection All real beans are available. Requires @MockBean for services/repos.
    Test Type Integration/End-to-End. Sliced/Unit testing for Web layer.

    Example Usage

    In this example, we start a real server on a random port and use WebTestClient to perform a real HTTP request.


    Commonly Used Helper Annotations
    • @MockBean: Used to add a mock to the ApplicationContext, replacing any existing bean of the same type.
    • @TestPropertySource: Used to override specific properties just for the test.
    • @ActiveProfiles: Used to run the test using a specific profile (e.g., test).

    Overview

    The @MockBean annotation is a specialized Spring Boot testing tool used to add Mockito mocks to the Spring ApplicationContext. It is primarily used when you want to perform an Integration Test or a Slice Test (like @WebMvcTest) but need to simulate the behavior of a specific dependency rather than using the real one.

    When you use @MockBean, Spring replaces any existing bean of the same type in the context with a Mockito mock.


    How @MockBean Works
    1. Bean Replacement: If a bean of that type already exists in the context, Spring "swaps" it with the mock.
    2. Context Integration: Unlike a standard Mockito @Mock (which is just a local object), a @MockBean is a "first-class citizen" of the Spring Context. Other beans (like your Controller) will have this mock injected into them automatically.
    3. Reset Behavior: Spring automatically resets the mock after each test method to ensure test isolation.

    Core Differences: @Mock vs. @MockBean
    Feature @Mock (Mockito) @MockBean (Spring Boot)
    Library Pure Mockito. Spring Boot Test.
    Context Independent of Spring. Part of the Spring ApplicationContext.
    Injection Manual or via @InjectMocks. Handled by Spring's @Autowired logic.
    Use Case Fast Unit Tests (no Spring context). Integration or Sliced Tests.

    Example Usage: Testing a Controller

    In this scenario, we use @WebMvcTest to test only the web layer. Since the UserService is not loaded by this slice, we must provide a @MockBean for it.


    When to Use @MockBean
    • External Services: When your service calls an external API (like a Payment Gateway) that you don't want to hit during tests.
    • Database Isolation: When you want to test your Service layer logic without actually hitting a real or H2 database.
    • Complex Dependencies: When the real bean requires a heavy setup (like a Kafka producer or a Mail server) that isn't necessary for the current test.

    Common Pitfalls
    • Context Caching: Using @MockBean on different classes can lead to "Context Dirtying." Spring might have to restart the ApplicationContext frequently, which can slow down your test suite.
    • Verification: Remember to use Mockito's verify(service).method() to ensure the mock was actually called as expected.

    Overview

    Testcontainers is an open-source Java library that allows you to spin up real instances of databases, message brokers, or any service that can run in a Docker container during your integration tests.

    Instead of relying on "in-memory" substitutes like H2 (which might behave differently than your production database), Testcontainers ensures your tests run against the exact same technology stack used in production.


    Why Use Testcontainers?

    Historically, developers used H2 for testing and PostgreSQL for production. This led to "it works on my machine" bugs where H2 supported a feature or syntax that PostgreSQL did not (or vice versa).

    Feature In-Memory DB (H2) Testcontainers (Real DB)
    Fidelity Low. Simulates behavior. High. It is the real service.
    Setup Easy (embedded). Requires Docker on the machine.
    Speed Extremely Fast. Moderate (container startup time).
    Reliability May miss DB-specific bugs. Catches DB-specific bugs (e.g., JSONB, Triggers).
    Isolation Shared state is common. Fresh container per test class/method.

    How it Works with Spring Boot
    1. Startup: When the test starts, Testcontainers talks to your Docker daemon and pulls the required image (e.g., postgres:16).
    2. Configuration: It starts the container on a random available port to avoid conflicts.
    3. Dynamic Mapping: It injects the random port and connection details into Spring’s Environment properties.
    4. Cleanup: Once the tests are finished, it automatically stops and deletes the container.

    Implementation (Spring Boot 3.1+)

    Spring Boot 3.1 introduced the Service Connection API, which drastically simplifies the setup by removing the need for manual property mapping.


    Commonly Used Containers
    • Databases: PostgreSQL, MySQL, Oracle, MongoDB, Redis.
    • Messaging: Kafka, RabbitMQ, Pulsar.
    • Browsers: Selenium/WebDriver (for UI testing).
    • LocalStack: For mocking AWS services (S3, SQS, DynamoDB).

    Best Practice: Singleton Containers

    Starting a new container for every test class can be slow. A common pattern is to define a "Base Test Class" that starts the containers once and reuses them across the entire test suite, significantly reducing total test time.

    Overview

    MockMvc is the main entry point for server-side Spring MVC testing. It allows you to test your REST controllers without starting a full HTTP server. Instead, it "mocks" the entire Spring MVC infrastructure, sending requests directly to the DispatcherServlet and verifying the responses.

    This provides a high level of confidence in your web layer while maintaining the speed of a near-unit test.


    1. Key Capabilities
      • Perform Requests: Simulate any HTTP method (GET, POST, PUT, DELETE, etc.).
      • Set Headers/Body: Send JSON payloads, set Content-Types, and handle cookies or session data.
      • Expectations: Verify status codes, headers, and response bodies using jsonPath.

    2. Setup Styles
    3. There are two primary ways to set up MockMvc:

      Method Annotation Description
      Full Context @SpringBootTest + @AutoConfigureMockMvc Loads the entire application context. Useful for deep integration tests.
      Web Slice @WebMvcTest(YourController.class) Only loads the web layer (Controller, Advice, Filters). Faster and more focused.

    4. Example Implementation
    5. The following example shows how to test a POST request that returns a JSON object.


    6. Understanding JsonPath
    7. jsonPath is a powerful syntax used to inspect the returned JSON structure.

      • $.name: Accesses the "name" field at the root.
      • $.items[0].id: Accesses the "id" of the first element in an array.
      • $.[*].name: Returns an array of all "name" fields in the response.

    Comparison: MockMvc vs. WebTestClient
    Feature MockMvc WebTestClient
    Server No server started (Mocked). Can be mocked or run against real server.
    Paradigm Blocking/Servlet-based. Reactive/Non-blocking (WebFlux).
    Context Standard Spring MVC. Preferred for Spring Boot 3+ and WebFlux.

    Overview

    When moving a Spring Boot application to a production environment, you typically choose between running the application as a single compressed file (Fat JAR) or unpacking that file into its constituent parts (Exploded Directory).

    While the Fat JAR is the "standard" Spring Boot approach, the Exploded Directory strategy has become increasingly popular in the age of Docker and Kubernetes due to its efficiency.


    1. Fat JAR Deployment
    2. As discussed in previous questions, theFat JAR bundles your code, dependencies, and the embedded server into one .jar file.

      • Execution: java -jar app.jar
      • Pros: Extremely simple to move; a single file represents a single version of the truth.
      • Cons: Less efficient for Docker caching because changing one line of code requires re-uploading the entire (often 100MB+) file.
    3. Exploded Directory Deployment
    4. In an Exploded Directory strategy, the JAR file is unzipped before the application is started. The JVM is then pointed to the specific folders containing the classes and libraries.

      • Execution: java org.springframework.boot.loader.JarLauncher (after unzipping).
      • Pros: Optimized for container layering. Since dependencies are separated from application code, Docker only needs to rebuild the "code layer" (usually < 1MB).
      • Cons: More complex manual management if not using a container orchestrator.

      Comparison Table
      Feature Fat JAR Exploded Directory
      Packaging Single .jar file. Folder structure (BOOT-INF/lib, BOOT-INF/classes).
      Startup Speed Slightly slower (must index nested JARs). Faster (direct filesystem access).
      Docker Caching Poor (One big layer). Excellent (Layered by change frequency).
      Portability High (standalone). Medium (requires a specific folder structure).
      Production Use Standard/Legacy Cloud. Modern Kubernetes/Container best practice.

      Which should you choose?
      • Choose Fat JAR if you are deploying to a traditional Virtual Machine (VM), a simple VPS, or using a "Platform as a Service" (PaaS) like Heroku where you simply upload a build artifact.
      • Choose Exploded Directory if you are building Docker images. By unzipping the JAR in your Dockerfile, you ensure that your node_modules equivalent (the Maven dependencies) stay in a cached layer, making your CI/CD pipelines significantly faster.

      How to "Explode" a JAR in a Dockerfile

    From The Same Category

    Next.js

    Browse FAQ's

    Ruby On Rails

    Browse FAQ's

    Express.js

    Browse FAQ's

    Laravel

    Browse FAQ's

    Flask

    Browse FAQ's

    ASP.NET

    Browse FAQ's

    Django

    Browse FAQ's

    DocsAllOver

    Where knowledge is just a click away ! DocsAllOver is a one-stop-shop for all your software programming needs, from beginner tutorials to advanced documentation

    Get In Touch

    We'd love to hear from you! Get in touch and let's collaborate on something great

    Copyright copyright © Docsallover - Your One Shop Stop For Documentation