Using JCache in JEE 6/7

I can’t count the number of times I have come across yet another mostly buggy custom caching solution. Be it a HashMap stuck into a random DAO, a service or an annotation driven solution with interceptors of one flavor or another. I guess this is partially to blame on the long pending JCache specification (JSR-107), which has now been finalized last year some 13 years on from when it was first conceived.

Although JSR-107 missed the deadline for inclusion in the JEE 7 specification, it is still fairly easy to provide the required dependencies with your application to get full JSR-107 support in any JEE 6 or 7 compliant application server.

If you wanted, you could use the JSR-107 reference implementation, however it is strongly advised not to use the reference caching provider implementation since there is neither support nor an active community backing it.

Currently there are four JSR-107 compliant caching provider implementations, ignoring the reference implementation:

Simply including a JSR-107 compliant caching provider is not sufficient to enable annotation based caching.

“In order to use annotations in an application, a library or framework that processes these annotations
and intercepts calls to annotated application objects is required. In an application, the method and
configuration of processing caching annotations on classes is left to the implementation.” – JSR-107 JCache Specification, Chapter 11 Caching Annotations

Either your framework has been extended to process the annotations (as is the case with Spring 4.1 onward), or you will have to provide a framework specific implementation to process the cache annotations, as is the case with CDI for JEE 6 and 7.

The JSR-107 reference implementation provides annotation interceptors for CDI, Guice and Spring (rendered redundant with Spring 4.1).

You will have to include the caching provider (in this case Ehcache) and a set of CDI interceptors processing the caching annotations (provided by the JSR-107 reference implementation).

    <dependencies>
        ...
        <dependency>
            <groupId>org.jsr107.ri</groupId>
            <artifactId>cache-annotations-ri-cdi</artifactId>
            <version>1.0.0</version>
        </dependency>
        <dependency>
            <groupId>org.ehcache</groupId>
            <artifactId>jcache</artifactId>
            <version>1.0.1</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>

Now that all required dependencies are in place, the CDI interceptors have to be enabled by defining them in the beans.xml.

...
    <interceptors>
        <class>org.jsr107.ri.annotations.cdi.CacheResultInterceptor</class>
        <class>org.jsr107.ri.annotations.cdi.CacheRemoveEntryInterceptor</class>
        <class>org.jsr107.ri.annotations.cdi.CacheRemoveAllInterceptor</class>
        <class>org.jsr107.ri.annotations.cdi.CachePutInterceptor</class>
    </interceptors>
...

From here on you can use JCache annotations through out your application in all CDI and EJB beans.

@CacheDefaults(cacheName = "calc")
public class CalculateStuff {
    @CacheResult
    public Integer add(@CacheKey Integer a, @CacheKey Integer b) {
        System.out.println("Calculating: " + a + ", " + b);
        return a + b;
    }

    @CacheRemoveAll
    public void invalidateCache() {
        System.out.println("Cache invalidated");
    }
}
Acknowledgements

I would like to thank Björn Sonntag and Robert Meyer for reviewing my posts.

Leave a Reply

Your email address will not be published. Required fields are marked *