13. July 2017
5 min

Three approaches to using JCache (without JavaEE 8)

JSR-107 (aka JCache) specifies API and semantics for temporary, in-memory caching of Java objects in order to standardize most common caching use cases. This JSR took a long time to complete and was not able to be part of JavaEE 7. It is nevertheless a candidate for JavaEE 8, which should be released sometime in the (late) second half of 2017. However, with a little bit of effort, it is already possible to use JCache in Java applications so that when you are able to update to JavaEE 8, your code will already be working according to the standard and you will only need to get rid of dependencies rather than change your cache managing code. In this post I will show you three different ways how to accomplish that.

The example application

I created an example application, which simulates getting the balance of a guest in a hotel. The main service calls other services for different billing areas of the hotel (e.g. spa, pool, room service, etc.) and aggregates the amounts to come up with a total balance for a given guest.

The service is made available on the following REST API:

The application is only a simulation of calling slow services synchronously. That is why each service always returns a fixed amount after waiting a number of milliseconds. This way we can very easily tell by the response times when we are getting a result taken from the cache.

You can look at and download the complete code on github: https://github.com/paolizq/jcache-examples

JCache usage with annotations

JCache defines a set of annotations in order to work with a cache.

@CacheDefaults annotates a class and applies the given configuration to all class methods.

@CacheKey  annotates a parameter to define it as the key through which an object can be found in the cache.

@CacheValue  annotates a parameter to define it as the value to save to a cache.

@CacheResult  annotates a method and saves its result to the cache.

@CachePut  annotates a method and saves the parameters passed to the cache.

@CacheRemove  annotates a method and removes the value identified by the given key from the cache

@CacheRemoveAll  annotates a method and removes all the objects of the cache specified in this or in the class annotation.

Now let’s take a look at how we can get these annotations to work.

Approach 1: Taking matters into your own hands

If you want to add support for JCache to an application that runs on a JavaEE compliant application server, you currently do not have any shortcuts and need to do everything on your own. Start off by adding the java cache API and the reference implementation of the cache annotations to your project as dependencies.

Then on your beans.xml  file register the interceptors of the reference implementation.

Now you only have to annotate the relevant classes in the application.

You can see this in action on the jcache-ri project. First build the war file with:

Then deploy the application to a JavaEE compliant server and call the API, for example:

The result will take a little bit to be displayed and if you look at the logs of your server you should see a line similar to this:

If you call the API a second time with the same guest ID, you should get the result a lot faster and nothing will be written to the log.

Approach 2: Getting everything handed to you on a silver platter

The Payara application server is derived from glassfish with many enhancements on top, including a JCache implementation and Hazelcast out of the box, which means the configuration efforts are minimal. The jcache-payara project does not only create a .war file like the first example, but it packages it together with payara micro to create an uber-jar. This way we do not need to start an application server and deploy the application on top of it. We simply run the resulting jar with java -jar .

To create the microservice we need the following dependencies:

Since the dependencies are only needed to compile the code, the war file that is generated will be smaller compared to the one generated in approach one.

To generate the uber-jar for the example application in jcache-payara, you just need to run the following:

Now you can run the application.

And call the API:

The application will behave identically to the one in the previous approach.

Approach 3: The spring boot way

Even though spring has its own cache abstraction and therefore its own caching annotations, they also offer JCache support, thus enabling the use of standard annotations. All you need to do is add the JCache dependency to your spring boot project…

… and annotate your Application class with @EnableCaching .

To build the jar for the jcache-spring application run

And to run the application

Now you can call the API


I just showed you three approaches in which you can use the JCache API without having to wait for JavaEE 8. The decision on which approach to use depends very much on the application on which it will be used. If you want to use JCache on a new application, then you might be able to choose one of the easier options shown instead of taking the long approach. However if your application already exists it might be very costly to make a big change to it solely because of JCache, so you probably will have to choose the approach that is the most similar to your current technology stack.

Comment article