Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/spring-projects/spring-boot/llms.txt

Use this file to discover all available pages before exploring further.

Spring Boot’s IO support covers everything from making outbound HTTP calls and caching expensive computations, to sending email, scheduling jobs, processing batches, and exposing gRPC services. Each area is backed by a dedicated auto-configuration that activates when the right dependency is on the classpath.

HTTP clients

RestClient, WebClient, and RestTemplate for imperative and reactive outbound HTTP calls.

Caching

@Cacheable, @CachePut, @CacheEvict backed by Redis, Caffeine, Hazelcast, and more.

Email

JavaMailSender auto-configuration via spring-boot-starter-mail for SMTP email sending.

Validation

Bean Validation 1.1 with Hibernate Validator, @Valid, @Validated, and constraint annotations.

Quartz scheduler

spring-boot-starter-quartz for cron-based and trigger-based job scheduling.

Spring Batch

Batch job processing with in-memory, JDBC, or MongoDB job repositories.

gRPC

spring-boot-starter-grpc-server and spring-boot-starter-grpc-client for Protocol Buffers RPC.

HTTP clients

Spring Boot provides various convenient ways to call remote REST services. Use RestClient for imperative (blocking) applications, WebClient for reactive applications, or RestTemplate for legacy code.
Spring Boot creates and pre-configures a prototype RestClient.Builder bean. Inject the builder into your components to create RestClient instances:
MyService.java
@Service
public class MyService {

    private final RestClient restClient;

    public MyService(RestClient.Builder restClientBuilder) {
        this.restClient = restClientBuilder
            .baseUrl("https://api.example.com")
            .build();
    }

    public User getUser(Long id) {
        return restClient.get()
            .uri("/users/{id}", id)
            .retrieve()
            .body(User.class);
    }
}
Apply SSL configuration using an SSL bundle:
MyService.java
@Service
public class MyService {

    private final RestClient restClient;

    public MyService(RestClient.Builder restClientBuilder, RestClientSsl ssl) {
        this.restClient = restClientBuilder
            .apply(ssl.fromBundle("my-ssl-bundle"))
            .build();
    }
}
Configure global timeouts for all auto-configured clients:
application.yaml
spring:
  http:
    clients:
      connect-timeout: 2s
      read-timeout: 1s
      redirects: dont-follow

Caching

Spring Boot auto-configures the cache infrastructure when caching support is enabled with @EnableCaching. It selects a cache provider from your classpath — Redis, Caffeine, Hazelcast, Infinispan, JCache, or a simple in-memory ConcurrentHashMap as a fallback. Add the starter:
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
Enable caching and annotate service methods:
MyMathService.java
@Service
public class MyMathService {

    @Cacheable("piDecimals")
    public int computePiDecimal(int precision) {
        // expensive computation
        return computeActualPiDecimal(precision);
    }

    @CacheEvict(value = "piDecimals", allEntries = true)
    public void clearCache() {}
}
Before invoking computePiDecimal, Spring looks for an entry in the piDecimals cache matching the precision argument. If found, the cached value is returned immediately without invoking the method.
Avoid adding @EnableCaching to your main application class. Doing so makes caching mandatory, including when running test slices that do not need it.
Configure cache providers with properties:
application.yaml
spring:
  cache:
    type: "redis"               # explicit provider selection
    cache-names: "users,orders"
    redis:
      time-to-live: "10m"
For Caffeine:
application.yaml
spring:
  cache:
    cache-names: "cache1,cache2"
    caffeine:
      spec: "maximumSize=500,expireAfterAccess=600s"

Email

Spring Boot auto-configures JavaMailSender when spring-boot-starter-mail is present and spring.mail.host is set.
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-mail</artifactId>
</dependency>
application.yaml
spring:
  mail:
    host: "smtp.example.com"
    port: 587
    username: "user@example.com"
    password: "secret"
    properties:
      "[mail.smtp.auth]": true
      "[mail.smtp.starttls.enable]": true
      "[mail.smtp.connectiontimeout]": 5000
      "[mail.smtp.timeout]": 3000
      "[mail.smtp.writetimeout]": 5000
Inject and use JavaMailSender directly in your services:
MyEmailService.java
@Service
public class MyEmailService {

    private final JavaMailSender mailSender;

    public MyEmailService(JavaMailSender mailSender) {
        this.mailSender = mailSender;
    }

    public void sendWelcomeEmail(String to, String name) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setFrom("noreply@example.com");
        message.setTo(to);
        message.setSubject("Welcome to our application");
        message.setText("Hello " + name + ", welcome!");
        mailSender.send(message);
    }
}

Validation

Bean Validation 1.1 is automatically enabled when a JSR-303 implementation (such as Hibernate Validator) is on the classpath. Add the starter:
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Annotate your service class with @Validated and use constraint annotations on parameters:
MyBean.java
@Service
@Validated
public class MyBean {

