This tutorial covers all basic aspects of using a Cache implementation named Ehcache in Spring Boot. We will start with some basic cache definitions and then we will create a quickstart example.
Firstly, let’s introduce Eh Cache:
Ehcache is a cache library which improves performance by reducing the load on underlying resources. Ehcache is an open source, standards-based (JSR-107) cache that can improve performance, offload your database, and complex operations. It’s the a robust Java-based cache and provides out of the box Spring Caching and Hibernate integration.
That being said, let’s see how to create a Spring Boot application which uses Eh Cache to speed up CPU intensive operations.
Coding a Spring Boot Eh Cache application
Our example application will store in a Cache a Long attribute as key and as value Long attribute that corresponds to the factorial of the key. The larger is the key, the larger is the impact on the CPU to calculate the value. Therefore we will cache it.

Firstly, to enable Caching, the first requirement is to annotate our application with @EnableCaching annotation.
@SpringBootApplication @EnableCaching public class SpringBootEhcacheDemoApplication { public static void main(String[] args) { SpringApplication.run(SpringBootEhcacheDemoApplication.class, args); } }
Next, the Service class, which contains the Cache annotations:
@Service public class CacheService { @Cacheable("numbers") public Long getFactorial(long id) { return calculateFactorial(id); } @CachePut(value = "numbers") public Long update(Long id) { return calculateFactorial(id); } @CacheEvict(value = "numbers", allEntries = true) public void evictData() { System.out.println("Cache evicted"); } public long calculateFactorial(long n) { System.out.println("calculating..."); return LongStream.rangeClosed(1, n).reduce(1, (long x, long y) -> x * y); } }
- Let’s begin from the method getFactorial. This method contains an annotations @Cachable which references the Cache “numbers”. That means, that the method will access the Cache “numbers”. If the id is available as key, it will be returned immediately. Otherwise, the method calculateFactorial will calculate the value and it will be added to the Cache.
- Next, let’s take a look at the update method. It contains the @CachePut annotation. We will use this method to add an element to the Cache. In this case, the calculateFactorial will always be called to calculate the value and it will be added to the Cache.
- Finally, the evictData method which evicts all entries from the Cache with @CacheEvict. You can parameterize it although, for the sake of simplicity, we will clean all Cache data with “allEntries=true”
Next, we will add a REST Control to access our Service:
@RestController @RequiredArgsConstructor @RequestMapping("/numbers") public class CacheController { private final CacheService cacheService; @GetMapping("/get/{id}") public ResponseEntity<Long> get(@PathVariable long id) { Long fact = cacheService.getFactorial(id); return new ResponseEntity<>( fact, HttpStatus.OK ); } @GetMapping("/put/{id}") public ResponseEntity<Long> add(@PathVariable long id) { Long fact = cacheService.update(id); return new ResponseEntity<>( fact, HttpStatus.OK ); } @GetMapping("/evict") public ResponseEntity<String> evict() { cacheService.evictData(); return new ResponseEntity<>( "Cache cleaned", HttpStatus.OK ); } }
The Controller is pretty simple. It is merely a wrapper to the ServiceCache which provides the key, when required to store/update the Cache.
Finally, we will add a CacheEventListener which traces Cache events. We will use it to verify cache hits or misses:
public class CacheLogger implements CacheEventListener<Object, Object> { private final Logger LOG = LoggerFactory.getLogger(CacheLogger.class); @Override public void onEvent(CacheEvent<?, ?> cacheEvent) { LOG.info("Key: {} | EventType: {} | Old value: {} | New value: {}", cacheEvent.getKey(), cacheEvent.getType(), cacheEvent.getOldValue(), cacheEvent.getNewValue()); } }
Adding the Eh Cache configuration
To define the actual Cache settings, we will provide a minimal Eh Cache configuration in a file named resources/ehcache.xml.
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ehcache.org/v3" xmlns:jsr107="http://www.ehcache.org/v3/jsr107" xsi:schemaLocation=" http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd http://www.ehcache.org/v3/jsr107 http://www.ehcache.org/schema/ehcache-107-ext-3.0.xsd"> <cache alias="numbers"> <key-type>java.lang.Long</key-type> <value-type>java.lang.Long</value-type> <expiry> <ttl unit="seconds">30</ttl> </expiry> <listeners> <listener> <class>com.sample.config.CacheLogger</class> <event-firing-mode>ASYNCHRONOUS</event-firing-mode> <event-ordering-mode>UNORDERED</event-ordering-mode> <events-to-fire-on>CREATED</events-to-fire-on> <events-to-fire-on>EXPIRED</events-to-fire-on> </listener> </listeners> <resources> <heap unit="entries">100</heap> <offheap unit="MB">10</offheap> </resources> </cache> </config>
As you can see, this file contains the configuration for the Cache named “numbers”, including:
- The key/value type
- The time-to-live of items in the Cache items. In our configurations, items will expiry in 30 seconds
- The Cache holds up to 100 entries on heap
The Cache holds as well up to 10 MB of off-heap memory before it starts evicting data
The configuration also contains a reference to our CacheLogger which will be fired upon any CREATED or EXPIRY events.
Testing our Spring Boot Cache
To test our application, let’s add the required dependencies to the pom.xml:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-cache</artifactId> </dependency> <dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.7.1</version> </dependency> <dependency> <groupId>javax.cache</groupId> <artifactId>cache-api</artifactId> </dependency>
Now we can run the application:
mvn install spring-boot:run
we will first put an item in the cache:
$ curl http://localhost:8080/numbers/put/9 362880
Let’s check on the Console what happened:
calculating... 2021-10-04 15:28:15.824 INFO 19421 --- [e [_default_]-0] com.sample.config.CacheLogger : Key: 9 | EventType: CREATED | Old value: null | New value: 362880
So, the calculation happened as that key was missing in the Cache.
Now let’s try fetching that key from the Cache:
$ curl http://localhost:8080/numbers/get/9 362880
If you check the logs of Spring Boot Console, you will see that no CacheLogger notifications are there. Nor the “calculating…..” message is there.
We will now evict the data from the Cache:
curl http://localhost:8080/authors/evict
Now if you try accessing again the key ‘9’, it will require again a Calculation.
Much the same way, the item will be evicted from the Cache if you wait for 30 seconds:
2021-10-04 16:53:54.324 INFO 23188 --- [e [_default_]-1] com.sample.config.CacheLogger : Key: 9 | EventType: EXPIRED | Old value: 362880 | New value: null calculating... 2021-10-04 16:53:54.325 INFO 23188 --- [e [_default_]-1] com.sample.config.CacheLogger : Key: 9 | EventType: CREATED | Old value: null | New value: 362880
Using Conditional Caching
Caching annotations can include conditions as well. Consider, for example, we want to store in Cache only calculation which are really expensive. So, factorial numbers with a basis greater than 10.
Here is how to set it in the @CachePut:
@CachePut(value = "numbers", condition="#id>10") public Long update(Long id) { return calculateFactorial(id); }
In the above example, keys which are not larger than 10 will not go in the Cache.
Much the same way, we can make our Cache eviction more granular. For example, we can choose to delete just a single item:
@CacheEvict(value = "numbers", key = "#id") public void delete(long id) { System.out.println("Cache evicted"); }
Conclusion
In this tutorial we have covered the basics of Eh Cache and how to integrate it with a Spring Boot application to store and fetch data from a Cache.
The source code for this tutorial is available here: https://github.com/fmarchioni/masterspringboot/tree/master/cache/spring-boot-ehcache