Using Infinispan with WildFly

The Infinispan subsystem provides caching support for HA services in the form of Infinispan caches such as high-performance, transactional caches which can operate in both non-distributed and distributed scenarios. WildFly application server ships with the Infinispan subsystem, however, it is recommended not to use the application server cache definition as repository for your Cache. This tutorial shows the available options for using Infinispan in an Enterprise application deployed on WildFly or any Java EE container.

As said, you are adviced not to use WildFly’s Infinispan Caches for application purpose as they are internally used for managing the application’s server own Caches. So which are our options? You can use these two patterns:

Library mode – When running in this mode, you have to provide all the binaries required to build and run your Cache. You can do it in two ways: either embedding the libraries in your application or installing the modules into the application server. This usage mode gives access to advanced functionalities such as Transactional support, Listeners and Interceptors, Batching, Lucene-based queries and index, Distributed execution framework via Map-Reduce.

Client-server mode: When running in this mode applications can remotely access the data grid server using Hot Rod, memcached or REST client APIs. You have to bundle a minimal set of API to connect to the Infinispan Server and this additional layer can provide you some benefits such as Connection pooling with cache stores, multiple interfaces (memcached, Hotrod, REST), authentication and encrypytion and cluster Rolling upgrades (without bringing the cluster down).

infinispan tutorial

In the following tutorial we have described how to use a remote Infinispan Server through the Hot Rod protocol: Connecting to a Remote Infinispan Server using Hot Rod

Now we will learn how to code an application in Library mode.

Deploy and application on WildFly in Library Mode

The core part of it is the MyCacheManagerProvider which defines a DefaultCacheManager using the “jgroups-udp.xml” configuration based on a Clustered Synchronous Cache that uses Distribution as Cache mode:

 
package com.mastertheboss.producer;

import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.cache.CacheMode;

@ApplicationScoped
public class MyCacheManagerProvider {

	private static final long ENTRY_LIFESPAN = 60 * 1000; // 60 seconds


	private DefaultCacheManager manager;

	public DefaultCacheManager getCacheManager() {
		if (manager == null) {

			GlobalConfiguration glob = new GlobalConfigurationBuilder().clusteredDefault() 
					.transport().addProperty("configurationFile", "jgroups-udp.xml")  
					.globalJmxStatistics().allowDuplicateDomains(true).enable() 
					.build();  
			Configuration loc = new ConfigurationBuilder().jmxStatistics().enable()  
					.clustering().cacheMode(CacheMode.DIST_SYNC)  
					.hash().numOwners(2)  
					.expiration().lifespan(ENTRY_LIFESPAN)  
					.build();
			manager = new DefaultCacheManager(glob, loc, true);
		}
		return manager;
	}

	@PreDestroy
	public void cleanUp() {
		manager.stop();
		manager = null;
	}

}


The above Cache is configure to expire its entries after 60 seconds.

In order to make available the DefaultCacheManager, we will create a producer Class that gets injected the MyCacheManagerProvider:

 
package com.mastertheboss.producer;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import org.infinispan.manager.DefaultCacheManager;
 

@ApplicationScoped
public class ApplicationBean {
  
 
    @Inject
    MyCacheManagerProvider cacheManagerProvider;

    @Produces
    DefaultCacheManager getDefaultCacheManager() {
        return cacheManagerProvider.getCacheManager();
    }
}

The class which manages your Cache is the following Manager class that contains some basic methods for adding or cleaning the cache:

package com.mastertheboss.service;

import java.util.ArrayList;
import java.util.List;
import javax.enterprise.inject.Model;
import javax.inject.Inject;

import org.infinispan.Cache;
import org.infinispan.manager.DefaultCacheManager;
import com.mastertheboss.model.Item;

@Model
public class Manager {

	@Inject  
	DefaultCacheManager cacheManager;

	private String key;
	private String value;

	public Manager() {
	}

	public String save() {
		Cache<String, Item> cache = cacheManager.getCache();
		Item item = new Item();
		item.setKey(key);
		item.setValue(value);
		cache.put(item.getKey(), item);
		return "home";
	}

	public List getCacheList() {
		Cache<String, Item> cache = cacheManager.getCache();
		List list = new ArrayList();
		cache.entrySet().forEach(entry -> list.add(entry.getValue()));
		return list;

	}

