[[spring_integration]]
=== Using {brandname} with Spring
{brandname} integrates with the Spring Framework to make it easy to add caching capabilities to your applications.

[NOTE]
====
{brandname} supports Spring 4 and Spring 5 with different sets of dependencies.
====

[[spring_boot_starter]]
//Infinispan only: Refer to GitHub.
ifndef::productized[]
==== Spring Boot Starter
Check out the {brandname} link:https://github.com/infinispan/infinispan-spring-boot[Spring Boot Starter on GitHub] to quickly get up and running.
endif::productized[]

[[spring_cache_provider]]
==== Setting Up {brandname} as a Spring Cache Provider
{brandname} implements the Spring SPI to offer high-performance, in-memory caching capabilities.

[[spring_add_support]]
===== Adding Spring Cache Support
The link:http://spring.io/[Spring Framework] offers a link:https://docs.spring.io/spring/docs/5.1.3.RELEASE/spring-framework-reference/integration.html#cache[cache abstraction] with two simple annotations:

* `@Cacheable` adds entries to the cache.
* `@CacheEvict` removes entries from the cache.

To add caching support to your application, do the following:

. Enable cache annotations in your application context either declaratively or programmatically.
+
* *Declaratively:* Add `<cache:annotation-driven/>` to your application context.
+
include::topics/configuration/spring_annotation_driven.adoc[]
+
* *Programmatically:* Enable cache support as follows:
+
[source,java,options=nowrap]
----
@EnableCaching @Configuration
public class Config {
}
----
+
. Add {brandname} and the Spring integration module to your `pom.xml`.
+
Spring 4::
* Embedded mode: `infinispan-spring4-embedded`
* Remote client-server mode: `infinispan-spring4-remote`
Spring 5::
* Embedded mode: `infinispan-spring5-embedded`
* Remote client-server mode: `infinispan-spring5-remote`
+
The following is an example with Spring 5 in embedded mode:
+
include::topics/dependencies/spring_integration.adoc[]

[[spring_configure_cache_provider]]
===== Configuring {brandname} as the Spring Cache Provider
The Spring cache provider SPI has two interfaces through which it interacts with {brandname}: `org.springframework.cache.CacheManager` and `org.springframework.cache.Cache`. The `CacheManager` interface acts as a factory for named `Cache` instances.

At runtime Spring looks for a `CacheManager` implementation that has a bean named `cacheManager` in the application context.

You can configure your application context either declaratively or programmatically.

* *Declaratively:*
+
[source,xml,options=nowrap]
----
<!-- Infinispan cache manager -->
<bean id="cacheManager"
          class="org.infinispan.spring.embedded.provider.SpringEmbeddedCacheManagerFactoryBean"
          p:configurationFileLocation="classpath:/org/infinispan/spring/embedded/provider/sample/books-infinispan-config.xml" />
----
* *Programmatically:*
+
[source,xml,options=nowrap]
----
@EnableCaching
@Configuration
public class Config {

   @Bean
   public CacheManager cacheManager() {
      return new SpringEmbeddedCacheManager(infinispanCacheManager());
   }

   private EmbeddedCacheManager infinispanCacheManager() {
      return new DefaultCacheManager();
   }

}
----

[[spring_add_caching]]
==== Adding Caching to Your Application
Add the `@Cacheable` and `@CacheEvict` annotations to your application code.

[[spring_add_entries]]
===== Adding Cache Entries
The `@Cacheable` annotation adds returned values to a defined cache.

For instance, you have a data access object (DAO) for books. You want book instances to be cached after they have been loaded from the underlying database using `BookDao#findBook(Integer bookId)`.

Annotate the `findBook(Integer bookId)` method with `@Cacheable` as follows:

[source,java,options=nowrap]
----
@Transactional
@Cacheable(value = "books", key = "#bookId")
public Book findBook(Integer bookId) {...}
----

Any `Book` instances returned from `findBook(Integer bookId)` are stored in a cache named `books`, using `bookId` as the key.

Note that "#bookId" is an expression in the link:http://static.springsource.org/spring/docs/current/spring-framework-reference/html/expressions.html[Spring Expression Language] that evaluates the `bookId` argument.

[IMPORTANT]
====
If your application needs to reference entries in the cache directly, you should include the `key` attribute. Without this attribute, Spring generates a hash from the supplied method arguments to use as the cache key.
====

