この章では、キャッシュ・エントリを変更するためにJCacheエントリ・プロセッサを作成および使用する手順について説明します。エントリ・プロセッサはjavax.cache.processorパッケージで定義され、Java Caching API仕様の第9章「Entry Processors」で説明されています。
この章には次の項が含まれます:
JCacheは、アトミックでロック・フリーな方法でキャッシュ・エントリの更新を実行するエントリ・プロセッサの使用をサポートしています。分散キャッシュ環境では、エントリはキャッシュ・データを保持している異なるサーバーのそれぞれで並列に処理されます。
多くの場合、エントリ・プロセッサは1回の操作でキャッシュに複数の変更を行うために使用されます。たとえば、エントリ・プロセッサは一連のキーの値を評価し、あるロジックに基づいて異なる値を返すかもしれません。アプリケーションは処理の最終的な結果のみを表示でき、エントリ・プロセッサが起動中である中間の結果にはアクセスしません。処理中にエラーは発生した場合、例外がスローされ、キャッシュは変更されません。
エントリ・プロセッサはEntryProcessorインタフェースを実装する必要があります。エントリ・プロセッサの実装は、Cache.invokeおよびCache.invokeAllメソッドによって実行時にキャッシュ・エントリ上で起動されます。
また、Coherence JCacheプロバイダは、ローカル、パーティションおよびパススルー・キャッシュでのJCacheエントリ・プロセッサの使用をサポートしています。プロバイダは、Coherence固有のInvocableMap.EntryProcessor APIを使用してJCacheエントリ・プロセッサを実装しています。
エントリ・プロセッサはEntryProcessorインタフェースを実装する必要があります。このインタフェースには、キャッシュ・エントリのすべての処理ロジックを提供する1つのprocessメソッドが含まれています。エントリ・プロセッサは、MutableEntryエントリを操作します。MutableEntryインタフェースは、エントリ・プロセッサが処理の間、エントリに排他アクセスすることを保証します。processメソッドでも、すべての引数を定義できます。引数は、プロセッサが起動された際にそのプロセッサに渡されます。
エントリ・プロセッサの一部として実行される操作はアプリケーションには見えず、processメソッドが完了した後でのみ有効になります。processメソッドでエラーが発生した場合、キャッシュ・エントリは変更されません。
エントリ・プロセッサはインプロセスで実行されることは保証されないため、常にシリアライズ可能です。たとえば、Coherenceパーティション・キャッシュを使用する場合は、エントリ・プロセッサが処理されるデータを含むキャッシュ・サーバー上で実行される可能性があります。Coherenceキャッシュでは、エントリ・プロセッサはPOFシリアライズも使用できます。ただし、POFにはキャッシュ・プロバイダ実装間の移植性はありません。
例37-1では、キャッシュ・エントリの値を1つ増やすエントリ・プロセッサを作成しています。このエントリの値は整数です。キー、値および戻り値の型は、APIによって要求される型の安全性を保証するために明示的に定義されています。
例37-1 EntryProcessorの実装例
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;
}
}
}
Cache APIは、エントリ・プロセッサを起動する2つのメソッドを提供しています。invokeメソッドは単一のキャッシュ・エントリを操作し、invokeAllメソッドは一連のキャッシュ・エントリを操作します。エントリは、キー名を使用して指定します。
エントリ・プロセッサは、Cacheインスタンスからinvokeメソッドを使用して単一のキーに対して起動されます。次の例は、単一キーの処理を示しています。この例では、例37-1で作成したMyEntryProcessorの実装を使用しています。
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");
エントリ・プロセッサは、invokeAllメソッドを使用して複数のキーに対して起動されます。キーは、Set実装によってグループ化されている必要があります。プロセッサはセット内の各キーに対して起動されますが、キーが処理される順番は保証されていません。次の例は、HashSetクラスによってグループ化されている複数のキーを処理し、EntryProcessorResult.getメソッドを使用してある特定のキーに対するエントリ・プロセッサから戻された値を取得する方法を示しています。この例では、例37-1で作成したMyEntryProcessorの実装を使用しています。
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");