Spring Cache Custom Key Generator Rating: 9,6/10 8729 votes

In the last example we saw how to use a custom KeyGenerator by using CacheConfig#keyGenerator. In this example, we will see how to register our custom KeyGenerator globally by implementing CachingConfigurer interface or by extending its adapter class CachingConfigurerSupport.

Spring Caching API provides options to create a custom key generator for handling all such use cases. To give a different default key generator, we need to implement the org.springframework.cache.interceptor.KeyGenerator interface.KeyGenerator needs to. Nov 04, 2014  Caching with Spring: Advanced Topics and Best Practices. And @CachePut annotations to be used on the same method @CacheConfig Class-level annotation that allows to share the cache names, the custom KeyGenerator, the custom CacheManager and finally the custom CacheResolver. Does not enable caching. Default Key Generation Strategy. Custom Key Generators. But what if you actually want to use the same cache for multiple methods without conflicts? The solution is to define and use a custom cache key generator. In the following example both methods use the same cache (“examplecache”), but also use a custom cache key generator (MethodSpecificKeyGenerator). Spring Cache Custom KeyGenerator #java #springframework #rest #springboot #mvc #springmvc. Use the key property or a custom key generator to have more fine-grained control over your cache keys. Cacheable Annotations and Synchronization For very expensive methods, you want to optimize.

Example

Java Config

CachingConfigurer interface is to be implemented by @Configuration classes annotated with @EnableCaching. It provides various methods to configure or customize caching abstraction.

We are also overriding cacheManager() method to register our cache provider.

The Custom KeyGenerator

A service bean

As compare to the last example, we don't need to use @CacheConfig#keyGenerator or @Cacheable#keyGenerator anymore.

The main class

Example Project

Dependencies and Technologies Used:

  • spring-context 5.0.4.RELEASE: Spring Context.
  • JDK 1.8
  • Maven 3.3.9

We have earlier written few interesting articles on caching in spring and another good article on @Cacheable and @CacheEvict annotations for caching in spring. This is another comprehensive tutorial for spring caching using Spring 4. Spring caching is available since 3.1, but spring 4.1 has added lot of cool features with the existing spring caching framework. Another interesting part of this spring caching tutorial is that I am going to use Spring Boot for packaging and running this spring caching example.

Note that spring provides only the caching abstraction, the actual caching store is not implemented by spring caching framework. We have to configure some of the external caching storage.

Spring Cache Tutorial Table of Contents

Here is the list of topics covered in this tutorial about spring cache.

  1. What is Spring Cache?
  2. Cache Implementations
  3. Spring Cache Annotations
    1. @Cacheable
    2. @CachePut
    3. @CacheEvict
    4. @Caching
    5. @CacheConfig
  4. How to Enable Spring Cache?
  5. JCache (JSR – 107) Support
  6. EhCache Configuration
  7. Cache Fallback Mechanism
  8. Spring Boot Application
  9. Spring Cache Example Application
  10. Exceptions

What is Spring Cache?

  1. Spring’s core framework provides APIs for supporting caching in the existing spring applications.
  2. This support is available from Spring Framework 3.1 and there is significant improvement provided in the Spring 4.1.
  3. This is an abstract framework where Spring only provides the layer where other third party caching implementations can be easily plugged for storing data.
  4. In short, cache storage is not implemented by Spring, where as enabling and caching is supported by spring out of the box.
  5. Caching is supported for the methods and it works good if the methods return the same result for the given input for the multiple invocations.

Cache Implementations

As I have mentioned earlier, the actual implementations of the cache is by third party library and Spring provides only the abstract layer for enabling that specific cache implementation to store the cache data. Spring’s has the abstraction for the following list of cache implementations out of the box:

  1. JDK java.util.concurrent.ConcurrentMap based caches
  2. EhCache
  3. Guava Caches
  4. JSR 107 complaint caches

At the end of this tutorial, I will explain first two caches in the above list. For the ConcurrentMap we just need the Cache manager to be configured and the data stored in the in-memory, for the EhCache we have to add the ehcache.xml file in the classpath.

Spring Cache Annotations

The following are the list of spring caching annotations. These are specific to the spring framework, apart from that there are few more annotations that are implemented as part of the JCache (JSR – 107). I will explain that in the later part of this tutorial.

  1. @Cacheable
  2. @CacheEvict
  3. @CachePut
  4. @Caching
  5. @CacheConfig

@Cacheable