	public void removeItem(String key) {
		Cache<String, Item> cache = cacheManager.getCache();   
		cache.remove(key);
	}

	public void clear() {
		Cache<String, Item> cache = cacheManager.getCache();
		cache.clear();
	}
	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getValue() {
		return value;
	}

	public void setValue(String value) {
		this.value = value;
	}
}

In order to complete the application, a simple xhtml page which displays data and let add new Items:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head>

</h:head>
<h:body>
	<h2>Infinispan Demo - Library Mode</h2>
	<h:form id="jsfexample">
		<h:panelGrid columns="2" styleClass="default">

			<h:outputText value="Enter key:" />
			<h:inputText value="#{manager.key}" />

			<h:outputText value="Enter value:" />
			<h:inputText value="#{manager.value}" />

			<h:commandButton actionListener="#{manager.save}"
				styleClass="buttons" value="Save key/value" />
			<h:commandButton actionListener="#{manager.clear}"
				styleClass="buttons" value="Clear cache" />

			<h:messages />


		</h:panelGrid>


		<h:dataTable value="#{manager.cacheList}" var="item"
			styleClass="table" headerClass="table-header"
			rowClasses="table-odd-row,table-even-row">
			<h:column>
				<f:facet name="header">Key</f:facet>
				<h:outputText value="#{item.key}" />
			</h:column>
			<h:column>
				<f:facet name="header">Value</f:facet>
				<h:outputText value="#{item.value}" />
			</h:column>
		</h:dataTable>
	</h:form>
</h:body>
</html>

Finally, if we want to package our application and deploy it on WildFly, we need to specify in our pom.xml that Infinispan libraries are NOT provided so they will be packaged in our Web application. Here is the pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.mastertheboss</groupId>
	<artifactId>infinispan-wildfly-library</artifactId>

	<version>1.0</version>

	<packaging>war</packaging>
	<name>Quickstart: Infinispan-WildFly</name>

	<licenses>
		<license>
			<name>Apache License, Version 2.0</name>
			<url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
			<distribution>repo</distribution>
		</license>
	</licenses>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<maven.compiler.source>1.8</maven.compiler.source>
		<maven.compiler.target>1.8</maven.compiler.target>
		<infinispan.version>9.4.5.Final</infinispan.version>
		<version.server.bom>15.0.0.Final</version.server.bom>
	</properties>
	<dependencyManagement>
		<dependencies>

			<dependency>
				<groupId>org.wildfly.bom</groupId>
				<artifactId>wildfly-javaee8-with-tools</artifactId>
				<version>${version.server.bom}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>

		</dependencies>
	</dependencyManagement>
	<dependencies>
		<dependency>
			<groupId>javax.enterprise</groupId>
			<artifactId>cdi-api</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.spec.javax.annotation</groupId>
			<artifactId>jboss-annotations-api_1.3_spec</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.jboss.spec.javax.ejb</groupId>
			<artifactId>jboss-ejb-api_3.2_spec</artifactId>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>org.infinispan</groupId>
			<artifactId>infinispan-core</artifactId>
			<version>${infinispan.version}</version>
		</dependency>
		<dependency>
			<groupId>org.infinispan</groupId>
			<artifactId>infinispan-commons</artifactId>
			<version>${infinispan.version}</version>
		</dependency>
	</dependencies>
	
	<build>
		<finalName>${project.artifactId}</finalName>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<failOnMissingWebXml>false</failOnMissingWebXml>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

And here is the application in action:

infinispan tutorial

You can check the source code for this tutorial on: https://github.com/fmarchioni/mastertheboss/tree/master/infinispan/infinispan-wildfly-library

Two options to deploy applications in library mode

The example discussed here bundles the infinispan libraries with your application. Another option for deploying applications in library mode is to install the Infinispan data Grid/JDG Modules in the WildFly/JBoss EAP application server. The Infinispan modules are available here: http://infinispan.org/download/ (Click on WildFly/EAP Modules)

To install the modules in JBoss EAP/WildFly, unzip the modules in the application server home directory. The user application needs to include dependencies on these modules via jboss-deployment-structure.xml file.

<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
   <deployment>
      <dependencies>
         <module name="org.infinispan" slot="ispn-9.4" services="export"/>
      </dependencies>
   </deployment>
</jboss-deployment-structure>
Found the article helpful? if so please follow us on Socials