第32章 Infinispan CDI モジュール
32.1. Infinispan CDI モジュール
Infinispan の infinispan-cdi
モジュールには Context and Dependency Injection (CDI) が含まれています。 infinispan-cdi
モジュールは以下を提供します。
- Cache API を使用した設定およびインジェクション。
- キャッシュリスナーと CDI イベントシステム間のブリッジ。
- JCACHE をキャッシュするアノテーションの部分サポート。
32.2. Infinispan CDI の使用
32.2.1. Infinispan CDI の要件
以下は Infinispan CDI モジュールを Red Hat JBoss Data Grid と使用するための要件になります。
- 最新バージョンの infinispan-cdi モジュールを使用してください。
- 依存関係の情報を正しく設定してください。
32.2.2. CDI Maven 依存関係の設定
CDI モジュールは各デプロイメント型の Infinispan jar に含まれています。他に必要な依存関係はありません。
ライブラリーモード
ライブラリーモードでは、infinispan-embedded
アーティファクトに CDI モジュールが含まれています。以下の例のように依存関係として追加する必要があります。
<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-embedded</artifactId> <version>${infinispan.version}</version> </dependency>
リモートクライアントサーバーモード
リモートクライアントサーバーモードでは、infinispan-remote
アーティファクトに CDI モジュールが含まれています。以下の例のように依存関係として追加する必要があります。
<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-remote</artifactId> <version>${infinispan.version}</version> </dependency>
32.3. Infinispan CDI モジュールの使用
32.3.1. Infinispan CDI モジュールの使用
Infinispan CDI モジュールは以下の目的に使用できます。
- Infinispan キャッシュを CDI Bean および Java EE コンポーネントに設定およびインジェクトする。
- キャッシュマネージャーの設定。
- CDI アノテーションを使用した格納および取得の制御。
32.3.2. Infinispan キャッシュの設定およびインジェクション
32.3.2.1. Infinispan キャッシュのインジェクション
Infinispan キャッシュは、プロジェクトの CDI Bean にインジェクトできる複数のコンポーネントの 1 つです。
以下のコードスニペットはキャッシュインスタンスを CDI Bean にインジェクトする方法を示しています。
public class MyCDIBean { @Inject Cache<String, String> cache; }
32.3.2.2. リモート Infinispan キャッシュのインジェクション
リモート Infinispan キャッシュをインジェクトするには、普通のキャッシュをインジェクトするコードスニペットを次のように若干変更します。
public class MyCDIBean { @Inject RemoteCache<String, String> remoteCache; }
32.3.2.3. インジェクションのターゲットキャッシュの設定
32.3.2.3.1. インジェクションのターゲットキャッシュの設定
インジェクションのターゲットキャッシュを設定するには、次の 3 つのステップに従います。
- 修飾子アノテーションを作成します。
- プロデューサークラスを追加します。
- 希望のクラスをインジェクトします。
32.3.2.3.2. 修飾子アノテーションの作成
CDI を使用して特定のキャッシュを返すには、次のようにカスタムのキャッシュ修飾子アノテーションを作成します。
カスタムキャッシュ修飾子
@javax.inject.Qualifier @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface SmallCache {}
作成した @SmallCache
修飾子を使用して、特定のキャッシュの作成方法を指定します。
32.3.2.3.3. プロデューサークラスの追加
以下のコードスニペットは、@SmallCache
修飾子 (前のステップで作成) がどのようにキャッシュの作成方法を指定するかを示しています。
@SmallCache
修飾子の使用
import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.cdi.ConfigureCache; import javax.enterprise.inject.Produces; public class CacheCreator { @ConfigureCache("smallcache") @SmallCache @Produces public Configuration specialCacheCfg() { return new ConfigurationBuilder() .memory() .size(10) .build(); } }
コードスニペットの要素は次のとおりです。
-
@ConfigureCache
はキャッシュの名前を指定します。 -
@SmallCache
はキャッシュ修飾子です。
32.3.2.3.4. 希望のクラスのインジェクト
以下のように @SmallCache
修飾子と新しいプロデューサークラスを使用して、特定のキャッシュを CDI Bean にインジェクトします。
public class MyCDIBean { @Inject @SmallCache Cache<String, String> mySmallCache; }
32.3.3. CDI を用いたキャッシュマネージャーの設定
32.3.3.1. CDI を用いたキャッシュマネージャーの設定
Red Hat JBoss Data Grid のキャッシュマネージャー (組み込みとリモートの両方) は CDI を使用して設定できます。設定するキャッシュマネージャーが組み込みかリモートであるかに関わらず、最初の手順として、アノテーションを付けてプロデューサーとして動作するデフォルト設定を指定します。
32.3.3.2. デフォルト設定の指定
Red Hat JBoss Data Grid 設定に対してプロデューサーとしてアノテーション付けされたメソッドを指定し、デフォルトの Infinispan 設定を置き換えます。以下の設定例はこの手順を示しています。
デフォルト設定の指定
public class Config { @Produces public Configuration defaultEmbeddedConfiguration () { return new ConfigurationBuilder() .memory() size(100) .build(); } }
他の修飾子が提供されない場合、CDI は @Default
修飾子を追加します。
@Produces
アノテーションが設定インスタンスを返すメソッドに配置された場合、Configuration オブジェクトが必要なときにメソッドが呼び出されます。
この設定例では、作成後に設定され返される新しい Configuration オブジェクトが作成されます。
32.3.3.3. 組み込みキャッシュマネージャーの作成のオーバーライド
前提条件
「デフォルト設定の指定」参照してください。
非クラスターキャッシュの作成
プロデューサーメソッドにアノテーションが付けられた後、以下のように EmbeddedCacheManager
の作成時にこのメソッドが呼び出されます。
public class Config { @Produces @ApplicationScoped public EmbeddedCacheManager defaultEmbeddedCacheManager() { Configuration cfg = new ConfigurationBuilder() .memory() .size(150) .build(); return new DefaultCacheManager(cfg); } }
@ApplicationScoped
アノテーションはメソッドが 1 度だけ呼び出されることを指定します。
クラスターキャッシュの作成
以下の設定は、クラスターキャッシュの作成が可能な EmbeddedCacheManager
の作成に使用できます。
public class Config { @Produces @ApplicationScoped public EmbeddedCacheManager defaultClusteredCacheManager() { GlobalConfiguration g = new GlobalConfigurationBuilder() .clusteredDefault() .transport() .clusterName("InfinispanCluster") .build(); Configuration cfg = new ConfigurationBuilder() .memory() .size(150) .build(); return new DefaultCacheManager(g, cfg); } }
EmbeddedCacheManager を生成するメソッドの呼び出し
非クラスターメソッドの @Produces
アノテーションが付けられたメソッドは Configuration
オブジェクトを生成します。クラスターキャッシュの例で @Produces
アノテーションが付けられたメソッドは EmbeddedCacheManager
オブジェクトを生成します。
以下のように CDI Bean にインジェクションを追加し、適切にアノテーションが付けられたメソッドを呼び出します。これにより EmbeddedCacheManager
が生成され、起動時にコードにインジェクトされます。
EmbeddedCacheManager の生成
... @Inject EmbeddedCacheManager cacheManager; ...
32.3.3.4. リモートキャッシュマネージャーの設定
RemoteCacheManager
は、以下のように EmbeddedCacheManagers
と似た方法で設定されます。
リモートキャッシュマネージャーの設定
public class Config { @Produces @ApplicationScoped public RemoteCacheManager defaultRemoteCacheManager() { Configuration conf = new ConfigurationBuilder().addServer().host(ADDRESS).port(PORT).build(); return new RemoteCacheManager(conf); } }}
32.3.3.5. 単一クラスでの複数のキャッシュマネージャーの設定
単一のクラスを使用して、作成された修飾子を基に複数のキャッシュマネージャーおよびリモートキャッシュマネージャーを設定できます。以下に例を示します。
複数のキャッシュマネージャーの設定
public class Config { @Produces @ApplicationScoped public org.infinispan.manager.EmbeddedCacheManager defaultEmbeddedCacheManager() { Configuration cfg = new ConfigurationBuilder() .memory() .size(150) .build(); return new DefaultCacheManager(cfg); } @Produces @ApplicationScoped @DefaultClustered public org.infinispan.manager.EmbeddedCacheManager defaultClusteredCacheManager() { GlobalConfiguration g = new GlobalConfigurationBuilder() .clusteredDefault() .transport() .clusterName("InfinispanCluster") .build(); Configuration cfg = new ConfigurationBuilder() .memory() .size(150) .build(); return new DefaultCacheManager(g, cfg); } @Produces @ApplicationScoped @DefaultRemote public RemoteCacheManager defaultRemoteCacheManager() { org.infinispan.client.hotrod.configuration.Configuration conf = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder().addServer().host(ADDRESS).port(PORT).build(); return new RemoteCacheManager(conf); } @Produces @ApplicationScoped @RemoteCacheInDifferentDataCentre public RemoteCacheManager newRemoteCacheManager() { org.infinispan.client.hotrod.configuration.Configuration confid = new org.infinispan.client.hotrod.configuration.ConfigurationBuilder().addServer().host(ADDRESS_FAR_AWAY).port(PORT).build(); return new RemoteCacheManager(confid); } }
32.4. CDI アノテーションを使用した格納および取得
32.4.1. キャッシュアノテーションの設定
特定の CDI アノテーションは JCache (JSR-107) 仕様で受け入れられます。含まれるアノテーションはすべて javax.cache パッケージにあります。
アノテーションインターセプトメソッドは CDI Bean を呼び出し、インターセプトの結果として格納および取得タスクを実行します。
CDI はリモートクライアントサーバーモードとライブラリーモードの両方でサポートされますが、@CachePut、@CacheRemove、@CacheRemoveAll、@CacheResult などのアノテーションはリモードクライアントサーバーモードでは使用できません。
32.4.2. キャッシュアノテーションの有効化
JBoss Data Grid には、使用方法に応じてインターセプターが 2 セット含まれています。beans.xml ファイルを使用するとインターセプターを CDI Bean アーカイブに追加できます。
オプション 1: CDI インターセプター
以下のコードを追加すると、InjectedCacheResultInterceptor
、InjectedCachePutInterceptor
、InjectedCacheRemoveEntryInterceptor
、および InjectedCacheRemoveAllInterceptor
などのインターセプターが追加されます。
CDI インターセプターの追加
<beans xmlns="http://java.sun.som/xml/ns/javaee" xmlns:xsi="http://www/w3/org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd" > <interceptors> <class>org.infinispan.jcache.annotation.InjectedCacheResultInterceptor</class> <class>org.infinispan.jcache.annotation.InjectedCachePutInterceptor</class> <class>org.infinispan.jcache.annotation.InjectedCacheRemoveEntryInterceptor</class> <class>org.infinispan.jcache.annotation.InjectedCacheRemoveAllInterceptor</class> </interceptors> </beans>
オプション 2: JCache インターセプター
以下のコードを追加すると CacheResultInterceptor
、CachePutInterceptor
、CacheRemoveEntryInterceptor
、および CacheRemoveAllInterceptor
などのインターセプターが追加されます。
JCache インターセプターの追加
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd"> <interceptors> <class>org.infinispan.jcache.annotation.CacheResultInterceptor</class> <class>org.infinispan.jcache.annotation.CachePutInterceptor</class> <class>org.infinispan.jcache.annotation.CacheRemoveEntryInterceptor</class> <class>org.infinispan.jcache.annotation.CacheRemoveAllInterceptor</class> </interceptors> </beans>
Red Hat JBoss Data Grid が javax.cache アノテーションを使用するには、記載されているインターセプターが beans.xml ファイルに存在する必要があります。
32.4.3. メソッド呼び出しの結果をキャッシュ
32.4.3.1. メソッド呼び出しの結果をキャッシュ
今後のアクセスのために結果をキャッシュに保存することは、時間またはリソース集約型の操作で一般的に行われます。以下のコードはこのような操作の例になります。
public String toCelsiusFormatted(float fahrenheit) { return NumberFormat.getInstance() .format((fahrenheit * 5 / 9) - 32) + " degrees Celsius"; }
一般的には、メソッド呼び出しの結果をキャッシュし、次に結果が必要になるときにキャッシュをチェックします。以下は、このような操作の結果をキャッシュで検索するコードスニペットの例になります。結果が見つからない場合、コードスニペットは toCelsiusFormatted
を再実行し、結果をキャッシュに格納します。
float f = getTemperatureInFahrenheit(); Cache<Float, String> fahrenheitToCelsiusCache = getCache(); String celsius = fahrenheitToCelsiusCache = get(f); if (celsius == null) { celsius = toCelsiusFormatted(f); fahrenheitToCelsiusCache.put(f, celsius); }
このような場合、Infinispan CDI モジュールを使用すると、関連する例で余分なコードを削除できます。以下のように、メソッドに @CacheResult
アノテーションを付けます。
@javax.cache.annotation.CacheResult public String toCelsiusFormatted(float fahrenheit) { return NumberFormat.getInstance() .format((fahrenheit * 5 / 9) - 32) + " degrees Celsius"; }
アノテーションにより、Infinispan はキャッシュをチェックし、結果が見つからなかった場合は toCelsiusFormatted()
メソッドを呼び出します。
Infinispan CDI モジュールでは、保存した結果のキャッシュをチェックできますが、これは適用前に注意して考慮する必要があります。呼び出しの結果が常に最新のデータである必要がある場合やキャッシュの読み取りにリモートネットワークの検索やキャッシュローダーからのデシリアライズが必要である場合、コールメソッド呼び出し前のキャッシュのチェックは逆効果になる可能性があります。
32.4.3.2. 使用するキャッシュの指定
以下のオプションの属性 (cacheName
) を @CacheResult
アノテーションに追加し、メソッドコールの結果をチェックするキャッシュを指定します。
@CacheResult(cacheName = "mySpecialCache") public String doSomething(String parameter) { <!-- Additional configuration information here --> }
32.4.3.3. キャッシュされた結果のキャッシュキー
デフォルトでは、@CacheResult
アノテーションはキャッシュから取得された結果のキーを作成します。このキーは、関連するメソッドのすべてのパラメーターの組み合わせで構成されます。
次のように @CacheKey
アノテーションを使用してカスタムキーを作成します。
カスタムキーの作成
@CacheResult public String doSomething (@CacheKey String p1, @CacheKey String p2, String dontCare) { <!-- Additional configuration information here --> }
この例では、キャッシュキーの作成に p1
と p2
のみが値として使用されます。キャッシュキーの判断には dontCare
の値は使用されません。
32.4.3.4. カスタムキーの生成
次のようにカスタムキーを生成します。
import javax.cache.annotation.CacheKey; import javax.cache.annotation.CacheKeyGenerator; import javax.cache.annotation.CacheKeyInvocationContext; import java.lang.annotation.Annotation; public class MyCacheKeyGenerator implements CacheKeyGenerator { @Override public CacheKey generateCacheKey(CacheKeyInvocationContext<? extends Annotation> ctx) { return new MyCacheKey( ctx.getAllParameters()[0].getValue() ); } }
このメソッドはカスタムキーを構築します。このキーは呼び出しコンテキストの最初のパラメーターによって生成された値の一部として渡されます。
カスタムのキー生成スキームを指定するには、以下のように任意のパラメーター cacheKeyGenerator
を @CacheResult
アノテーションに追加します。
@CacheResult(cacheKeyGenerator = MyCacheKeyGenerator.class) public void doSomething(String p1, String p2) { <!-- Additional configuration information here --> }
提供されたメソッドを使用し、p1
にカスタムキーが含まれます。
32.4.4. キャッシュ操作
32.4.4.1. キャッシュエントリーの更新
@CachePut
アノテーションが含まれるメソッドが呼び出されると、パラメーター (通常は @CacheValue
アノテーションが付けられたメソッドに渡されます) はキャッシュに格納されます。
@CachePut
アノテーションが付けられたメソッドの例
import javax.cache.annotation.CachePut; import javax.cache.annotation.CacheKey; import javax.cache.annotation.CacheValue; @CachePut (cacheName = "personCache") public void updatePerson (@CacheKey long personId, @CacheValue Person newPerson) { <!-- Additional configuration information here --> }
@CachePut
メソッドの cacheName
および cacheKeyGenerator
を使用するとさらにカスタマイズすることができます。また、呼び出されたメソッドの一部のパラメーターに @CacheKey
アノテーションを付けるとキーの生成を制御できます。
「キャッシュされた結果のキャッシュキー」も参照してください。
32.4.4.2. キャッシュからのエントリーの削除
以下は、キャッシュからエントリーを削除するために使用される @CacheRemoveEntry
アノテーションが付けられたメソッドの例になります。
キャッシュからエントリーを削除
import javax.cache.annotation.CacheRemoveEntry; import javax.cache.annotation.CacheKey; @CacheRemoveEntry (cacheName = "cacheOfPeople") public void changePersonName (@CacheKey long personId, string newName) { <!-- Additional configuration information here --> }
このアノテーションは、任意の cacheName
および cacheKeyGenerator
属性を受け入れます。
32.4.4.3. キャッシュの消去
@CacheRemoveAll
メソッドを呼び出して、キャッシュからすべてのエントリーを消去します。
@CacheRemoveAll
を使用してキャッシュからすべてのエントリーを消去
import javax.cache.annotation.CacheRemoveAll; @CacheRemoveAll (cacheName = "statisticsCache") public void resetStatistics() { <!-- Additional configuration information here --> }
例のとおり、このアノテーションは任意の cacheName
属性を受け入れます。