Ehcache is a tool used in Java to make programs run faster by storing and retrieving data more efficiently. It helps speed up applications by keeping frequently used information close at hand, reducing the need to fetch it repeatedly from the main data source.
Ehcache is an open-source library used in Java for caching Java programs, specifically local and distributed caching in main memory or on the hard disk.
Caching is mainly useful for the following scenarios- The same data is requested again and again (so-called hot spots), which have to be loaded from the database anew with each request. This data can be cached in the main memory of the server application (RAM) or on the client (browser cache). This reduces access times and the number of data transfers since the server does not have to repeatedly request data from the database and send it to the client.
Long-term or resource-intensive operations are often performed with specific parameters. Depending on the parameters, the result of the operation can be stored temporarily so that the server can send the result to the client without executing the operation.
➡️ Simple Configuration: Ehcache can be easily configured using XML or programmatically.
➡️ Memory Management: Efficient use of memory with features like eviction policies and off-heap storage.
➡️ Caching Strategies: Support for various caching strategies, including time-based expiration, LRU (Least Recently Used), and more.
➡️ Concurrency Support: Thread-safe operations and support for concurrent access.
➡️ Listeners: Ability to register listeners to be notified of cache events.
🔹In-Memory Storage: Ehcache primarily operates in memory, which means cached data is stored in the application’s heap memory. This allows for fast read and write access.
🔹Cache Elements: Ehcache manages data in the form of key-value pairs, where the key is used for lookups, and the value is the cached data.
🔹Cache Managers: Cache managers are responsible for creating and managing caches. Multiple caches can coexist within a single cache manager, each with its configuration and characteristics.
🔸Adding Dependencies: To use Ehcache in your Java project, add the Ehcache dependencies to your project’s build file. For example, in Maven:
<dependency> <groupId>org.ehcache</groupId> <artifactId>ehcache</artifactId> <version>3.9.4</version> </dependency>
🔸Configuring Ehcache: Ehcache can be configured using an XML file or programmatically. Here’s a basic XML configuration:
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd"> <cache name="myCache" maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" memoryStoreEvictionPolicy="LRU"/> </ehcache>
To enable caching support in Spring Boot, we need a simple configuration class that must be annotated with
@EnableCaching. Up to this point, we don’t need to do anything more as the following code shows:
@Configuration @EnableCaching public class EhcacheConfig { }
🔸Basic Cache Operations: Using Ehcache for caching involves simple operations, such as putting data into the cache, getting data from the cache, and removing data from the cache. Here’s an example:
@Service public class CalculationService { private final Logger LOG = LoggerFactory.getLogger(CalculationService.class); public double areaOfCircle(int radius) { LOG.info("calculate the area of a circle with a radius of {}", radius); return Math.PI * Math.pow(radius, 2); } } @Cacheable(value = "areaOfCircleCache", key = "#radius", condition = "#radius > 5") public double areaOfCircle(int radius) { LOG.info("calculate the area of a circle with a radius of {}", radius); return Math.PI * Math.pow(radius, 2); }
Related read: 19 Point Checklist: Starting a New Project in Spring Boot
🔹Cache Eviction Strategies: To avoid inflated caches, you should, of course, have configured a meaningful eviction strategy. On the other hand, it is also possible to empty the cache based on requests. The following example shows how to remove all entries from the caches areaOfCircleCache and multiplyCache.
@CacheEvict(cacheNames = {"areaOfCircleCache", "multiplyCache"}, allEntries = true) public void evictCache() { LOG.info("Evict all cache entries..."); }
🔹Cache Listeners: Cache listeners allow you to respond to cache events, such as entries being added, updated, or removed. This can be useful for implementing custom logic when the cache state changes.
In the listener’s tag, we configure a CacheEventListener. The listener reacts to the following events:
The specified CacheLogger class only logs the occurred cache event on the console:
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()); } }
🔹CacheConfig: The @CacheConfig annotation allows us to define certain cache configurations at the class level. This is especially useful if certain cache settings are the same for all methods to be cached:
@Service @CacheConfig(cacheNames = "studentCache") public class StudentService { // ... @Cacheable public Optional<Student> find(Long id) { // ... } @CachePut(key = "#result.id") public Student create(String firstName, String lastName, String courseOfStudies) { // … }
Both the find() and create() methods use the studentCache cache in this example.
🔹CachePut: Methods annotated with @Cacheable are not executed again if a value already exists in the cache for the cache key. If the value does not exist in the cache, then the method is executed and places its value in the cache.
Now there is also the use case that we always want the method to be executed and its result to be placed in the cache. This is done using the @CachePut annotation, which has the same annotation parameters as @Cachable.
A possible scenario for using @CachePut is, for example, creating an entity object, as the following example shows:
@CachePut(cacheNames = "studentCache", key = "#result.id") public Student create(String firstName, String lastName, String courseOfStudies) { LOG.info("Creating student with firstName={}, lastName={} and courseOfStudies={}", firstName, lastName, courseOfStudies); long newId = ID_CREATOR.incrementAndGet(); Student newStudent = new Student(newId, firstName, lastName, courseOfStudies); // persist in database return newStudent; }
The key #result is a placeholder provided by Spring and refers to the return value of the method. The ID of the student is, therefore, the cache key. The cache entry is the return value of the method, the student in our example.
The method now creates a student object and stores it in the studentCache at the end. The next time this object is requested, it can be retrieved directly from the cache.
🔸Proper Configuration: Careful consideration of cache configuration, including size limits, eviction policies, and expiration times, is crucial to ensure optimal performance.
🔸Monitoring and Management: Ehcache provides monitoring and management features that allow you to keep track of cache usage, performance metrics, and potential issues. Utilize these features to ensure the health of your caching system.
🔸Performance Optimization: Optimizing the performance of your cache involves tuning various parameters, such as adjusting cache size, choosing appropriate eviction policies, and minimizing cache contention in a multi-threaded environment.
🔹Spring Caching Annotations: Spring Framework provides annotations like @Cacheable, @CachePut, and @CacheEvict that can be used with Ehcache to simplify caching in Spring applications.
🔹Ehcache with Spring Boot: Integrating Ehcache with Spring Boot is straightforward. Spring Boot provides auto-configuration for Ehcache, making setting up caching in your Spring Boot applications easy.
Related read: Spring Boot With Redis Cache Using Annotation
🔸Memory Leaks: Improperly managed caches can lead to memory leaks. Regularly monitor and analyze your application’s memory usage to identify and address potential issues.
🔸Inconsistent Cache State: In distributed environments, ensuring a consistent cache state across nodes can be challenging. Terracotta integration or other distributed caching solutions can help address this concern.
🔸Performance Bottlenecks: Identifying and addressing performance bottlenecks in your caching system requires a thorough understanding of your application’s usage patterns and careful tuning of cache configurations.
Explore real-world examples of organizations successfully implementing Ehcache to improve application performance, scalability, and reliability.
Stay informed about the latest developments in the Ehcache ecosystem, including new features, updates, and community contributions.
Ehcache is a powerful caching library that can significantly enhance the performance and scalability of Java applications. Understanding its features, architecture, and best practices is essential for effectively integrating caching into your projects.
Whether you are building a small application or a large-scale enterprise system, Ehcache provides the tools and flexibility needed to optimize data access and improve overall user experience.
Check out my GitHub to learn more about Ehcache.
How to Effectively Hire and Manage a Remote Team of Developers.
Download NowThe Mindbowser team's professionalism consistently impressed me. Their commitment to quality shone through in every aspect of the project. They truly went the extra mile, ensuring they understood our needs perfectly and were always willing to invest the time to...
CTO, New Day Therapeutics
I collaborated with Mindbowser for several years on a complex SaaS platform project. They took over a partially completed project and successfully transformed it into a fully functional and robust platform. Throughout the entire process, the quality of their work...
President, E.B. Carlson
Mindbowser and team are professional, talented and very responsive. They got us through a challenging situation with our IOT product successfully. They will be our go to dev team going forward.
Founder, Cascada
Amazing team to work with. Very responsive and very skilled in both front and backend engineering. Looking forward to our next project together.
Co-Founder, Emerge
The team is great to work with. Very professional, on task, and efficient.
Founder, PeriopMD
I can not express enough how pleased we are with the whole team. From the first call and meeting, they took our vision and ran with it. Communication was easy and everyone was flexible to our schedule. I’m excited to...
Founder, Seeke
Mindbowser has truly been foundational in my journey from concept to design and onto that final launch phase.
CEO, KickSnap
We had very close go live timeline and Mindbowser team got us live a month before.
CEO, BuyNow WorldWide
If you want a team of great developers, I recommend them for the next project.
Founder, Teach Reach
Mindbowser built both iOS and Android apps for Mindworks, that have stood the test of time. 5 years later they still function quite beautifully. Their team always met their objectives and I'm very happy with the end result. Thank you!
Founder, Mindworks
Mindbowser has delivered a much better quality product than our previous tech vendors. Our product is stable and passed Well Architected Framework Review from AWS.
CEO, PurpleAnt
I am happy to share that we got USD 10k in cloud credits courtesy of our friends at Mindbowser. Thank you Pravin and Ayush, this means a lot to us.
CTO, Shortlist
Mindbowser is one of the reasons that our app is successful. These guys have been a great team.
Founder & CEO, MangoMirror
Kudos for all your hard work and diligence on the Telehealth platform project. You made it possible.
CEO, ThriveHealth
Mindbowser helped us build an awesome iOS app to bring balance to people’s lives.
CEO, SMILINGMIND
They were a very responsive team! Extremely easy to communicate and work with!
Founder & CEO, TotTech
We’ve had very little-to-no hiccups at all—it’s been a really pleasurable experience.
Co-Founder, TEAM8s
Mindbowser was very helpful with explaining the development process and started quickly on the project.
Executive Director of Product Development, Innovation Lab
The greatest benefit we got from Mindbowser is the expertise. Their team has developed apps in all different industries with all types of social proofs.
Co-Founder, Vesica
Mindbowser is professional, efficient and thorough.
Consultant, XPRIZE
Very committed, they create beautiful apps and are very benevolent. They have brilliant Ideas.
Founder, S.T.A.R.S of Wellness
Mindbowser was great; they listened to us a lot and helped us hone in on the actual idea of the app. They had put together fantastic wireframes for us.
Co-Founder, Flat Earth
Ayush was responsive and paired me with the best team member possible, to complete my complex vision and project. Could not be happier.
Founder, Child Life On Call
The team from Mindbowser stayed on task, asked the right questions, and completed the required tasks in a timely fashion! Strong work team!
CEO, SDOH2Health LLC
Mindbowser was easy to work with and hit the ground running, immediately feeling like part of our team.
CEO, Stealth Startup
Mindbowser was an excellent partner in developing my fitness app. They were patient, attentive, & understood my business needs. The end product exceeded my expectations. Thrilled to share it globally.
Owner, Phalanx
Mindbowser's expertise in tech, process & mobile development made them our choice for our app. The team was dedicated to the process & delivered high-quality features on time. They also gave valuable industry advice. Highly recommend them for app development...
Co-Founder, Fox&Fork