[[jcache_jsr_107]]
= JCache (JSR-107) API
{brandname} provides an implementation of
JCache 1.0 API ( link:http://www.jcp.org/en/jsr/detail?id=107[JSR-107] ).
JCache specifies a standard Java API for caching temporary Java objects in
memory. Caching java objects can help get around bottlenecks arising from
using data that is expensive to retrieve (i.e. DB or web service), or data
that is hard to calculate. Caching these type of objects in memory can help
speed up application performance by retrieving the data directly from memory
instead of doing an expensive roundtrip or recalculation. This document
specifies how to use JCache with the {brandname} implementation of the
specification, and explains key aspects of the API.

== Creating embedded caches

.Prerequisites

. Ensure that `cache-api` is on your classpath.
. Add the following dependency to your `pom.xml`:
+
[source,xml,options="nowrap",subs=attributes+]
----
include::dependencies_maven/jcache.xml[]
----

.Procedure

* Create embedded caches that use the default JCache API configuration as follows:

[source,java]
----
include::code_examples/JCacheCreateCache.java[]
----

=== Configuring embedded caches

* Pass the URI for custom {brandname} configuration to the `CachingProvider.getCacheManager(URI)` call as follows:

[source,java]
----
include::code_examples/JCacheCreateCacheCustomConfig.java[]
----

WARNING: By default, the JCache API specifies that data should be stored as
`storeByValue`, so that object state mutations outside of operations to the
cache, won't have an impact in the objects stored in the cache. {brandname}
has so far implemented this using serialization/marshalling to make copies to
store in the cache, and that way adhere to the spec. Hence, if using default
JCache configuration with {brandname}, data stored must be marshallable.

Alternatively, JCache can be configured to store data by reference
(just like {brandname} or JDK Collections work). To do that, simply call:

[source,java]
----
include::code_examples/CreateCacheMutableConfiguration.java[]
----

== Creating remote caches

.Prerequisites

. Ensure that `cache-api` is on your classpath.
. Add the following dependency to your `pom.xml`:
+
[source,xml,options="nowrap",subs=attributes+]
----
include::dependencies_maven/jcache-remote.xml[]
----

.Procedure

* Create caches on remote {brandname} servers and use the default JCache API configuration as follows:

[source,java]
----
include::code_examples/JCacheCreateRemoteCache.java[]
----

=== Configuring remote caches

Hot Rod configuration files include `infinispan.client.hotrod.cache.*`
properties that you can use to customize remote caches.

* Pass the URI for your `hotrod-client.properties` file to the `CachingProvider.getCacheManager(URI)` call as follows:

[source,java]
----
include::code_examples/JCacheCreateRemoteCacheCustomConfig.java[]
----

== Store and retrieve data
Even though JCache API does not extend neither
link:{jdkdocroot}/java/util/Map.html[java.util.Map]
not link:{jdkdocroot}/java/util/concurrent/ConcurrentMap.html[java.util.concurrent.ConcurrentMap],
it providers a key/value API to store and retrieve data:

[source,java]
----
include::code_examples/JCacheStoreRetrieve.java[]
----

Contrary to standard link:{jdkdocroot}/java/util/Map.html[java.util.Map],
link:https://github.com/jsr107/jsr107spec/blob/v1.0.0-RC1/src/main/java/javax/cache/Cache.java[javax.cache.Cache]
comes with two basic put methods called put and getAndPut. The former returns
`void` whereas the latter returns the previous value associated with the key.
So, the equivalent of link:{jdkdocroot}/java/util/Map.html#put-K-V-[java.util.Map.put(K)]
in JCache is link:https://github.com/jsr107/jsr107spec/blob/v1.0.0-RC1/src/main/java/javax/cache/Cache.java#L230[javax.cache.Cache.getAndPut(K)].


TIP: Even though JCache API only covers standalone caching, it can be plugged
with a persistence store, and has been designed with clustering or
distribution in mind. The reason why javax.cache.Cache offers two put methods
is because standard java.util.Map put call forces implementors to calculate
the previous value. When a persistent store is in use, or the cache is
distributed, returning the previous value could be an expensive operation, and
often users call standard link:{jdkdocroot}/java/util/Map.html#put-K-V-[java.util.Map.put(K)]
without using the return value. Hence, JCache users need to think about
whether the return value is relevant to them, in which case they need to call
link:https://github.com/jsr107/jsr107spec/blob/v1.0.0-RC1/src/main/java/javax/cache/Cache.java#L230[javax.cache.Cache.getAndPut(K)] ,
otherwise they can call link:{jdkdocroot}/java/util/Map.html#put-K-V-[java.util.Map.put(K, V)]
which avoids returning the potentially expensive operation of returning the
previous value.


== Comparing java.util.concurrent.ConcurrentMap and javax.cache.Cache APIs
Here's a brief comparison of the data manipulation APIs provided by
link:{jdkdocroot}/java/util/concurrent/ConcurrentMap.html[java.util.concurrent.ConcurrentMap]
and link:https://github.com/jsr107/jsr107spec/blob/v1.0.0-RC1/src/main/java/javax/cache/Cache.java[javax.cache.Cache] APIs.

[options="header"]
|===
|Operation |java.util.concurrent.ConcurrentMap<K, V> |javax.cache.Cache<K, V>

|store and no return
| N/A 
| `void put(K key)`

|store and return previous value
| `V put(K key)`
| `V getAndPut(K key)`

|store if not present
| `V putIfAbsent(K key, V value)`
| `boolean putIfAbsent(K key, V value)`

|retrieve
| `V get(Object key)`
| `V get(K key)`

|delete if present
| `V remove(Object key)`
| `boolean remove(K key)`

|delete and return previous value
| `V remove(Object key)`
| `V getAndRemove(K key)`

|delete conditional
| `boolean remove(Object key, Object value)`
| `boolean remove(K key, V oldValue)`

|replace if present
| `V replace(K key, V value)`
| `boolean replace(K key, V value)`

|replace and return previous value
| `V replace(K key, V value)`
| `V getAndReplace(K key, V value)`

|replace conditional
| `boolean replace(K key, V oldValue, V newValue)`
| `boolean replace(K key, V oldValue, V newValue)`

|===

Comparing the two APIs, it's obvious to see that, where possible, JCache
avoids returning the previous value to avoid operations doing expensive
network or IO operations. This is an overriding principle in the design of
JCache API. In fact, there's a set of operations that are present in
link:{jdkdocroot}/java/util/concurrent/ConcurrentMap.html[java.util.concurrent.ConcurrentMap] ,
but are not present in the link:https://github.com/jsr107/jsr107spec/blob/v1.0.0-RC1/src/main/java/javax/cache/Cache.java[javax.cache.Cache]
because they could be expensive to compute in a distributed cache.
The only exception is iterating over the contents of the cache:

[options="header"]
|===
|Operation |java.util.concurrent.ConcurrentMap<K, V> |javax.cache.Cache<K, V>

|calculate size of cache
| `int size()`
| N/A

|return all keys in the cache
| `Set<K> keySet()`
| N/A

|return all values in the cache
| `Collection<V> values()`
| N/A

|return all entries in the cache
| `Set<Map.Entry<K, V>> entrySet()`
| N/A

|iterate over the cache
| use `iterator()` method on keySet, values or entrySet
| `Iterator<Cache.Entry<K, V>> iterator()`

|===


== Clustering JCache instances
{brandname} JCache implementation goes beyond the specification in order to
provide the possibility to cluster caches using the standard API. Given a
{brandname} configuration file configured to replicate caches like this:

.infinispan.xml
[source,xml,options="nowrap",subs=attributes+]
----
include::xml/jcache_clustering.xml[]
----

You can create a cluster of caches using this code:

[source,java]
----
include::code_examples/JCacheClustering.java[]
----
