Developing applications with Infinispan in Library Mode

In this tutorial we want to give some guidelines on developing applications with Infinispan or the supported version named JBoss Data Grid.

First of all, make a bookmark on the following page which contains the demo quickstart applications, configured to run on JBoss Data Grid: https://github.com/jboss-developer/jboss-jdg-quickstarts

The main difference, if you want to run the above examples on the upstream project (Infinispan) is that you need replacing JDG dependencies with Infinispan core libraries.

Before beginning let’s make a distinction between the two different usage modes:

Infinispan modes

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 DataGrid 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

 

Let’s see of coding an example of Library mode. (If you want an example of a Client-Server application take a look at the following tutorial: Infinispan 8 tutorial )

Developing an applicaiton in Library Mode 

The core part of it is the LocalCacheContainerProvider which defines the CacheContainer configuration programmatically:

 
package com.demo.infinispan.cache;
 
import javax.annotation.PreDestroy;
import javax.enterprise.context.ApplicationScoped;
import org.infinispan.commons.api.BasicCacheContainer;
import org.infinispan.configuration.cache.CacheMode;
import org.infinispan.configuration.cache.Configuration;
import org.infinispan.configuration.cache.ConfigurationBuilder;
import org.infinispan.configuration.global.GlobalConfiguration;
import org.infinispan.configuration.global.GlobalConfigurationBuilder;
import org.infinispan.manager.DefaultCacheManager;
import org.infinispan.util.concurrent.IsolationLevel;
 
 
@ApplicationScoped
public class LocalCacheContainerProvider   {
    

    private BasicCacheContainer manager;

    public BasicCacheContainer getCacheContainer() {
        if (manager == null) {
            GlobalConfiguration glob = new GlobalConfigurationBuilder()
                .nonClusteredDefault()  
                .globalJmxStatistics().enable()  
                .build();  
            Configuration loc = new ConfigurationBuilder()
                .jmxStatistics().enable()  
                .clustering().cacheMode(CacheMode.LOCAL)  
                .locking().isolationLevel(IsolationLevel.REPEATABLE_READ)  
                .persistence().passivation(false).addSingleFileStore().purgeOnStartup(true)  
                .build(); //Builds the Configuration object
            manager = new DefaultCacheManager(glob, loc, true);
           System.out.println("Created DefaultCacheManager using library mode");
        }
        return manager;
    }

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

This CDI class is used to produce a BasicCacheContainer based on a Local Cache mode. For Clustered Cache Containers you can use as cacheMode one of the available modes (Replication/Distribution):

Configuration config = new ConfigurationBuilder()
.clustering().cacheMode(CacheMode.REPL_SYNC)
.build();

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

package com.demo.infinispan.manager;

import org.infinispan.commons.api.BasicCache;

import com.demo.infinispan.cache.LocalCacheContainerProvider;
import com.demo.infinispan.model.Item;

import javax.enterprise.inject.Model;
import javax.inject.Inject;

import java.util.ArrayList;

import java.util.List;

@Model
public class Manager {
	public static final String CACHE_NAME = "itemcache";

	@Inject
	private LocalCacheContainerProvider cacheProvider;

	private BasicCache<String, Item> cache;

	private String key;
	private String value;

	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;
	}

	public Manager() {
	}

	public String save() {
		cache = cacheProvider.getCacheContainer().getCache(CACHE_NAME);
		Item item = new Item();
		item.setKey(key);
		item.setValue(value);
		cache.put(item.getKey(), item);
		return "home";
	}

	public List getCacheList() {
		List<Item> dataList = new ArrayList<Item>();
		if (cache != null)
			dataList.addAll(cache.values());
		return dataList;

	}

	public void removeItem(String key) {
		cache = cacheProvider.getCacheContainer().getCache(CACHE_NAME);
		cache.remove(key);
	}

	public void clear() {
		cache = cacheProvider.getCacheContainer().getCache(CACHE_NAME);
		cache.clear();
	}

}

Completing the application is 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>DataGrid 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>

And here is the application in action:

infinispan tutorial

You can find the full project here: https://github.com/fmarchioni/mastertheboss/tree/master/infinispan-demo

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-8.2" services="export"/>
      </dependencies>
   </deployment>
</jboss-deployment-structure>

(Please notice that for JDG, the slot name is “jdg-6.3”)

Found the article helpful? if so please follow us on Socials