Using Infinispan with WildFly

User Rating: 4 / 5

Star ActiveStar ActiveStar ActiveStar ActiveStar Inactive
 

Today I'm going to test Infinispan cache from within the lastest release of Wildfly. Let's see what happens!

The first obvious thing we need to check is how the new release of the application server defines the infinispan subsystem. As you can see from the following snippet, the subsystem has upgraded to the version 4.0 which includes for the standalone server configuration just a pair of caches (the web and the hibernate cache) while the ha configurations ship with some additional cache containers (server and ejb):

  <cache-container name="server" aliases="singleton cluster" default-cache="default" module="org.wildfly.clustering.server">
        <transport lock-timeout="60000"/>
        <replicated-cache name="default" mode="SYNC">
            <transaction mode="BATCH"/>
        </replicated-cache>
    </cache-container>
    <cache-container name="web" default-cache="dist" module="org.wildfly.clustering.web.infinispan">
        <transport lock-timeout="60000"/>
        <distributed-cache name="dist" mode="ASYNC" l1-lifespan="0" owners="2">
            <locking isolation="REPEATABLE_READ"/>
            <transaction mode="BATCH"/>
            <file-store/>
        </distributed-cache>
        <distributed-cache name="concurrent" mode="SYNC" l1-lifespan="0" owners="2">
            <file-store/>
        </distributed-cache>
    </cache-container>
    <cache-container name="ejb" aliases="sfsb" default-cache="dist" module="org.wildfly.clustering.ejb.infinispan">
        <transport lock-timeout="60000"/>
        <distributed-cache name="dist" mode="ASYNC" l1-lifespan="0" owners="2">
            <locking isolation="REPEATABLE_READ"/>
            <transaction mode="BATCH"/>
            <file-store/>
        </distributed-cache>
    </cache-container>
    <cache-container name="hibernate" default-cache="local-query" module="org.hibernate.infinispan">
        <transport lock-timeout="60000"/>
        <local-cache name="local-query">
            <eviction strategy="LRU" max-entries="10000"/>
            <expiration max-idle="100000"/>
        </local-cache>
        <invalidation-cache name="entity" mode="SYNC">
            <transaction mode="NON_XA"/>
            <eviction strategy="LRU" max-entries="10000"/>
            <expiration max-idle="100000"/>
        </invalidation-cache>
        <replicated-cache name="timestamps" mode="ASYNC"/>
    </cache-container>

Besides the upgraded subsystem, the most relevant change is that Infinispan has now deprecated the EAGER cache start mode, therefore the only accepted start mode is now lazy. This can have some impact on your applications, in particular if you are relying on CDI to produce the org.infinispan.Cache as a resource. Let's see how you lookup the following custom  Cache which you have defined in your HA profile:

<cache-container name="replicated_cache" default-cache="default" module="org.wildfly.clustering.server" jndi-name="infinispan/replicated_cache">
        <transport lock-timeout="60000"/>
        <replicated-cache name="mycache" jndi-name="infinispan/replicated_cache/mycache" mode="SYNC">
            <transaction locking="OPTIMISTIC" mode="FULL_XA"/>
            <eviction strategy="NONE"/>
        </replicated-cache>
</cache-container>

Case 1: Accessing Infinispan Cache from EJB Applications

Using a custom Cache by means of an EJB class which works as wrapper is the simplest case. All you need is adding an appropriate Resource annotation which refers to our Cache and create a getter method for it:

package com.sample;

import javax.annotation.Resource;
import javax.ejb.Stateless;
import org.infinispan.Cache;

@Stateless
public class ApplicationEJB {
	 
    @Resource(lookup = "java:jboss/infinispan/replicated_cache/mycache")   
    private Cache  cache;
	
    public Cache getCache() {
		return cache;
    }
	 
}

You can then inject your EJB in any other Container resource and use it to manage your cache:

@EJB ApplicationEJB ejb;

As a side note, besides accessing the org.infinispan.Cache resource directly, you can also access it indirectly through the CacheContainer which hosts the Cache:

@Resource(lookup="java:jboss/infinispan/replicated_cache")
private org.infinispan.manager.CacheContainer container;

Case 2: Injecting Infinispan Cache from CDI

Another approach which is more elegant is using a Producer method in an ApplicationScoped class to Produce the org.infinispan.Cache:

package com.sample;

import javax.annotation.Resource;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import org.infinispan.Cache;

 
@ApplicationScoped
public class ApplicationBean {
 
   @Produces
   @Resource(name="myCache") 
   private Cache  cache;
 
}

As you can see, we had to specify a reference to our real JNDI name. Why this ? Because lookup through CDI beans result in the @Resource annotation being processed by Weld rather than the EE subsystem (see this thread abut it: https://developer.jboss.org/thread/272391 ). As we have specified a reference to the real JNDI name, we need to use a standard descriptor to solve the binding. For example, within the web.xml file you could specify:

<web-app version="3.1" 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/web-app_3_1.xsd">
 
   <resource-ref>  
        <res-ref-name>myCache</res-ref-name>  
        <lookup-name>java:jboss/infinispan/replicated_cache/mycache</lookup-name>  
   </resource-ref>

</web-app>

Now the beauty of CDI lets you inject your Cache directly in any Java EE context:

@Inject Cache cache

Compile and Deploy

You can compile the above class by adding the required Maven dependency to your Maven project:

<dependency>
  <groupId>org.infinispan</groupId>
  <artifactId>infinispan-core</artifactId>
  <version>8.2.4.Final</version>
</dependency>
<dependency>
    <groupId>org.infinispan</groupId>
    <artifactId>infinispan-commons</artifactId>
    <version>8.2.4.Final</version>
</dependency>

In order to get working with your Infinispan cache on Wildfly is triggering Infinispan dependencies, either using in your META-INF/MANIFEST.MF or jboss-deployment-structure.xml as follows:

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <deployment>
     <dependencies>
       <module name="org.infinispan" services="export"/>  
       <module name="org.infinispan.commons" services="export"/>  
    </dependencis>
  </deployment>
</jboss-deployment-structure>

As you can see from the above jboss-deployment-structure.xml, we needed also to include a dependency to org.infinispan.commons: this is why, since Infinispan 7 some of the core classes have been moved to the module org.infinispan.commons.

...or if you are using Maven:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-ejb-plugin</artifactId>
  <version>2.3</version>
    <configuration>
      <archive>
        <manifestEntries>
          <Dependencies>org.infinispan org.infinispan.commons export</Dependencies>
        </manifestEntries> 
       </archive>
 . . . .
     </configuration>
</plugin>

That's all! enjoy using Wildfly  and Infinispan!

Follow us on Twitter