Using CDI to Access Infinispan
Join the DZone community and get the full member experience.
Join For Free
DZone: Could you please introduce Infinispan?
Peter Muir/Kevin Pollet: Infinispan,
from JBoss, is an extremely scalable, highly available data grid
platform - 100% open source, and written in Java. The purpose of
Infinispan is to expose a data structure that is highly concurrent,
designed ground-up to make the most of modern multi-processor/multi-core
architectures while at the same time providing distributed cache
capabilities. At its core Infinispan exposes a JSR-107 (JCACHE)
compatible Cache interface (which in turn extends java.util.Map). It is
also optionally is backed by a peer-to-peer network architecture to
distribute state efficiently around a data grid.
Offering high
availability via making replicas of state across a network as well as
optionally persisting state to configurable cache stores, Infinispan
offers enterprise features such as efficient eviction algorithms to
control memory usage as well as JTA compatibility.
In addition to
the peer-to-peer architecture of Infinispan, on the roadmap is the
ability to run farms of Infinispan instances as servers and connecting
to them using a plethora of clients - both written in Java as well as
other popular platforms.
DZone: Could you explain what CDI is and why it's important?
Peter Muir/Kevin Pollet: CDI
provides a powerful, consistent programming built into the core of Java
EE (version 6 onwards). It offers type safe injection, loose coupling
via AOP (interceptors and decorators) and events, and extreme
extensibility. CDI offers tight integration with Java EE technologies
(such as JAX-RS and JPA), and, via extensions, with other projects such
as Wicket and GWT (via JBoss’ Errai).
Java EE 7 aims to bring
excellent CDI integration for other specifications (such as JCache, the
new caching standard, and JMS 2). The community is also forging ahead,
and soon you can expect to see excellent OSGi support for Weld (the RI
of CDI), CDI built right into the core of JBoss’ next generation ESB.
Other projects such as Apache MyFaces CODI have been working hard to
provide additional JSF and Bean Validation integrations.
CDI is
aimed to offer excellent productivity for developers. Eclipse (via JBoss
Tools), IDEA and NetBeans all offer great support for CDI, and the new
JBoss project, Forge, offers scaffolding. And of course, we can’t forget
testing! You can easily unit your CDI beans using mocks, but we are
strong believers in integration testing, and have been working hard on
the Arquillian project to make it just as easy to test in an application
server as it is to unit test.
Whilst CDI is required for Java
EE, both JBoss and Apache offer support for CDI on servlet containers
(such as Jetty and Tomcat) as well as plain old Java SE.
DZone: Why has Infinispan brought in integration with CDI? What are the benefits?
Peter Muir/Kevin Pollet: Caching
is a essential part of an application architecture - Infinispan is a
great choice for this; meanwhile CDI offers excellent developer
productivity. The benefits are many, for example you can inject a cache
into any bean managed by CDI (such as EJBs, Servlets and managed beans)
by using the @Inject annotation (and all in a typesafe approach!).
Another benefit is that all cache configurations of the entire
application can be gathered together into a single Configuration class.
DZone: How does this integrate with the work you're doing on JSR 107?
Peter Muir/Kevin Pollet: JCache
(aka JSR-107) defines a standard caching API to work with a standalone
cache, as well as a distributed cache. An interesting part of the
specification are the annotations designed to solve common caching use
cases. The Infinispan CDI extension adds support for these annotations.
DZone: How can I get CDI working with Infinispan? Which version should I use? What configuration is involved?
Peter Muir/Kevin Pollet: The
CDI module is available since Infinispan 5.0 (Pagoa). To get this
extension working add the following dependency and create a beans.xml
file in your application (like any CDI applications).
<dependency> <groupId>org.infinispan</groupId> <artifactId>infinispan-cdi</artifactId> <version>${infinispan.version}</version> </dependency>
If you want to use the JCache annotations support you need
to enable the CDI interceptors (provided by this module) in your
beans.xml. More information here.
DZone: Can you give an example of how caching annotations help developers?
Peter Muir/Kevin Pollet: Here's an example without caching annotations:
public class UserDAO { private Cache<Long, User> cache; public User findUser(long id){ User user = cache.get(id); if ( user == null ) { user = …; // retrieve the user with the given id user.put(id, user); } return user; } public void storeUser(long id, User user){ // store the user with the given id // ... cache.put(id, user); } public void removeUser(long id){ // remove the user with the given id // ... cache.remove(id); } public void removeAllUser(){ // remove all user // ... cache.clear(); } }
The following DAO uses some of the caching annotations defined by JCache specification and has exactly the same behavior.
… import javax.cache.interceptor.CacheResult; import javax.cache.interceptor.CachePut; import javax.cache.interceptor.CacheValue; import javax.cache.interceptor.CacheRemoveEntry; import javax.cache.interceptor.CacheRemoveAll; public class UserDAO { // When this method is called: // - If the user with the given id is not in the cache, the method result is cached // - If an user with the given id is found in the cache, the intercepted method is not called and the cached // result is returned. @CacheResult(cacheName="user-cache") public User findUser(long id) { User user = …; // retrieve the user with the given id return user; } // When this method is called the given user is cached with the given id as key. In all cases the intercepted method // is called. @CachePut(cacheName="user-cache") public void storeUser(long id, @CacheValue User user){ // store the user with the given id // ... } // When this method is called, the user with the given id will be removed from the cache. In all cases the intercepted // method is called. @CacheRemoveEntry(cacheName="user-cache") public void removeUser(long id){ // remove the user with the given id // ... } // When this method is called, all entries in the cache will be removed. In all cases the intercepted // method is called. @CacheRemoveAll(cacheName="user-cache") public void removeAllUser(){ // remove all user // ... } }
By using the annotations, we’ve managed to split out
orthogonal concerns - the business logic, and the fact it needs caching,
resulting in cleaner, more maintainable code.
DZone: What are your plans for the future?
Peter Muir/Kevin Pollet: We’re
aiming to provide preview support of JCache in Infinispan 5.2, as a
separate module. This will allow early adopters to try out JCache
straight away. We’re then planning to provide native JCache support in
the Infinispan core for Infinispan 6.
Also, you can expect to see some pretty nice demos of CDI with Infinispan coming soon!
Opinions expressed by DZone contributors are their own.
Comments