[[spring_remove_entries]]
===== Deleting Cache Entries
The `@CacheEvict` annotation deletes entries from a defined cache.

Annotate the `deleteBook(Integer bookId)` method with `@CacheEvict` as follows:

[source,java,options=nowrap]
----
// Evict all entries in the "books" cache
@Transactional
@CacheEvict (value="books", key = "#bookId", allEntries = true)
public void deleteBookAllEntries() {...}

// Evict entries in the "books" cache that match #bookId
@Transactional
@CacheEvict (value="books", key = "#bookId")
public void deleteBook(Integer bookId) {...]}
----

[[spring_configure_timeouts]]
==== Configuring Timeouts for Cache Operations

The {brandname} Spring cache provider defaults to blocking behaviour when performing read and write operations. By default operations are synchronous and do not time out. However, you might want to set a maximum time to wait for operations before timing out in some situations. For example, timeouts are useful if you need to ensure that an operation completes within a certain time and you can ignore the cached value.

`infinispan.spring.operation.read.timeout`::
Specifies the time, in milliseconds, to wait for read operations to complete. The default is `0` which means unlimited wait time.
`infinispan.spring.operation.write.timeout`::
Specifies the time, in milliseconds, to wait for write operations to complete. The default is `0` which means unlimited wait time.

To configure timeouts for cache operations, set the properties in the context XML for your application on either `SpringEmbeddedCacheManagerFactoryBean` or `SpringRemoteCacheManagerFactoryBean`.

[TIP]
====
In remote client-server mode, you can also add these properties to `hotrod-client.properties`.
====

The following example shows the timeout properties in the context XML for `SpringRemoteCacheManagerFactoryBean`:

[source,xml,options=nowrap]
----
<bean id="springRemoteCacheManagerConfiguredUsingConfigurationProperties"
      class="org.infinispan.spring.remote.provider.SpringRemoteCacheManagerFactoryBean">
    <property name="configurationProperties">
        <props>
           <prop key="infinispan.spring.operation.read.timeout">500</prop>
           <prop key="infinispan.spring.operation.write.timeout">700</prop>
        </props>
    </property>
</bean>
----

[[spring_externalize_sessions]]
==== Externalizing Sessions Using Spring Session

link:http://docs.spring.io/spring-session/docs/current/reference/html5[Spring Session] lets you externalize user session information into {brandname}.

To configure Spring Session integration in your application, do the following:

Add dependencies to your `pom.xml` as follows:

Spring 4::
* Embedded mode: `infinispan-spring4-embedded`
* Remote client-server mode: `infinispan-spring4-remote`
* Spring Framework: `spring-session`
+
The following is an example with Spring 4 in embedded mode:
+
include::topics/dependencies/spring4_session_dependencies.adoc[]
+
Spring 5::
* Embedded mode: `infinispan-spring5-embedded`
* Remote client-server mode: `infinispan-spring5-remote`
* Spring Framework: `spring-session-core`
+
The following is an example with Spring 5 in remote client-server mode:
+
include::topics/dependencies/spring5_session_dependencies.adoc[]

After you add dependencies, do the following:

. Specify the appropriate FactoryBean to expose a `CacheManager` instance.
+
* Embedded mode: `SpringEmbeddedCacheManagerFactoryBean`
* Remote client-server mode: `SpringRemoteCacheManagerFactoryBean`
+
. Enable Spring Session with the appropriate annotation.
+
* Embedded mode: `@EnableInfinispanEmbeddedHttpSession`
* Remote client-server mode: `@EnableInfinispanRemoteHttpSession`
+
These annotations have optional parameters:
+
- `maxInactiveIntervalInSeconds` sets session expiration time in seconds. The default is `1800`.
- `cacheName` specifies the name of the cache that stores sessions. The default is `sessions`.

The following example shows a complete, annotation-based configuration:

[source,java,options=nowrap]
----
@EnableInfinispanEmbeddedHttpSession
@Configuration
public class Config {

   @Bean
   public SpringEmbeddedCacheManagerFactoryBean springCacheManager() {
      return new SpringEmbeddedCacheManagerFactoryBean();
   }

   //An optional configuration bean responsible for replacing the default
   //cookie that obtains configuration.
   //For more information refer to the Spring Session documentation.
   @Bean
   public HttpSessionStrategy httpSessionStrategy() {
      return new HeaderHttpSessionStrategy();
   }
}
----
