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`. The auto-configuration ignores any other generic type. #### [](#io.caching.provider.simple)1.1.9. Simple #### If none of the other providers can be found, a simple implementation using a `ConcurrentHashMap` as the cache store is configured. This is the default if no caching library is present in your application. By default, caches are created as needed, but you can restrict the list of available caches by setting the `cache-names` property. For instance, if you want only `cache1` and `cache2` caches, set the `cache-names` property as follows: Properties ``` spring.cache.cache-names=cache1,cache2 ``` Yaml ``` spring: cache: cache-names: "cache1,cache2" ``` If you do so and your application uses a cache not listed, then it fails at runtime when the cache is needed, but not on startup. This is similar to the way the "real" cache providers behave if you use an undeclared cache. #### [](#io.caching.provider.none)1.1.10. None #### When `@EnableCaching` is present in your configuration, a suitable cache configuration is expected as well. If you need to disable caching altogether in certain environments, force the cache type to `none` to use a no-op implementation, as shown in the following example: Properties ``` spring.cache.type=none ``` Yaml ``` spring: cache: type: "none" ``` [](#io.hazelcast)2. Hazelcast ---------- If [Hazelcast](https://hazelcast.com/) is on the classpath and a suitable configuration is found, Spring Boot auto-configures a `HazelcastInstance` that you can inject in your application. Spring Boot first attempts to create a client by checking the following configuration options: * The presence of a `com.hazelcast.client.config.ClientConfig` bean. * A configuration file defined by the `spring.hazelcast.config` property. * The presence of the `hazelcast.client.config` system property. * A `hazelcast-client.xml` in the working directory or at the root of the classpath. * A `hazelcast-client.yaml` in the working directory or at the root of the classpath. | |Spring Boot supports both Hazelcast 4 and Hazelcast 3.
If you downgrade to Hazelcast 3, `hazelcast-client` should be added to the classpath to configure a client.| |---|----------------------------------------------------------------------------------------------------------------------------------------------------------------------| If a client can not be created, Spring Boot attempts to configure an embedded server. If you define a `com.hazelcast.config.Config` bean, Spring Boot uses that. If your configuration defines an instance name, Spring Boot tries to locate an existing instance rather than creating a new one. You could also specify the Hazelcast configuration file to use through configuration, as shown in the following example: Properties ``` spring.hazelcast.config=classpath:config/my-hazelcast.xml ``` Yaml ``` spring: hazelcast: config: "classpath:config/my-hazelcast.xml" ``` Otherwise, Spring Boot tries to find the Hazelcast configuration from the default locations: `hazelcast.xml` in the working directory or at the root of the classpath, or a `.yaml` counterpart in the same locations. We also check if the `hazelcast.config` system property is set. See the [Hazelcast documentation](https://docs.hazelcast.org/docs/latest/manual/html-single/) for more details. | |Spring Boot also has [explicit caching support for Hazelcast](#io.caching.provider.hazelcast).
If caching is enabled, the `HazelcastInstance` is automatically wrapped in a `CacheManager` implementation.| |---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| [](#io.quartz)3. Quartz Scheduler ---------- Spring Boot offers several conveniences for working with the [Quartz scheduler](https://www.quartz-scheduler.org/), including the `spring-boot-starter-quartz` “Starter”. If Quartz is available, a `Scheduler` is auto-configured (through the `SchedulerFactoryBean` abstraction). Beans of the following types are automatically picked up and associated with the `Scheduler`: * `JobDetail`: defines a particular Job.`JobDetail` instances can be built with the `JobBuilder` API. * `Calendar`. * `Trigger`: defines when a particular job is triggered. By default, an in-memory `JobStore` is used. However, it is possible to configure a JDBC-based store if a `DataSource` bean is available in your application and if the `spring.quartz.job-store-type` property is configured accordingly, as shown in the following example: Properties ``` spring.quartz.job-store-type=jdbc ``` Yaml ``` spring: quartz: job-store-type: "jdbc" ``` When the JDBC store is used, the schema can be initialized on startup, as shown in the following example: Properties ``` spring.quartz.jdbc.initialize-schema=always ``` Yaml ``` spring: quartz: jdbc: initialize-schema: "always" ``` | |By default, the database is detected and initialized by using the standard scripts provided with the Quartz library.
These scripts drop existing tables, deleting all triggers on every restart.
It is also possible to provide a custom script by setting the `spring.quartz.jdbc.schema` property.| |---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| To have Quartz use a `DataSource` other than the application’s main `DataSource`, declare a `DataSource` bean, annotating its `@Bean` method with `@QuartzDataSource`. Doing so ensures that the Quartz-specific `DataSource` is used by both the `SchedulerFactoryBean` and for schema initialization. Similarly, to have Quartz use a `TransactionManager` other than the application’s main `TransactionManager` declare a `TransactionManager` bean, annotating its `@Bean` method with `@QuartzTransactionManager`. By default, jobs created by configuration will not overwrite already registered jobs that have been read from a persistent job store. To enable overwriting existing job definitions set the `spring.quartz.overwrite-existing-jobs` property. Quartz Scheduler configuration can be customized using `spring.quartz` properties and `SchedulerFactoryBeanCustomizer` beans, which allow programmatic `SchedulerFactoryBean` customization. Advanced Quartz configuration properties can be customized using `spring.quartz.properties.*`. | |In particular, an `Executor` bean is not associated with the scheduler as Quartz offers a way to configure the scheduler through `spring.quartz.properties`.
If you need to customize the task executor, consider implementing `SchedulerFactoryBeanCustomizer`.| |---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Jobs can define setters to inject data map properties. Regular beans can also be injected in a similar manner, as shown in the following example: ``` import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; public class MySampleJob extends QuartzJobBean { // fields ... private MyService myService; private String name; // Inject "MyService" bean public void setMyService(MyService myService) { this.myService = myService; } // Inject the "name" job data property public void setName(String name) { this.name = name; } @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { this.myService.someMethod(context.getFireTime(), this.name); } } ``` [](#io.email)4. Sending Email ---------- The Spring Framework provides an abstraction for sending email by using the `JavaMailSender` interface, and Spring Boot provides auto-configuration for it as well as a starter module. | |See the [reference documentation](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/integration.html#mail) for a detailed explanation of how you can use `JavaMailSender`.| |---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| If `spring.mail.host` and the relevant libraries (as defined by `spring-boot-starter-mail`) are available, a default `JavaMailSender` is created if none exists. The sender can be further customized by configuration items from the `spring.mail` namespace. See [`MailProperties`](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mail/MailProperties.java) for more details. In particular, certain default timeout values are infinite, and you may want to change that to avoid having a thread blocked by an unresponsive mail server, as shown in the following example: Properties ``` spring.mail.properties[mail.smtp.connectiontimeout]=5000 spring.mail.properties[mail.smtp.timeout]=3000 spring.mail.properties[mail.smtp.writetimeout]=5000 ``` Yaml ``` spring: mail: properties: "[mail.smtp.connectiontimeout]": 5000 "[mail.smtp.timeout]": 3000 "[mail.smtp.writetimeout]": 5000 ``` It is also possible to configure a `JavaMailSender` with an existing `Session` from JNDI: Properties ``` spring.mail.jndi-name=mail/Session ``` Yaml ``` spring: mail: jndi-name: "mail/Session" ``` When a `jndi-name` is set, it takes precedence over all other Session-related settings. [](#io.validation)5. Validation ---------- The method validation feature supported by Bean Validation 1.1 is automatically enabled as long as a JSR-303 implementation (such as Hibernate validator) is on the classpath. This lets bean methods be annotated with `javax.validation` constraints on their parameters and/or on their return value. Target classes with such annotated methods need to be annotated with the `@Validated` annotation at the type level for their methods to be searched for inline constraint annotations. For instance, the following service triggers the validation of the first argument, making sure its size is between 8 and 10: ``` import javax.validation.constraints.Size; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @Service @Validated public class MyBean { public Archive findByCodeAndAuthor(@Size(min = 8, max = 10) String code, Author author) { return ... } } ``` The application’s `MessageSource` is used when resolving `{parameters}` in constraint messages. This allows you to use [your application’s `messages.properties` files](features.html#features.internationalization) for Bean Validation messages. Once the parameters have been resolved, message interpolation is completed using Bean Validation’s default interpolator. [](#io.rest-client)6. Calling REST Services ---------- If your application calls remote REST services, Spring Boot makes that very convenient using a `RestTemplate` or a `WebClient`. ### [](#io.rest-client.resttemplate)6.1. RestTemplate ### If you need to call remote REST services from your application, you can use the Spring Framework’s [`RestTemplate`](https://docs.spring.io/spring-framework/docs/5.3.16/javadoc-api/org/springframework/web/client/RestTemplate.html) class. Since `RestTemplate` instances often need to be customized before being used, Spring Boot does not provide any single auto-configured `RestTemplate` bean. It does, however, auto-configure a `RestTemplateBuilder`, which can be used to create `RestTemplate` instances when needed. The auto-configured `RestTemplateBuilder` ensures that sensible `HttpMessageConverters` are applied to `RestTemplate` instances. The following code shows a typical example: ``` import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; @Service public class MyService { private final RestTemplate restTemplate; public MyService(RestTemplateBuilder restTemplateBuilder) { this.restTemplate = restTemplateBuilder.build(); } public Details someRestCall(String name) { return this.restTemplate.getForObject("/{name}/details", Details.class, name); } } ``` | |`RestTemplateBuilder` includes a number of useful methods that can be used to quickly configure a `RestTemplate`.
For example, to add BASIC auth support, you can use `builder.basicAuthentication("user", "password").build()`.| |---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| #### [](#io.rest-client.resttemplate.customization)6.1.1. RestTemplate Customization #### There are three main approaches to `RestTemplate` customization, depending on how broadly you want the customizations to apply. To make the scope of any customizations as narrow as possible, inject the auto-configured `RestTemplateBuilder` and then call its methods as required. Each method call returns a new `RestTemplateBuilder` instance, so the customizations only affect this use of the builder. To make an application-wide, additive customization, use a `RestTemplateCustomizer` bean. All such beans are automatically registered with the auto-configured `RestTemplateBuilder` and are applied to any templates that are built with it. The following example shows a customizer that configures the use of a proxy for all hosts except `192.168.0.5`: ``` import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.client.HttpClient; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.conn.DefaultProxyRoutePlanner; import org.apache.http.protocol.HttpContext; import org.springframework.boot.web.client.RestTemplateCustomizer; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.web.client.RestTemplate; public class MyRestTemplateCustomizer implements RestTemplateCustomizer { @Override public void customize(RestTemplate restTemplate) { HttpRoutePlanner routePlanner = new CustomRoutePlanner(new HttpHost("proxy.example.com")); HttpClient httpClient = HttpClientBuilder.create().setRoutePlanner(routePlanner).build(); restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory(httpClient)); } static class CustomRoutePlanner extends DefaultProxyRoutePlanner { CustomRoutePlanner(HttpHost proxy) { super(proxy); } @Override public HttpHost determineProxy(HttpHost target, HttpRequest request, HttpContext context) throws HttpException { if (target.getHostName().equals("192.168.0.5")) { return null; } return super.determineProxy(target, request, context); } } } ``` Finally, you can define your own `RestTemplateBuilder` bean. Doing so will replace the auto-configured builder. If you want any `RestTemplateCustomizer` beans to be applied to your custom builder, as the auto-configuration would have done, configure it using a `RestTemplateBuilderConfigurer`. The following example exposes a `RestTemplateBuilder` that matches what Spring Boot’s auto-configuration would have done, except that custom connect and read timeouts are also specified: ``` import java.time.Duration; import org.springframework.boot.autoconfigure.web.client.RestTemplateBuilderConfigurer; import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) public class MyRestTemplateBuilderConfiguration { @Bean public RestTemplateBuilder restTemplateBuilder(RestTemplateBuilderConfigurer configurer) { return configurer.configure(new RestTemplateBuilder()).setConnectTimeout(Duration.ofSeconds(5)) .setReadTimeout(Duration.ofSeconds(2)); } } ``` The most extreme (and rarely used) option is to create your own `RestTemplateBuilder` bean without using a configurer. In addition to replacing the auto-configured builder, this also prevents any `RestTemplateCustomizer` beans from being used. ### [](#io.rest-client.webclient)6.2. WebClient ### If you have Spring WebFlux on your classpath, you can also choose to use `WebClient` to call remote REST services. Compared to `RestTemplate`, this client has a more functional feel and is fully reactive. You can learn more about the `WebClient` in the dedicated [section in the Spring Framework docs](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/web-reactive.html#webflux-client). Spring Boot creates and pre-configures a `WebClient.Builder` for you. It is strongly advised to inject it in your components and use it to create `WebClient` instances. Spring Boot is configuring that builder to share HTTP resources, reflect codecs setup in the same fashion as the server ones (see [WebFlux HTTP codecs auto-configuration](web.html#web.reactive.webflux.httpcodecs)), and more. The following code shows a typical example: ``` import org.neo4j.cypherdsl.core.Relationship.Details; import reactor.core.publisher.Mono; import org.springframework.stereotype.Service; import org.springframework.web.reactive.function.client.WebClient; @Service public class MyService { private final WebClient webClient; public MyService(WebClient.Builder webClientBuilder) { this.webClient = webClientBuilder.baseUrl("https://example.org").build(); } public Mono
someRestCall(String name) { return this.webClient.get().uri("/{name}/details", name).retrieve().bodyToMono(Details.class); } } ``` #### [](#io.rest-client.webclient.runtime)6.2.1. WebClient Runtime #### Spring Boot will auto-detect which `ClientHttpConnector` to use to drive `WebClient`, depending on the libraries available on the application classpath. For now, Reactor Netty and Jetty RS client are supported. The `spring-boot-starter-webflux` starter depends on `io.projectreactor.netty:reactor-netty` by default, which brings both server and client implementations. If you choose to use Jetty as a reactive server instead, you should add a dependency on the Jetty Reactive HTTP client library, `org.eclipse.jetty:jetty-reactive-httpclient`. Using the same technology for server and client has it advantages, as it will automatically share HTTP resources between client and server. Developers can override the resource configuration for Jetty and Reactor Netty by providing a custom `ReactorResourceFactory` or `JettyResourceFactory` bean - this will be applied to both clients and servers. If you wish to override that choice for the client, you can define your own `ClientHttpConnector` bean and have full control over the client configuration. You can learn more about the [`WebClient` configuration options in the Spring Framework reference documentation](https://docs.spring.io/spring-framework/docs/5.3.16/reference/html/web-reactive.html#webflux-client-builder). #### [](#io.rest-client.webclient.customization)6.2.2. WebClient Customization #### There are three main approaches to `WebClient` customization, depending on how broadly you want the customizations to apply. To make the scope of any customizations as narrow as possible, inject the auto-configured `WebClient.Builder` and then call its methods as required.`WebClient.Builder` instances are stateful: Any change on the builder is reflected in all clients subsequently created with it. If you want to create several clients with the same builder, you can also consider cloning the builder with `WebClient.Builder other = builder.clone();`. To make an application-wide, additive customization to all `WebClient.Builder` instances, you can declare `WebClientCustomizer` beans and change the `WebClient.Builder` locally at the point of injection. Finally, you can fall back to the original API and use `WebClient.create()`. In that case, no auto-configuration or `WebClientCustomizer` is applied. [](#io.webservices)7. Web Services ---------- Spring Boot provides Web Services auto-configuration so that all you must do is define your `Endpoints`. The [Spring Web Services features](https://docs.spring.io/spring-ws/docs/3.1.2/reference/html/) can be easily accessed with the `spring-boot-starter-webservices` module. `SimpleWsdl11Definition` and `SimpleXsdSchema` beans can be automatically created for your WSDLs and XSDs respectively. To do so, configure their location, as shown in the following example: Properties ``` spring.webservices.wsdl-locations=classpath:/wsdl ``` Yaml ``` spring: webservices: wsdl-locations: "classpath:/wsdl" ``` ### [](#io.webservices.template)7.1. Calling Web Services with WebServiceTemplate ### If you need to call remote Web services from your application, you can use the [`WebServiceTemplate`](https://docs.spring.io/spring-ws/docs/3.1.2/reference/html/#client-web-service-template) class. Since `WebServiceTemplate` instances often need to be customized before being used, Spring Boot does not provide any single auto-configured `WebServiceTemplate` bean. It does, however, auto-configure a `WebServiceTemplateBuilder`, which can be used to create `WebServiceTemplate` instances when needed. The following code shows a typical example: ``` import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; import org.springframework.stereotype.Service; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.soap.client.core.SoapActionCallback; @Service public class MyService { private final WebServiceTemplate webServiceTemplate; public MyService(WebServiceTemplateBuilder webServiceTemplateBuilder) { this.webServiceTemplate = webServiceTemplateBuilder.build(); } public SomeResponse someWsCall(SomeRequest detailsReq) { return (SomeResponse) this.webServiceTemplate.marshalSendAndReceive(detailsReq, new SoapActionCallback("https://ws.example.com/action")); } } ``` By default, `WebServiceTemplateBuilder` detects a suitable HTTP-based `WebServiceMessageSender` using the available HTTP client libraries on the classpath. You can also customize read and connection timeouts as follows: ``` import java.time.Duration; import org.springframework.boot.webservices.client.HttpWebServiceMessageSenderBuilder; import org.springframework.boot.webservices.client.WebServiceTemplateBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.transport.WebServiceMessageSender; @Configuration(proxyBeanMethods = false) public class MyWebServiceTemplateConfiguration { @Bean public WebServiceTemplate webServiceTemplate(WebServiceTemplateBuilder builder) { WebServiceMessageSender sender = new HttpWebServiceMessageSenderBuilder() .setConnectTimeout(Duration.ofSeconds(5)) .setReadTimeout(Duration.ofSeconds(2)) .build(); return builder.messageSenders(sender).build(); } } ``` [](#io.jta)8. Distributed Transactions with JTA ---------- Spring Boot supports distributed JTA transactions across multiple XA resources by using an [Atomikos](https://www.atomikos.com/) embedded transaction manager. JTA transactions are also supported when deploying to a suitable Java EE Application Server. When a JTA environment is detected, Spring’s `JtaTransactionManager` is used to manage transactions. Auto-configured JMS, DataSource, and JPA beans are upgraded to support XA transactions. You can use standard Spring idioms, such as `@Transactional`, to participate in a distributed transaction. If you are within a JTA environment and still want to use local transactions, you can set the `spring.jta.enabled` property to `false` to disable the JTA auto-configuration. ### [](#io.jta.atomikos)8.1. Using an Atomikos Transaction Manager ### [Atomikos](https://www.atomikos.com/) is a popular open source transaction manager which can be embedded into your Spring Boot application. You can use the `spring-boot-starter-jta-atomikos` starter to pull in the appropriate Atomikos libraries. Spring Boot auto-configures Atomikos and ensures that appropriate `depends-on` settings are applied to your Spring beans for correct startup and shutdown ordering. By default, Atomikos transaction logs are written to a `transaction-logs` directory in your application’s home directory (the directory in which your application jar file resides). You can customize the location of this directory by setting a `spring.jta.log-dir` property in your `application.properties` file. Properties starting with `spring.jta.atomikos.properties` can also be used to customize the Atomikos `UserTransactionServiceImp`. See the [`AtomikosProperties` Javadoc](https://docs.spring.io/spring-boot/docs/2.6.4/api/org/springframework/boot/jta/atomikos/AtomikosProperties.html) for complete details. | |To ensure that multiple transaction managers can safely coordinate the same resource managers, each Atomikos instance must be configured with a unique ID.
By default, this ID is the IP address of the machine on which Atomikos is running.
To ensure uniqueness in production, you should configure the `spring.jta.transaction-manager-id` property with a different value for each instance of your application.| |---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| ### [](#io.jta.javaee)8.2. Using a Java EE Managed Transaction Manager ### If you package your Spring Boot application as a `war` or `ear` file and deploy it to a Java EE application server, you can use your application server’s built-in transaction manager. Spring Boot tries to auto-configure a transaction manager by looking at common JNDI locations (`java:comp/UserTransaction`, `java:comp/TransactionManager`, and so on). If you use a transaction service provided by your application server, you generally also want to ensure that all resources are managed by the server and exposed over JNDI. Spring Boot tries to auto-configure JMS by looking for a `ConnectionFactory` at the JNDI path (`java:/JmsXA` or `java:/XAConnectionFactory`), and you can use the [`spring.datasource.jndi-name` property](data.html#data.sql.datasource.jndi) to configure your `DataSource`. ### [](#io.jta.mixing-xa-and-non-xa-connections)8.3. Mixing XA and Non-XA JMS Connections ### When using JTA, the primary JMS `ConnectionFactory` bean is XA-aware and participates in distributed transactions. You can inject into your bean without needing to use any `@Qualifier`: ``` public MyBean(ConnectionFactory connectionFactory) { // ... } ``` In some situations, you might want to process certain JMS messages by using a non-XA `ConnectionFactory`. For example, your JMS processing logic might take longer than the XA timeout. If you want to use a non-XA `ConnectionFactory`, you can the `nonXaJmsConnectionFactory` bean: ``` public MyBean(@Qualifier("nonXaJmsConnectionFactory") ConnectionFactory connectionFactory) { // ... } ``` For consistency, the `jmsConnectionFactory` bean is also provided by using the bean alias `xaJmsConnectionFactory`: ``` public MyBean(@Qualifier("xaJmsConnectionFactory") ConnectionFactory connectionFactory) { // ... } ``` ### [](#io.jta.supporting-alternative-embedded-transaction-manager)8.4. Supporting an Alternative Embedded Transaction Manager ### The [`XAConnectionFactoryWrapper`](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jms/XAConnectionFactoryWrapper.java) and [`XADataSourceWrapper`](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jdbc/XADataSourceWrapper.java) interfaces can be used to support alternative embedded transaction managers. The interfaces are responsible for wrapping `XAConnectionFactory` and `XADataSource` beans and exposing them as regular `ConnectionFactory` and `DataSource` beans, which transparently enroll in the distributed transaction. DataSource and JMS auto-configuration use JTA variants, provided you have a `JtaTransactionManager` bean and appropriate XA wrapper beans registered within your `ApplicationContext`. The [AtomikosXAConnectionFactoryWrapper](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXAConnectionFactoryWrapper.java) and [AtomikosXADataSourceWrapper](https://github.com/spring-projects/spring-boot/tree/v2.6.4/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/jta/atomikos/AtomikosXADataSourceWrapper.java) provide good examples of how to write XA wrappers. [](#io.whats-next)9. What to Read Next ---------- You should now have a good understanding of Spring Boot’s [core features](features.html#features) and the various technologies that Spring Boot provides support for via auto-configuration. The next few sections go into detail about deploying applications to cloud platforms. You can read about [building container images](container-images.html#container-images) in the next section or skip to the [production-ready features](actuator.html#actuator) section.