@Cacheable annotation is one of the most important and common annotation for caching the requests. If you annotate a method with @Cacheable, if multiple requests are received by the application, then this annotation will not execute the method multiple times, instead it will send the result from the cached storage.

Here is an example:

The following are the list of properties that can be used inside @Cacheable annotation to customize the caching functionality.

AttributesDescription
cacheManagerThe bean name of the cache manager
cacheNames

The list of cache store names where the method

cache has to be stored. This should be any array of strings.

cacheResolverThe name of the custom cache resolver
condition

This is Spring Expression Language (SPeL) for the conditional caching

for the method

keySpring Expression Language for computing the key dynamically
keyGeneratorThe bean name of the custom key generator to use
unlessSpring Expression Language for bypassing caching for specific scenarios.
valueIt is a cache name to store the caches

@CachePut

@CachePut annotation helps for updating the cache with the latest execution without stopping the method execution. The only difference between @Cacheable and @CachePut is that first one is only once executed for the combination of similar key and updated the cache storage and later is executed every time and updates the cache storage.

It is not recommended to use both the annotation for the same method which will result in an unexpected results. It is highly recommended to use either @Cacheable or @CachePut for a method.

The list of attributes defined in this annotation is similar to the @Cacheable.

@CacheEvict

@CacheEvict annotation is used for removing a single cache or clearing the entire cache from the cache storage. This annotation supports suitable parameters to execute the condition to clear the matching set of cached from the store. If you set the allEntries=true , then the entire cache will be cleared.

Spring Cache Custom Key Generator For Sale

The list of attributes supported in this annotation is shown below:

AttributesDescription
allEntriesIt indicated whether all the data in the cache has to be removed
beforeInvocationThis attribute indicates whether the eviction has to be done before the method invocation.
cacheManagerThe bean name of the cache manager
cacheNames

The list of cache store names where the method

cache has to be stored. This should be any array of strings.

cacheResolverThe name of the custom cache resolver
condition

This is Spring Expression Language (SPeL) for the conditional caching

for the method

keySpring Expression Language for computing the key dynamically
keyGeneratorThe bean name of the custom key generator to use
unlessSpring Expression Language for bypassing caching for specific scenarios.
valueIt is a cache name to store the caches

@Caching

@Caching annotation used for grouping multiple annotations of the same type together when one annotation is not sufficient for the specifying the suitable condition. For example, you can put mutiple @CacheEvict ot @CachePut annotation inside @Caching to narrow down your conditions as you need.

The list of attributes supported in this annotation is shown below:

AttributesDescription
cacheableThis is array of @Cacheable annotation
evictThis is array of @CacheEvict annotation
putThis is array of @CachePut annotation

@CacheConfig

If you have multiple operations in a class where each operation has to be given cache configuration details, this could be tedious job if the number of operations are higher. You can annotate @CacheConfig at the class level to avoid repeated mentioning in each method. For example, in the class level you can provide the cache name and in the method you just annotate with @Cacheable annotation.

The list of attributes supported in this annotation is shown below:

AttributesDescription
cacheManagerThe bean name of the cache manager
cacheNames

The list of cache store names where the method

cache has to be stored. This should be any array of strings.

cacheResolverThe name of the custom cache resolver
keyGeneratorThe bean name of the custom key generator to use

Enable Spring Caching

If you are enabling enabling caching in your spring applications, then you have to take care of the following two things:

  1. Caching declaration – Identify the methods that has to be cached and define the caching policy.
  2. Cache Configurations – Configure the cache manager where the backing data is stored and retrieved for the quick response.
  3. EnableCaching – Finally you have to enable the caching using Java configurations or the XML configurations.

Caching in spring is not enabled by default. We have to enable the caching by annotating a configuration class with @EnableCaching or declaring it in the XML file. Here is the example snippet for enabling the caching.

If you are using XML configurations, then it looks like this:

The advantage of having the control to enable or disable is that we are not required to update the configurations in every single file. We just have to remove the configuration in single place, rest all will work fine.

JCache (JSR – 107) Support

Since spring framework 4.1, spring’s caching abstraction completely supports the JCache specification and you can use JCache annotations without any special configurations. Here is the table that compares the list of annotations in Spring and JCache specification.

SpringJCache (JSR-107)Remarks
@Cacheable@CacheResult
@CachePut@CachePut There is no change in the annotation name
@CacheEvict@CacheRemove @CacheRemove evicts conditionaly when

there is exception throw from the method.

@CacheEvict(allEntries=true)@CacheRemoveAll JCache adds another annotation for

removing all the cache entries

