On behalf of the SDK Engineering Team, I'm happy to announce that we've worked on an implementation of the JCache specification (JSR107) and so a developer preview is in order!

The JCache specification allows developers to build their applications around a standard API for Caching, swapping implementations with minimum effort. This implementation will rely on Couchbase Server and the 2.0 Java SDK to perform caching in an efficient and performant manner.

We want developers to have a taste of what's to come and allow them to give feedback and suggestions early in the process. Note that this is by no mean a finished implementation, as quite a few things are still work in progress, but basic operations and configuration are functional.

Let's discover how to use this implementation!

Obtaining The Implementation

The plan is of course to make it available on Maven Central, but for now the Couchbase JCache implementation is hosted on our own Maven repository. You can grab the developer preview from there by adding the following to your pom.xml:

Alternatively, you can grab the jars directly (you'll need java-cache, java-client and java-core), of if you feel adventurous you can see the latest code on github.

A Short Overview

In JCache, a CachingProvider is resolved and used to obtain a CacheManager, in turn used to create Caches. Each cache can be configured using a CacheConfiguration.

This implementation relies on the Cluster and Bucket introduced in the Java SDK 2.0.0. In order to correctly configure the underlying bucket, a CouchbaseConfiguration must be used in this implementation (but note that CouchbaseConfiguration.builder().build() should provide sane defaults, see below).

Each CouchbaseCacheManager has an underlying CouchbaseCluster instance. These are bootstrapped using a list of connection strings that default to localhost but can be changed by calling setBootstrap on the caching provider prior to creating the cache manager.

The CouchbaseCacheManager can then be used to create and obtain a new CouchbaseCache, which is backed by a Bucket from the SDK.

Let's see a short complete example. This example requires the following couchbase context:

  • A cluster reachable on localhost:8091
  • A bucket named “jcache” (password: “jcache”) in this cluster

Once that is the case, the following snippet can be run:

Note that cache managers are identified by an URI and a ClassLoader, and are only created if no previous CacheManager was registered for the same identifiers (otherwise the method returns the existing manager).

Customizing The Way Caching Is Done

We saw that by default, the caching implementation tries to connect to a cluster reachable on localhost, and that we can use CouchbaseConfiguration.builder("cacheName").build() as a default for the configuration of a cache. But was can we customize through CouchbaseConfiguration?

Common Settings in the JCache API

The CouchbaseConfiguration is based on a default MutableConfiguration (which defines common settings from the API). One can change these settings either by mutating the configuration once it is built, or passing a CompleteConfiguration to be copied to the builder's useBase(CompleteConfiguration base) method.

What Bucket To Use?

You have two options: either share a single bucket for multiple caches, prefixing the keys of each cache in the shared bucket, or use a dedicated bucket for a given cache.

By default, a shared bucket named jcache is used (expected password: “jcache”). The default prefix is the name of the cache followed by an underscore.

  • Shared cache can be changed via useSharedBucket(String name, String password).
  • Key prefix in a shared cache context can be changed by using withPrefix(String prefix).
  • Alternative method of using dedicated cache can be activated by using useDedicatedBucket(String name, String password) (it will reset the prefix).

Relying On Views To List All Items In A Cache

Part of the JCache API allows to get all items in a cache, or iterate over them. The best way to achieve that in Couchbase is to use views. So this implementations expects a view to be available to list all items in a cache.

  • By default, the expected design document and view are jcache and the cacheName.
  • The design document can be changed by calling viewAllDesignDoc(String designDocName).
  • The view name can be changed by calling viewAllViewName(String viewName).
  • Alternatively use viewAll(String designDocName, String viewName) to change both.

The user is expected to create the correct view in the correct bucket for each cache. Don't forget that keys are probably prefixed in the bucket (unless you explicitely used a dedicated bucket).

What's Next?

This developer preview showcases the general direction we went with this implementation, and has most JCache operations working in a minimal capacity (there's no proper locking yet, so operations described as atomic in the spec, like getAndPut, should not be considered as such).

The remaining things to implement in order to have a full specification coverage are: – improving and completing statistics gathering – locking, atomicity of a sub-set of operations – adding support for listeners – adding support for EntryProcessors – implementing read-through and write-through – adding annotation support


I hope this will be of interest to you. If you want to learn more about JCache or the Java SDK (and maybe come back here later), here are some resources:

If you have some suggestions or feedback to give, please do! The best place to do so is in the comments below or in the official forums.

You can also file Issues in our bug tracker (use the “Couchbase Java Client” project, aka JCBC, and use JCache component).

Contributions are also welcome! You would have to sign our CLA (see open-source doc) and let us validate that you did before submitting a pull-request on GitHub.

I hope you enjoyed this preview. Happy coding!

Posted by Simon Basle, Software Engineer, Pivotal

Simon Basl_ is a Paris-based Software Engineer working in the Spring team at Pivotal. Previously, he worked in the Couchbase Java SDK team. His interests span software design aspects (OOP, design patterns, software architecture), rich clients, what lies beyond code (continuous integration, (D)VCS, best practices), and reactive programming. He is also an editor for the French version of InfoQ.com.

Leave a reply