    public Archive findByCodeAndFormatWithSomeCodeAndAnotherCode(
            @Size(min = 8, max = 10) String code,
            @NotNull Format format) {
        return archiveRepository.findByCode(code);
    }
}
Use @Valid in controllers to trigger validation on request bodies:
MyController.java
@RestController
public class MyController {

    @PostMapping("/users")
    public User createUser(@Valid @RequestBody CreateUserRequest request) {
        return userService.create(request);
    }
}
Common constraint annotations: @NotNull, @NotBlank, @Size, @Min, @Max, @Email, @Pattern, @Positive, @Future.

Quartz scheduler

Spring Boot offers several conveniences for working with the Quartz scheduler, including the spring-boot-starter-quartz starter. A Scheduler is auto-configured through SchedulerFactoryBean.
pom.xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Beans of these types are automatically picked up and associated with the Scheduler:
  • JobDetail — defines a particular job
  • Calendar
  • Trigger — defines when a particular job is triggered
Use JDBC-backed job storage for persistence:
application.yaml
spring:
  quartz:
    job-store-type: "jdbc"
    jdbc:
      initialize-schema: "always"
By default, the database is detected and initialized using standard scripts provided with the Quartz library. These scripts drop existing tables, deleting all triggers on every restart. Use spring.quartz.jdbc.schema to point to a custom script if you need to preserve triggers between restarts.
Define a job with dependency injection:
MySampleJob.java
@Component
public class MySampleJob extends QuartzJobBean {

    private final MyService myService;

    public MySampleJob(MyService myService) {
        this.myService = myService;
    }

    @Override
    protected void executeInternal(JobExecutionContext context) {
        myService.doWork();
    }
}

Spring Batch

Spring Boot offers several conveniences for working with Spring Batch, including running a Job on startup automatically when a single Job bean is found in the application context. Supported job repository stores:
  • In-memory — for development and testing
  • JDBC — for production, with configurable table prefix
  • MongoDB — document-based job metadata
application.yaml
spring:
  batch:
    jdbc:
      table-prefix: "CUSTOM_"
    job:
      enabled: true   # set to false to prevent auto-run on startup
For MongoDB store, enable schema initialization:
application.yaml
spring:
  batch:
    data:
      mongodb:
        schema:
          initialize: true
If multiple Job beans are found, specify which to run:
application.yaml
spring:
  batch:
    job:
      name: "myImportJob"

gRPC

Spring Boot includes support for developing and testing both client and server gRPC applications using spring-boot-starter-grpc-server and spring-boot-starter-grpc-client.
1

Define a service in a .proto file

hello.proto
syntax = "proto3";

option java_package = "com.example.grpc.proto";
option java_multiple_files = true;

service HelloWorld {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 1;
}
Place .proto files in src/main/proto. Add the Maven or Gradle protobuf plugin to generate Java code.
2

Implement the gRPC server

Extend the generated base class and annotate it with @GrpcService:
MyHelloWorldService.java
@GrpcService
public class MyHelloWorldService extends HelloWorldGrpc.HelloWorldImplBase {

    @Override
    public void sayHello(HelloRequest request, StreamObserver<HelloReply> responseObserver) {
        HelloReply reply = HelloReply.newBuilder()
            .setMessage("Hello '" + request.getName() + "'")
            .build();
        responseObserver.onNext(reply);
        responseObserver.onCompleted();
    }
}
The server starts on port 9090 by default using Netty.
3

Call the gRPC server from a client

Import stub classes using @ImportGrpcClients and configure the channel:
MyApplication.java
@SpringBootApplication
@ImportGrpcClients(types = HelloWorldGrpc.HelloWorldBlockingStub.class,
                   target = "myservice")
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}
application.yaml
spring:
  grpc:
    client:
      channel:
        myservice:
          target: static://grpc.example.com:9090
Use the stub bean like any other Spring bean:
MyApplicationRunner.java
@Component
public class MyApplicationRunner implements ApplicationRunner {

    private final HelloWorldGrpc.HelloWorldBlockingStub stub;

    public MyApplicationRunner(HelloWorldGrpc.HelloWorldBlockingStub stub) {
        this.stub = stub;
    }

    @Override
    public void run(ApplicationArguments args) {
        HelloReply reply = stub.sayHello(
            HelloRequest.newBuilder().setName("Spring").build()
        );
        System.out.println(reply.getMessage());
    }
}
Configure gRPC server SSL using SSL bundles:
application.yaml
spring:
  grpc:
    server:
      port: 9090
      ssl:
        bundle: mysslbundle
For testing, use @AutoConfigureTestGrpcTransport to replace gRPC channels with in-process test channels. This avoids needing to listen on a real network port and makes tests run faster.

Build docs developers (and LLMs) love