この章では、キャッシュ・エントリを変更するために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");