EhCache: Embedded Caching Solution
Caching is one of the most effective ways to improve application performance and reduce load on databases and external services. Among the many options available to Java developers, EhCache stands out as a mature, lightweight, and easy-to-integrate embedded caching library.
In this post, we'll explore what EhCache is, why you might use it, and how to get started with practical examples.
What Is EhCache?
EhCache is an open-source, standards-based caching library written in Java. It runs in-process (embedded within your application's JVM), which means there's no separate server to deploy or maintain. This makes it an excellent choice for single-node applications, or as a first-level cache in distributed systems.
Key features include:
- In-memory (heap and off-heap) caching
- Disk persistence for durability across restarts
- JSR-107 (JCache) compliance for standardized APIs
- Tiered storage to balance speed and capacity
- Configurable eviction and expiry policies
Why Use EhCache?
Consider a service that repeatedly fetches the same reference data from a database. Every request incurs network latency and database load. By caching results:
- Latency drops since data is served from memory
- Database pressure decreases, improving overall scalability
- Throughput increases without adding infrastructure
Because EhCache is embedded, it avoids the network hop associated with distributed caches like Redis or Memcached, making it exceptionally fast for local reads.
Adding EhCache to Your Project
For a Maven project, add the following dependencies. We'll use EhCache 3.x, which implements the JCache standard.
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.10.8</version>
</dependency>
<dependency>
<groupId>javax.cache</groupId>
<artifactId>cache-api</artifactId>
<version>1.1.1</version>
</dependency>
Programmatic Configuration
EhCache 3 offers a fluent builder API for defining caches in code. Here's a simple example that caches Long keys to String values.
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.builders.*;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
public class CacheExample {
public static void main(String[] args) {
CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
.withCache("productCache",
CacheConfigurationBuilder.newCacheConfigurationBuilder(
Long.class, String.class,
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(1000, EntryUnit.ENTRIES)
.offheap(10, MemoryUnit.MB))
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(
java.time.Duration.ofMinutes(5))))
.build(true);
Cache<Long, String> cache = cacheManager.getCache(
"productCache", Long.class, String.class);
cache.put(1L, "Wireless Mouse");
String value = cache.get(1L);
System.out.println("Cached value: " + value);
cacheManager.close();
}
}
Understanding Tiered Storage
The example above defines two tiers:
-
Heap tier (
1000 entries) — fastest, stored as Java objects on the JVM heap. -
Off-heap tier (
10 MB) — stored in serialized form outside the heap, reducing garbage collection pressure.
EhCache automatically moves hotter data into faster tiers. You can add a disk tier for persistence:
ResourcePoolsBuilder.newResourcePoolsBuilder()
.heap(1000, EntryUnit.ENTRIES)
.offheap(10, MemoryUnit.MB)
.disk(100, MemoryUnit.MB, true) // true = persistent
XML Configuration
Many teams prefer declarative configuration. Create an ehcache.xml file:
<config xmlns='http://www.ehcache.org/v3'>
<cache alias="productCache">
<key-type>java.lang.Long</key-type>
<value-type>java.lang.String</value-type>
<expiry>
<ttl unit="minutes">5</ttl>
</expiry>
<resources>
<heap unit="entries">1000</heap>
<offheap unit="MB">10</offheap>
</resources>
</cache>
</config>
Load it at runtime:
URL myUrl = getClass().getResource("/ehcache.xml");
XmlConfiguration xmlConfig = new XmlConfiguration(myUrl);
CacheManager cacheManager = CacheManagerBuilder
.newCacheManager(xmlConfig);
cacheManager.init();
Using the JCache (JSR-107) API
If you want to keep your code portable across caching providers, use the standard JCache API with EhCache as the backing provider.
java
import javax.cache.*;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.spi.CachingProvider;
CachingProvider provider = Caching.getCachingProvider();
CacheManager manager = provider.getCacheManager();
MutableConfiguration<Long, String> config =
new MutableConfiguration<Long, String>()
.setTypes(Long.class, String.class)
.setSt
Top comments (0)