Chapter 10. Using the CDI Extension Data Grid provides an extension that integrates with the CDI (Contexts and Dependency Injection) programming model and allows you to: Configure and inject caches into CDI Beans and Java EE components. Configure cache managers. Receive cache and cache manager level events. Control data storage and retrieval using JCache annotations. 10.1. CDI Dependencies Update your pom.xml with one of the following dependencies to include the Data Grid CDI extension in your project: Embedded (Library) Mode Server Mode 10.2. Injecting Embedded Caches Set up CDI beans to inject embedded caches. Procedure Create a cache qualifier annotation. ... import javax.inject.Qualifier; @Qualifier @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GreetingCache { 1 } 1 Creates a @GreetingCache qualifier. Add a producer method that defines the cache configuration. ... import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.cdi.ConfigureCache; import javax.enterprise.inject.Produces; public class Config { @ConfigureCache("mygreetingcache") 1 @GreetingCache 2 @Produces public Configuration greetingCacheConfiguration() { return new ConfigurationBuilder() .memory() .size(1000) .build(); } } 1 Names the cache to inject. 2 Adds the cache qualifier. Add a producer method that creates a clustered Cache Manager, if required ... package org.infinispan.configuration.global.GlobalConfigurationBuilder; public class Config { @GreetingCache 1 @Produces @ApplicationScoped 2 public EmbeddedCacheManager defaultClusteredCacheManager() { 3 return new DefaultCacheManager( new GlobalConfigurationBuilder().transport().defaultTransport().build(); } } 1 Adds the cache qualifier. 2 Creates the bean once for the application. Producers that create Cache Managers should always include the @ApplicationScoped annotation to avoid creating multiple Cache Managers. 3 Creates a new DefaultCacheManager instance that is bound to the @GreetingCache qualifier. Note Cache managers are heavy weight objects. Having more than one Cache Manager running in your application can degrade performance. When injecting multiple caches, either add the qualifier of each cache to the Cache Manager producer method or do not add any qualifier. Add the @GreetingCache qualifier to your cache injection point. 10.3. Injecting Remote Caches Set up CDI beans to inject remote caches. Procedure Create a cache qualifier annotation. @Remote("mygreetingcache") 1 @Qualifier @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RemoteGreetingCache { 2 } 1 names the cache to inject. 2 creates a @RemoteGreetingCache qualifier. Add the @RemoteGreetingCache qualifier to your cache injection point. public class GreetingService { @Inject @RemoteGreetingCache private RemoteCache<String, String> cache; public String greet(String user) { String cachedValue = cache.get(user); if (cachedValue == null) { cachedValue = "Hello " + user; cache.put(user, cachedValue); } return cachedValue; } } Tips for injecting remote caches You can inject remote caches without using qualifiers. ... @Inject @Remote("greetingCache") private RemoteCache<String, String> cache; If you have more than one Data Grid cluster, you can create separate remote Cache Manager producers for each cluster. ... import javax.enterprise.context.ApplicationScoped; public class Config { @RemoteGreetingCache @Produces @ApplicationScoped 1 public ConfigurationBuilder builder = new ConfigurationBuilder(); 2 builder.addServer().host("localhost").port(11222); return new RemoteCacheManager(builder.build()); } } 1 creates the bean once for the application. Producers that create Cache Managers should always include the @ApplicationScoped annotation to avoid creating multiple Cache Managers, which are heavy weight objects. 2 creates a new RemoteCacheManager instance that is bound to the @RemoteGreetingCache qualifier. 10.4. JCache Caching Annotations You can use the following JCache caching annotations with CDI managed beans when JCache artifacts are on the classpath: @CacheResult caches the results of method calls. @CachePut caches method parameters. @CacheRemoveEntry removes entries from a cache. @CacheRemoveAll removes all entries from a cache. Important Target type: You can use these JCache caching annotations on methods only. To use JCache caching annotations, declare interceptors in the beans.xml file for your application. Managed Environments (Application Server) <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.2" bean-discovery-mode="annotated"> <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> Non-managed Environments (Standalone) <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.2" bean-discovery-mode="annotated"> <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> JCache Caching Annotation Examples The following example shows how the @CacheResult annotation caches the results of the GreetingService.greet() method: import javax.cache.interceptor.CacheResult; public class GreetingService { @CacheResult public String greet(String user) { return "Hello" + user; } } With JCache annotations, the default cache uses the fully qualified name of the annotated method with its parameter types, for example: org.infinispan.example.GreetingService.greet(java.lang.String) To use caches other than the default, use the cacheName attribute to specify the cache name as in the following example: @CacheResult(cacheName = "greeting-cache") 10.5. Receiving Cache and Cache Manager Events You can use CDI Events to receive Cache and Cache Manager level events. Use the @Observes annotation as in the following example: import javax.enterprise.event.Observes; import org.infinispan.notifications.cachemanagerlistener.event.CacheStartedEvent; import org.infinispan.notifications.cachelistener.event.*; public class GreetingService { // Cache level events private void entryRemovedFromCache(@Observes CacheEntryCreatedEvent event) { ... } // Cache manager level events private void cacheStarted(@Observes CacheStartedEvent event) { ... } }

Commands:
<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-cdi-embedded</artifactId> </dependency>
<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-cdi-remote</artifactId> </dependency>
import javax.inject.Qualifier; @Qualifier @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface GreetingCache { 1 }
import org.infinispan.configuration.cache.Configuration; import org.infinispan.configuration.cache.ConfigurationBuilder; import org.infinispan.cdi.ConfigureCache; import javax.enterprise.inject.Produces; public class Config { @ConfigureCache("mygreetingcache") 1 @GreetingCache 2 @Produces public Configuration greetingCacheConfiguration() { return new ConfigurationBuilder() .memory() .size(1000) .build(); } }
package org.infinispan.configuration.global.GlobalConfigurationBuilder; public class Config { @GreetingCache 1 @Produces @ApplicationScoped 2 public EmbeddedCacheManager defaultClusteredCacheManager() { 3 return new DefaultCacheManager( new GlobalConfigurationBuilder().transport().defaultTransport().build(); } }
import javax.inject.Inject; public class GreetingService { @Inject @GreetingCache private Cache<String, String> cache; public String greet(String user) { String cachedValue = cache.get(user); if (cachedValue == null) { cachedValue = "Hello " + user; cache.put(user, cachedValue); } return cachedValue; } }
@Remote("mygreetingcache") 1 @Qualifier @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RemoteGreetingCache { 2 }
public class GreetingService { @Inject @RemoteGreetingCache private RemoteCache<String, String> cache; public String greet(String user) { String cachedValue = cache.get(user); if (cachedValue == null) { cachedValue = "Hello " + user; cache.put(user, cachedValue); } return cachedValue; } }
@Inject @Remote("greetingCache") private RemoteCache<String, String> cache;
import javax.enterprise.context.ApplicationScoped; public class Config { @RemoteGreetingCache @Produces @ApplicationScoped 1 public ConfigurationBuilder builder = new ConfigurationBuilder(); 2 builder.addServer().host("localhost").port(11222); return new RemoteCacheManager(builder.build()); } }
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.2" bean-discovery-mode="annotated"> <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>
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd" version="1.2" bean-discovery-mode="annotated"> <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>
import javax.cache.interceptor.CacheResult; public class GreetingService { @CacheResult public String greet(String user) { return "Hello" + user; } }
@CacheResult(cacheName = "greeting-cache")
import javax.enterprise.event.Observes; import org.infinispan.notifications.cachemanagerlistener.event.CacheStartedEvent; import org.infinispan.notifications.cachelistener.event.*; public class GreetingService { // Cache level events private void entryRemovedFromCache(@Observes CacheEntryCreatedEvent event) { } // Cache manager level events private void cacheStarted(@Observes CacheStartedEvent event) { } }