37 Processing JCache Entries
javax.cache.processor
package and described in Chapter 9 of the Java Caching API Specification.
This chapter includes the following sections:
- Overview of Processing JCache Entries
JCache supports the use of entry processors to perform updates on cache entries in an atomic, lock-free manner. - Creating Entry Processors
JCache entry processors must implement theEntryProcessor
interface. - Using Entry Processors
TheCache
API provides theinvoke
andinvokeAll
methods that are used to call an entry processor.
Parent topic: Using the Coherence JCache Implementation
Overview of Processing JCache Entries
Entry processors are often used to make multiple changes to a cache in a single operation. For example, the entry processor may evaluate the values for a set of keys and then return different values based on some logic. The application can only view the final result of the processing and does not have access to intermediary results while the entry processor is being invoked. If an error occurs during processing, then an exception is thrown and no changes are made to the cache.
Entry processors must implements the EntryProcessor
interface. Entry processor implementations are invoked on cache entries at runtime using the Cache.invoke
and Cache.invokeAll
methods.
Lastly, the Coherence JCache provider supports the use of JCache entry processors for local, partitioned, and pass-through caches. The provider makes use of the native Coherence InvocableMap.EntryProcessor
API to implement JCache entry processors.
Parent topic: Processing JCache Entries
Creating Entry Processors
EntryProcessor
interface.The interface contains a single process
method that is used to provide any processing logic for cache entries. Entry processors operate on MutableEntry
entries. The MutableEntry
interface ensures that entry processors have exclusive access to entries during processing. The process
method also allows any arguments to be defined. The arguments can be passed to the processor when the processor is invoked.
Operations that are performed as part of an entry processor are not visible to an application and only take affect after the process
method has completed. If an error occurs during the process
method, then no changes are made to the cache entries.
Entry processors are not guaranteed to be executed in-process and therefore should always be serializable. For example, when using a Coherence partitioned cache, an entry processor may be executed on the cache server that contains the data to be processed. For Coherence caches, entry processors have the option of using POF serialization. However, POF is not portable among cache provider implementations.
Example 37-1 creates an entry processor that increments the value of a cache entry by one. The value of the entry is an integer. The key, value, and return types are explicitly defined to ensure type safety as required by the API.
Example 37-1 An Example EntryProcessor Implementation
import java.io.Serializable; import javax.cache.processor.EntryProcessor; import javax.cache.processor.EntryProcessorException; import javax.cache.processor.MutableEntry; public class MyEntryProcessor implements EntryProcessor <String, Integer, Integer>, Serializable { public static final long serialVersionUID = 1L; public Integer process(MutableEntry<String, Integer> entry, Object... arguments) throws EntryProcessorException { if (entry.exists()) { Integer current = entry.getValue(); entry.setValue(current + 1); return current; } else { entry.setValue(0); return -1; } } }
Parent topic: Processing JCache Entries
Using Entry Processors
Cache
API provides the invoke
and invokeAll
methods that are used to call an entry processor.The invoke
method operates on a single cache entry and the invokeAll
method operates on a set of cache entries. Entries are specified using the key name.
This section includes the following topics:
Parent topic: Processing JCache Entries
Invoking Entry Processors for a Single Key
Entry processors are invoked on a single key using the invoke
method from a Cache
instance. The following example demonstrates processing a single key. The examples uses the MyEntryProcessor
implementation that was created in Example 37-1.
CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = cachingProvider.getCacheManager(); MutableConfiguration<String, Integer> config = new MutableConfiguration<String, Integer>(); config.setTypes(String.class, Integer.class); Cache<String, Integer> cache = cacheManager.createCache("MyCache", config); String key = "k"; Integer value = 1; cache.put(key, value); System.out.println("The value is " + cache.get(key) + "\n"); cache.invoke(key, new MyEntryProcessor()); System.out.println("The value is now " + cache.get(key) + "\n");
Parent topic: Using Entry Processors
Invoking Entry Processors for Multiple Keys
Entry processors are invoked on multiple keys using the invokeAll
method. The keys must be grouped together using a Set
implementation. The processor is invoked for each key in the set and the order in which keys are processed is not guaranteed. The following example demonstrates processing multiple keys that are grouped using the HashSet
class and also uses the EntryProcessorResult.get
method to retrieve the value returned by the entry processor for a specific key. The example uses the MyEntryProcessor
implementation that was created in Example 37-1.
CachingProvider cachingProvider = Caching.getCachingProvider(); CacheManager cacheManager = cachingProvider.getCacheManager(); MutableConfiguration<String, Integer> config = new MutableConfiguration<String, Integer>(); config.setTypes(String.class, Integer.class); Cache<String, Integer> cache = cacheManager.createCache("MyCache", config); String key = "k"; Integer value = 1; String key1 = "k1"; Integer value1 = 1; cache.put(key, value); cache.put(key1, value1); HashSet hs = new HashSet(); hs.add(key); hs.add(key1); Map<String, EntryProcessorResult<Integer>> map = cache.invokeAll(hs, new MyEntryProcessor()); System.out.println("The value of k is now " + cache.get(key) + " the result of invokeAll for k is previous value of " + map.get(key).get() + "\n"); System.out.println("The value of k1 is now " + cache.get(key1) + " the result of invokeAll for k1 is previous value of " + map.get(key1).get() + "\n");
Parent topic: Using Entry Processors