Skip to content
Alex Snaps edited this page Jul 15, 2014 · 5 revisions

Ehcache’s JCache (aka JSR-107) tutorial

javax.cache API tutorial using Ehcache

This goal of this project is to try putting small and concise examples together to help you get started with the javax.caching API. Those examples will try to be as hands on as possible. I’ll begin with remaining implementer agnostic and shall then move on to more advanced use cases, where the javax.cache API as it stands won’t be enough.

Consider this work in progress though…​ I’ll add examples as often as possible. Also, feel free to provide input, comments or even bug reports. I could well get one or two things wrong while doing this!

Getting started with javax.cache API

First, you’ll want to clone this repo and import the source in your IDE. I’ve made this an Apache Maven project, as this remains the most commonly used build system.

The first class you’ll want to look at, a class that’s not 50 lines of code long (and that’s including the imports!) is org.ehcache.demos.jcache.JCacheSimpleExample. This example doesn’t use anything Ehcache specific, it only uses the javax.cache API as specified in JSR-107. The example is broken up in about 4 methods:

  1. static void main(String[]) method, that executes the simple work flow:

  2. JCacheSimpleExample(): The constructor, bootstrapping a javax.cache.CacheManager and creates a javax.cache.Cache

  3. JCacheSimpleExample.simplePutGet(): That creates an object, puts it in the cache and retrieves it back, to print it to the console

  4. JCacheSimpleExample.close(): That closes our CacheManager, disposing of all used resources

Let’s take a closer look at each one of them…​

The main method

There isn’t really much to say about it. Other than it making use of Java 7’s try with resource. While you can make use of it directly on the CacheManager, it’s probably not what you’ll want to do generally. Most of the time you’ll want to keep a reference to you CacheManager instance, e.g. initialize it in your Servlet.init(ServletConfig), keep around and only close it on Servlet.destroy() when your web application is shutdown. In our example, we use the constructor to initialize the CacheManager and the JCacheSimpleExample.close() method being our equivalent of destroying our web app.

The constructor

cacheManager = Caching.getCachingProvider()  // (1)
    .getCacheManager();                      // (2)

testCache = cacheManager.createCache("test", // (3)
    new MutableConfiguration<String, Person>().setTypes(String.class, Person.class) // (4)
        .setStoreByValue(false)              // (5)
);
  1. javax.cache.Caching.getCachingProvider(), a static method, resolves the javax.cache provider present on the application’s classpath. Here, it’ll use Ehcache’s JCacheCachingProvider.

Note
See the Caching API for more information on resolving the provider.
  1. From that CachingProvider we get the default CacheManager. As we’ve never asked for it, Ehcache will create the equivalent of it’s singleton CacheManager. We didn’t config anything about Ehcache at all, so it falls back to the default ehcache.xml embedded in its jar that was pulled in through maven.

  2. We then use that CacheManager to create a Cache. We’re naming it "test". We would be able to retrieve this cache by its name using CacheManager.getCache(String, Class, Class). But in this example, we’re keeping a reference to the cache that’s being created, as it’s directly returned by the CacheManager.createCache method.

  3. The Cache is created to be type safe, accepting String as keys and our example class Person as values.

  4. Finally, we want this cache to store values by reference (like a Map would). The default is to store by value, but since we only want to use the java heap to store cached values, we don’t want to pay the overhead of copying values.

A simple put & get

final Person me = new Person("Alex", "Snaps", "Terracotta");
testCache.put("me", me);                                     // (1)
final Person cachedMe = testCache.get("me");                 // (2)
System.out.println(cachedMe == me);
System.out.println(cachedMe);
  1. Using Cache<K,V>(K, V), we’re adding an entry to our cache. The key is "me", while the value is the Person object we just created. In this case, given Person instances are immutable, we can safely share them across threads in our application. So there is definitively no reason to store by value (i.e. have a copy on read and write cache).

  2. We then retrieve the cached Person under the same "me" key.

Given our cache is storing by reference, the first println will return true. As the value added is the same instance as the one returned. Should we have had the storeByValue = true, it would have printed false. Ehcache’s javax.cache wrapper would require you to have a Serializable value in order to copy it. You could actually do with out having your value types implement Serializable, but it would require using Ehcache specific APIs, so we won’t cover this here for now.

Releasing all resources

cacheManager.close();

Not much to say here…​ Once done, we close the CacheManager, which in turn closes all Cache instances it managers. The point is to have all resources used being released and to not leak resources (e.g. memory, threads, …​). The most simple example, which applies in our use case here, is to empty our "test" cache, i.e. release our Person instance, so the we don’t hold any reference to it anymore and it can be garbage collected.