IO
==========
Table of Contents
[Back to index](index.html)
* [1. Caching](#io.caching)
* [1.1. Supported Cache Providers](#io.caching.provider)
* [1.1.1. Generic](#io.caching.provider.generic)
* [1.1.2. JCache (JSR-107)](#io.caching.provider.jcache)
* [1.1.3. EhCache 2.x](#io.caching.provider.ehcache2)
* [1.1.4. Hazelcast](#io.caching.provider.hazelcast)
* [1.1.5. Infinispan](#io.caching.provider.infinispan)
* [1.1.6. Couchbase](#io.caching.provider.couchbase)
* [1.1.7. Redis](#io.caching.provider.redis)
* [1.1.8. Caffeine](#io.caching.provider.caffeine)
* [1.1.9. Simple](#io.caching.provider.simple)
* [1.1.10. None](#io.caching.provider.none)
* [2. Hazelcast](#io.hazelcast)
* [3. Quartz Scheduler](#io.quartz)
* [4. Sending Email](#io.email)
* [5. Validation](#io.validation)
* [6. Calling REST Services](#io.rest-client)
* [6.1. RestTemplate](#io.rest-client.resttemplate)
* [6.1.1. RestTemplate Customization](#io.rest-client.resttemplate.customization)
* [6.2. WebClient](#io.rest-client.webclient)
* [6.2.1. WebClient Runtime](#io.rest-client.webclient.runtime)
* [6.2.2. WebClient Customization](#io.rest-client.webclient.customization)
* [7. Web Services](#io.webservices)
* [7.1. Calling Web Services with WebServiceTemplate](#io.webservices.template)
* [8. Distributed Transactions with JTA](#io.jta)
* [8.1. Using an Atomikos Transaction Manager](#io.jta.atomikos)
* [8.2. Using a Java EE Managed Transaction Manager](#io.jta.javaee)
* [8.3. Mixing XA and Non-XA JMS Connections](#io.jta.mixing-xa-and-non-xa-connections)
* [8.4. Supporting an Alternative Embedded Transaction Manager](#io.jta.supporting-alternative-embedded-transaction-manager)
* [9. What to Read Next](#io.whats-next)
Most applications will need to deal with input and output concerns at some point.
Spring Boot provides utilities and integrations with a range of technologies to help when you need IO capabilities.
This section covers standard IO features such as caching and validation as well as more advanced topics such as scheduling and distributed transactions.
We will also cover calling remote REST or SOAP services and sending email.
[](#io.caching)1. Caching
----------
The Spring Framework provides support for transparently adding caching to an application.
At its core, the abstraction applies caching to methods, thus reducing the number of executions based on the information available in the cache.
The caching logic is applied transparently, without any interference to the invoker.
Spring Boot auto-configures the cache infrastructure as long as caching support is enabled by using the `@EnableCaching` annotation.
| |Check the [relevant section](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/integration.html#cache) of the Spring Framework reference for more details.|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
In a nutshell, to add caching to an operation of your service add the relevant annotation to its method, as shown in the following example:
```
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
@Component
public class MyMathService {
@Cacheable("piDecimals")
public int computePiDecimal(int precision) {
...
}
}
```
This example demonstrates the use of caching on a potentially costly operation.
Before invoking `computePiDecimal`, the abstraction looks for an entry in the `piDecimals` cache that matches the `i` argument.
If an entry is found, the content in the cache is immediately returned to the caller, and the method is not invoked.
Otherwise, the method is invoked, and the cache is updated before returning the value.
| |You can also use the standard JSR-107 (JCache) annotations (such as `@CacheResult`) transparently. However, we strongly advise you to not mix and match the Spring Cache and JCache annotations.|
|---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
If you do not add any specific cache library, Spring Boot auto-configures a [simple provider](#io.caching.provider.simple) that uses concurrent maps in memory.
When a cache is required (such as `piDecimals` in the preceding example), this provider creates it for you.
The simple provider is not really recommended for production usage, but it is great for getting started and making sure that you understand the features.
When you have made up your mind about the cache provider to use, please make sure to read its documentation to figure out how to configure the caches that your application uses.
Nearly all providers require you to explicitly configure every cache that you use in the application.
Some offer a way to customize the default caches defined by the `spring.cache.cache-names` property.
| |It is also possible to transparently [update](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/integration.html#cache-annotations-put) or [evict](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/integration.html#cache-annotations-evict) data from the cache.|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### [](#io.caching.provider)1.1. Supported Cache Providers ###
The cache abstraction does not provide an actual store and relies on abstraction materialized by the `org.springframework.cache.Cache` and `org.springframework.cache.CacheManager` interfaces.
If you have not defined a bean of type `CacheManager` or a `CacheResolver` named `cacheResolver` (see [`CachingConfigurer`](https://docs.spring.io/spring-framework/docs/5.3.16/javadoc-api/org/springframework/cache/annotation/CachingConfigurer.html)), Spring Boot tries to detect the following providers (in the indicated order):
1. [Generic](#io.caching.provider.generic)
2. [JCache (JSR-107)](#io.caching.provider.jcache) (EhCache 3, Hazelcast, Infinispan, and others)
3. [EhCache 2.x](#io.caching.provider.ehcache2)
4. [Hazelcast](#io.caching.provider.hazelcast)
5. [Infinispan](#io.caching.provider.infinispan)
6. [Couchbase](#io.caching.provider.couchbase)
7. [Redis](#io.caching.provider.redis)
8. [Caffeine](#io.caching.provider.caffeine)
9. [Simple](#io.caching.provider.simple)
| |It is also possible to *force* a particular cache provider by setting the `spring.cache.type` property. Use this property if you need to [disable caching altogether](#io.caching.provider.none) in certain environments (such as tests).|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |Use the `spring-boot-starter-cache` “Starter” to quickly add basic caching dependencies. The starter brings in `spring-context-support`. If you add dependencies manually, you must include `spring-context-support` in order to use the JCache, EhCache 2.x, or Caffeine support.|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
If the `CacheManager` is auto-configured by Spring Boot, you can further tune its configuration before it is fully initialized by exposing a bean that implements the `CacheManagerCustomizer` interface.
The following example sets a flag to say that `null` values should not be passed down to the underlying map:
```
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer;
import org.springframework.cache.concurrent.ConcurrentMapCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration(proxyBeanMethods = false)
public class MyCacheManagerConfiguration {
@Bean
public CacheManagerCustomizer cacheManagerCustomizer() {
return (cacheManager) -> cacheManager.setAllowNullValues(false);
}
}
```
| |In the preceding example, an auto-configured `ConcurrentMapCacheManager` is expected. If that is not the case (either you provided your own config or a different cache provider was auto-configured), the customizer is not invoked at all. You can have as many customizers as you want, and you can also order them by using `@Order` or `Ordered`.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### [](#io.caching.provider.generic)1.1.1. Generic ####
Generic caching is used if the context defines *at least* one `org.springframework.cache.Cache` bean.
A `CacheManager` wrapping all beans of that type is created.
#### [](#io.caching.provider.jcache)1.1.2. JCache (JSR-107) ####
[JCache](https://jcp.org/en/jsr/detail?id=107) is bootstrapped through the presence of a `javax.cache.spi.CachingProvider` on the classpath (that is, a JSR-107 compliant caching library exists on the classpath), and the `JCacheCacheManager` is provided by the `spring-boot-starter-cache` “Starter”.
Various compliant libraries are available, and Spring Boot provides dependency management for Ehcache 3, Hazelcast, and Infinispan.
Any other compliant library can be added as well.
It might happen that more than one provider is present, in which case the provider must be explicitly specified.
Even if the JSR-107 standard does not enforce a standardized way to define the location of the configuration file, Spring Boot does its best to accommodate setting a cache with implementation details, as shown in the following example:
Properties
```
# Only necessary if more than one provider is present
spring.cache.jcache.provider=com.example.MyCachingProvider
spring.cache.jcache.config=classpath:example.xml
```
Yaml
```
# Only necessary if more than one provider is present
spring:
cache:
jcache:
provider: "com.example.MyCachingProvider"
config: "classpath:example.xml"
```
| |When a cache library offers both a native implementation and JSR-107 support, Spring Boot prefers the JSR-107 support, so that the same features are available if you switch to a different JSR-107 implementation.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |Spring Boot has [general support for Hazelcast](#io.hazelcast). If a single `HazelcastInstance` is available, it is automatically reused for the `CacheManager` as well, unless the `spring.cache.jcache.config` property is specified.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
There are two ways to customize the underlying `javax.cache.cacheManager`:
* Caches can be created on startup by setting the `spring.cache.cache-names` property.
If a custom `javax.cache.configuration.Configuration` bean is defined, it is used to customize them.
* `org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer` beans are invoked with the reference of the `CacheManager` for full customization.
| |If a standard `javax.cache.CacheManager` bean is defined, it is wrapped automatically in an `org.springframework.cache.CacheManager` implementation that the abstraction expects. No further customization is applied to it.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### [](#io.caching.provider.ehcache2)1.1.3. EhCache 2.x ####
[EhCache](https://www.ehcache.org/) 2.x is used if a file named `ehcache.xml` can be found at the root of the classpath.
If EhCache 2.x is found, the `EhCacheCacheManager` provided by the `spring-boot-starter-cache` “Starter” is used to bootstrap the cache manager.
An alternate configuration file can be provided as well, as shown in the following example:
Properties
```
spring.cache.ehcache.config=classpath:config/another-config.xml
```
Yaml
```
spring:
cache:
ehcache:
config: "classpath:config/another-config.xml"
```
#### [](#io.caching.provider.hazelcast)1.1.4. Hazelcast ####
Spring Boot has [general support for Hazelcast](#io.hazelcast).
If a `HazelcastInstance` has been auto-configured, it is automatically wrapped in a `CacheManager`.
#### [](#io.caching.provider.infinispan)1.1.5. Infinispan ####
[Infinispan](https://infinispan.org/) has no default configuration file location, so it must be specified explicitly.
Otherwise, the default bootstrap is used.
Properties
```
spring.cache.infinispan.config=infinispan.xml
```
Yaml
```
spring:
cache:
infinispan:
config: "infinispan.xml"
```
Caches can be created on startup by setting the `spring.cache.cache-names` property.
If a custom `ConfigurationBuilder` bean is defined, it is used to customize the caches.
| |The support of Infinispan in Spring Boot is restricted to the embedded mode and is quite basic. If you want more options, you should use the official Infinispan Spring Boot starter instead. See [Infinispan’s documentation](https://github.com/infinispan/infinispan-spring-boot) for more details.|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### [](#io.caching.provider.couchbase)1.1.6. Couchbase ####
If Spring Data Couchbase is available and Couchbase is [configured](data.html#data.nosql.couchbase), a `CouchbaseCacheManager` is auto-configured.
It is possible to create additional caches on startup by setting the `spring.cache.cache-names` property and cache defaults can be configured by using `spring.cache.couchbase.*` properties.
For instance, the following configuration creates `cache1` and `cache2` caches with an entry *expiration* of 10 minutes:
Properties
```
spring.cache.cache-names=cache1,cache2
spring.cache.couchbase.expiration=10m
```
Yaml
```
spring:
cache:
cache-names: "cache1,cache2"
couchbase:
expiration: "10m"
```
If you need more control over the configuration, consider registering a `CouchbaseCacheManagerBuilderCustomizer` bean.
The following example shows a customizer that configures a specific entry expiration for `cache1` and `cache2`:
```
import java.time.Duration;
import org.springframework.boot.autoconfigure.cache.CouchbaseCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.couchbase.cache.CouchbaseCacheConfiguration;
@Configuration(proxyBeanMethods = false)
public class MyCouchbaseCacheManagerConfiguration {
@Bean
public CouchbaseCacheManagerBuilderCustomizer myCouchbaseCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("cache1", CouchbaseCacheConfiguration
.defaultCacheConfig().entryExpiry(Duration.ofSeconds(10)))
.withCacheConfiguration("cache2", CouchbaseCacheConfiguration
.defaultCacheConfig().entryExpiry(Duration.ofMinutes(1)));
}
}
```
#### [](#io.caching.provider.redis)1.1.7. Redis ####
If [Redis](https://redis.io/) is available and configured, a `RedisCacheManager` is auto-configured.
It is possible to create additional caches on startup by setting the `spring.cache.cache-names` property and cache defaults can be configured by using `spring.cache.redis.*` properties.
For instance, the following configuration creates `cache1` and `cache2` caches with a *time to live* of 10 minutes:
Properties
```
spring.cache.cache-names=cache1,cache2
spring.cache.redis.time-to-live=10m
```
Yaml
```
spring:
cache:
cache-names: "cache1,cache2"
redis:
time-to-live: "10m"
```
| |By default, a key prefix is added so that, if two separate caches use the same key, Redis does not have overlapping keys and cannot return invalid values. We strongly recommend keeping this setting enabled if you create your own `RedisCacheManager`.|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |You can take full control of the default configuration by adding a `RedisCacheConfiguration` `@Bean` of your own. This can be useful if you need to customize the default serialization strategy.|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
If you need more control over the configuration, consider registering a `RedisCacheManagerBuilderCustomizer` bean.
The following example shows a customizer that configures a specific time to live for `cache1` and `cache2`:
```
import java.time.Duration;
import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
@Configuration(proxyBeanMethods = false)
public class MyRedisCacheManagerConfiguration {
@Bean
public RedisCacheManagerBuilderCustomizer myRedisCacheManagerBuilderCustomizer() {
return (builder) -> builder
.withCacheConfiguration("cache1", RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofSeconds(10)))
.withCacheConfiguration("cache2", RedisCacheConfiguration
.defaultCacheConfig().entryTtl(Duration.ofMinutes(1)));
}
}
```
#### [](#io.caching.provider.caffeine)1.1.8. Caffeine ####
[Caffeine](https://github.com/ben-manes/caffeine) is a Java 8 rewrite of Guava’s cache that supersedes support for Guava.
If Caffeine is present, a `CaffeineCacheManager` (provided by the `spring-boot-starter-cache` “Starter”) is auto-configured.
Caches can be created on startup by setting the `spring.cache.cache-names` property and can be customized by one of the following (in the indicated order):
1. A cache spec defined by `spring.cache.caffeine.spec`
2. A `com.github.benmanes.caffeine.cache.CaffeineSpec` bean is defined
3. A `com.github.benmanes.caffeine.cache.Caffeine` bean is defined
For instance, the following configuration creates `cache1` and `cache2` caches with a maximum size of 500 and a *time to live* of 10 minutes
Properties
```
spring.cache.cache-names=cache1,cache2
spring.cache.caffeine.spec=maximumSize=500,expireAfterAccess=600s
```
Yaml
```
spring:
cache:
cache-names: "cache1,cache2"
caffeine:
spec: "maximumSize=500,expireAfterAccess=600s"
```
If a `com.github.benmanes.caffeine.cache.CacheLoader` bean is defined, it is automatically associated to the `CaffeineCacheManager`.
Since the `CacheLoader` is going to be associated with *all* caches managed by the cache manager, it must be defined as `CacheLoader