JCache: first overview


JCache is out since some months and we already have some implementations popping out (Hazelcast implemented the main part, Infinispan passes all TCKs, commons-jcs passes standalone TCKs – CDI implementation in progress, Spring just integrated it etc…).

This article is just here to present the basic API but some more will come with the features which can make it interesting compared to more simple APIs (like a Map).

JCache API follows more or less two designs. The instantiation one is the standard one for “JavaEE” and the Cache one is really based on Hazelcast (even if some other implementations are close, concepts are mainly 1-1 with Hazelcast).

Since you can get several implementations you need a provider. That’s why the first step is to get a CachingProvider:

final CachingProvider provider = Caching.getCachingProvider();

Of course there is a system property to force the provider (javax.cache.spi.CachingProvider) otherwise a standard ServiceLoader is used.

Then you need a CacheManager which will allow you to access caches:

final CacheManager manager = provider.getCacheManager(/* uri, classloader, properties */);

First thing interesting here is you have defaults for all parameters but some can be important:

  • uri: implementation specific configuration file (ehcache.xml for instance or hazelcast.xml)
  • classloader: surely the most important parameter: the classloader the cache is related to. Impacting is the cache is storedByValue (not by reference even lcoally) or distributed.
  • properties: implementation specific config

So the advice here is to ensure you initialize at least the classloader. There is a getDefaultURI() method in the cache provider and a getDefaultProperties() one. So the instantiation can look like:

final CacheManager manager = provider.getCacheManager(provider.getDefaultURI(), Thread.currentThread().getContextClassLoader(), provider.getDefaultProperties())

Of course if you bind it to a ServletContainerListener or something else you can get the classloader from another API (ServletContext for instance).

Now we have a manager we can create a cache (this is important to do so before getting it). The createCache() method of the manager takes the cacheName and its configuration as parameters. In the next sample I simply use a simple configuration but in next posts you’ll see it can be really more interesting. Just take care by default the cache uses storeByValue configuration which means key/values are copied which can degrade a bit the performances when using the cache locally.

final Cache<String, String> cache =  manager.createCache(
						cacheName,
						new MutableConfiguration<String, String>()
								.setStoreByValue(false)
								.setStatisticsEnabled(true)
								.setManagementEnabled(true)
								.setTypes(String.class, String.class));

If you are sure the cache is initialized and you just want to get it you can call getCache:

 style='color:#200080; font-weight:bold; '>final Cache<String, String> cache = manager.getCache(cacheName, String.class, String.class)

Note: I used typed APIs (String, String) but a not typed one exist.

Then simply use the cache as expected:

cache.put("foo", "bar");
final String value = cache.get("foo");

Note: there a are a lot of other interesting methods in Cache API.

Finally don’t forget to cleanup everything:

cache.close();
manager.close();
provider.close();

Here a sample Main to test it (tested with commons-jcs):

package org.superbiz.jcache;

import javax.cache.Cache;
import javax.cache.CacheManager;
import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration;
import javax.cache.spi.CachingProvider;

public class Demo {
	public static void main(final String[] args) {
		// there are shortcuts in Caching to get cache but best to handle it properly this way using
		// app lifecycle. Here just using try-with-resources to simulate it but means close() is important
		try (final CachingProvider provider = Caching.getCachingProvider()) {
			try (final CacheManager manager = provider.getCacheManager(provider.getDefaultURI(), Thread.currentThread().getContextClassLoader(), provider.getDefaultProperties())) {
				final String cacheName = "my-cache";
				manager.createCache(
						cacheName,
						new MutableConfiguration<String, String>()
								.setStoreByValue(false)
								.setStatisticsEnabled(true)
								.setManagementEnabled(true)
								.setTypes(String.class, String.class));
				try (final Cache<String, String> cache = manager.getCache(cacheName, String.class, String.class)) {
					System.out.println(cache.getName());
					cache.put("foo", "bar");
					if ("bar".equals(cache.get("foo"))) {
						System.out.printf(">> Yes!");
					}
				}
			}
		}
	}
}

/* pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
		 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>org.superbiz</groupId>
	<artifactId>jcache-demo</artifactId>
	<version>1.0-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>javax.cache</groupId>
			<artifactId>cache-api</artifactId>
			<version>1.0.0</version>
			<!-- <scope>provided</scope> -->
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-jcs-jcache</artifactId>
			<version>2.0-SNAPSHOT</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.1</version>
				<configuration>
					<target>1.7</target>
					<source>1.7</source>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>


*/
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s