JCache EntryProcessor Example

This post introduces you to JCache EntryProcessor interface. This interface is used to create concrete classes, whose purpose is to modify a cache entry.

This is useful when multiple thread are accessing the cache and trying to modify a cache entry at the same time. To avoid threading issues like race condition etc, the thread logic can use EntryProcessor implementation to perform compound operations as one atomic unit.

For example if a task involves modifying a cache entry and the task is executed in parallel using multiple threads. To prevent multiple threads from modifying the same entry at the same time without any lock on the cache entry resulting in wrong updations, we can use an implementation of EntryProcessor interface. The implementation will contain multiple operations that are to be executed as one unit on the cache entry.

The interface contains “process” method which takes the below two arguments.
1) an instance of MutableEntry allows exclusive access to a cache entry.
2) an array of arguments

Below is an example

Main Code


1  import java.util.Iterator;
2  
3  import javax.cache.Cache;
4  import javax.cache.Cache.Entry;
5  import javax.cache.CacheManager;
6  import javax.cache.Caching;
7  import javax.cache.configuration.MutableConfiguration;
8  import javax.cache.processor.EntryProcessor;
9  import javax.cache.processor.EntryProcessorException;
10 import javax.cache.processor.MutableEntry;
11 import javax.cache.spi.CachingProvider;
12 
13 public class JCacheDemo8 {
14  public static void main(String[] args) {
15      CachingProvider cachingProvider = Caching.getCachingProvider();
16      CacheManager cacheManager = cachingProvider.getCacheManager();
17      
18      MutableConfiguration mutableConfiguration = new MutableConfiguration();
19      mutableConfiguration.setTypes(String.class, String.class);
20      
21      Cache cache = cacheManager.createCache("cache1", mutableConfiguration);
22      cache.put("key1", "value1");
23      cache.put("key2", "value2");
24      cache.put("key3", "value3");
25      cache.put("key4", "value4");
26      
27      Iterator<Cache.Entry> iterator = cache.iterator();
28      while(iterator.hasNext()) {
29          Entry entry = iterator.next();
30          System.out.println(entry.getKey() + ":" + entry.getValue());
31      }
32      
33      String oldValue = cache.invoke("key1", new CustomEntryProcessor(), "value");
34      System.out.println("Old value: " + oldValue);
35      
36      iterator = cache.iterator();
37      while(iterator.hasNext()) {
38          Entry entry = iterator.next();
39          System.out.println(entry.getKey() + ":" + entry.getValue());
40      }
41      
42      cachingProvider.close();
43  }
44 }
45 
46 class CustomEntryProcessor implements EntryProcessor {
47  @Override
48  public String process(MutableEntry entry, Object... arg1) throws EntryProcessorException {
49      String oldValue = entry.getValue();
50      entry.setValue((String)arg1[0]);
51      return oldValue;
52  }
53 }

Explanation

In the above code, I have created CustomEntryProcessor a concrete implementation of EntryProcessor interface.

The job of CustomEntryProcessor is to get a particular cache entry value, change the value of that entry and return the old value.

During the scope of the process method, the cache entry is locked, preventing intermedicate results of the operation visible to other threads.

The operations from line 49 to 51 will be executed as one atomic unit.

I am instructing the cache to perform the modifying operation implemented in CustomEntryProcessor, by calling invoke method on Cache class. Please refer to line 33.

The invoke method takes three arguments which are
1) the key name point to the cache entry which has to be modified.
2) an instance of EntryProcessor interface
3) an array of arguments.

The above code will change the value of cache entry with key “key1” from “value1” to “value”.

Output

SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
key2:value2
key1:value1
key4:value4
key3:value3
Old value: value1
key2:value2
key1:value
key4:value4
key3:value3

Leave a Reply