@CacheConfig@CacheDefaults Both the annotations work similar

The JCache is located under the package org.springframework.cache.jcache. You can declare the JCache as like this:

If you are using Java based configuration, please add the below lines of code to your configuration class:

EhCache Configuration

Ehcache is one of the most popular caching implementation available as the open source caching implementation. This is located under the ackage org.springframework.cache.ehcache. You have to declare appropriate cache manager to start using it in your application.

The cache manager configuration for ehcache is:

If you want to configure using the Java configuration class, add the following lines of code:

Note that you should have ehcache.xml in the classpath or any other location where your spring application can load without any issues. This configuration provides more details about the cache size, file name, etc.

Here is the example of the ehcache.xml file:

You can read more about configuring the ehcahce here.

Cache Fallback Mechanism

There are situations when we change to different environments or any other scenarios our applications may not have caching store configured. In this case a runtime exception will be thrown by the spring application due to failure on finding the suitable cache store. Instead of removing the caching declarations in the application (which is teadious and time consuming work), we can configure a fall bacl dummy cache store to avoid and exception thrown. What happens is, when there is no cache store found by the spring application, it just executes the method normally without enforcing any caching mechanism. The declaration for fall back cache would look like this:

Spring Boot Application

We are going to run this application using Spring Boot command liner. This is very easy and simple way to quickly run our examples. I am using Spring Boot 1.2.5 for running this example. Here is the pom.xml required to download the dependencies:

Application.java

Spring Boot Auto Configuration Support

Update: After the release of Spring Boot 1.3.0

When I am writing this article, Spring Boot 1.2.5 doesn’t support the auto-configuration for caching technologies. We have to manually add the required dependencies to the pom.xml file. Since the Spring Boot 1.3.0 release, new starter pom spring-boot-starter-cache has been added to support the auto-configuration of caching technologies available in the classpath.

If you are using the spring boot 1.3.0 or later versions, you have to follow these steps to enable the caching configurations:

  • Just add the spring-boot-starter-cache and caching implementation JAR file to the pom.xml file
  • Annotate with @EnableCaching in the @Configuration file
  • It is not required to add the caching manager beans in the @Configuration file. Spring boot will add the required beans based on the caching technology available in the classpath.

The following are list of caching technologies supported as of now. If you are using any one of these technologies, then spring boot can perform the auto-configuration for you:

  • Hazelcast
  • Infinispan
  • Any JCache (JSR 107) implementation
  • Guava
  • Simple Map based in-memory cache also supported in the auto configuration

Spring Boot Cache Key

Spring Cache Example Application

This tutorial uses a simple example to illustrate the functionality of the caching in spring framework. And also it uses the ConcurrentMapCacheManager as the cache manager. This is a simple cache manager available with the Java release.

This example adds the EhCache, Guava, ConcurrentMapCacheManager and JCache managers in the Java configuration class. These configurations are added as part of the Spring Boot’s startup class with @Configuration annotation.

Spring Cache Key Generator

This example is to get the user details by running the sleep mode in the method where @Cacheable annotation is used. When you run the example, you can clearly note the difference for the first time and the subsequent invocations.

Spring Cache Custom Key Generator Example

Following are the list of files that are part of this example application:

  • Application.java
  • UserDetails.java
  • UserRepository.java
  • UserRepositoryImpl.java
  • ehcache.xml
  • pom.xml

You can download the spring caching example application.

Exceptions

This section shows some of the common error or exceptions that are encountered while developing this application. If you see any other issues, please write it in the comments section.

CacheManager Registration Problem:The below exception will be thrown when you have enabled caching functionality and not configured any of the cache manager. You should have atleast one cache manager to store the incoming catches.

Cache Manager Name Problem: When you are not specifying the cache name in the cache manager and you are trying to use it in the @Cacheable annotation. For example look at the following entry:

In the above code, it tries to search for the cache manager with the name of “users”, if it is not finding then it will throw the below exception.

Customs Cache Locations

Primary or Declare a Specific CacheManager Exception

In the above code, we have declaraed JDK cache and EhCache for our applications. But, if the application could not find any of these stores, then we have configured fallbackToNoOpCache to execute methods without any exceptions thrown at runtime.

When you are declaring more than one cache managers in your application, your application may not be able to resolve which cache manager has to be used for the annotation not using the cacheManager attribute to specify the cache manager name. In that case, you would encounter the following exception.

The above problem can be resolved by making one of the cache manager as the primary by annotating as @Primary as below:

Related posts: