Use infinispan in JAVA

Amanbhala
5 min readJun 25, 2022

Infinispan is an open-source in-memory data grid that offers flexible deployment options and robust capabilities for storing, managing, and processing data. Infinispan provides a key/value data store that can hold all types of data, from Java objects to plain text. Infinispan distributes your data across elastically scalable clusters to guarantee high availability and fault tolerance, whether you use Infinispan as a volatile cache or a persistent data store.

Features:

Interoperability

Access data across multiple protocols and programming languages.

Resilient and Fault Tolerant Data

Ensure data is always available to meet demanding workloads.

ACID Transactions

Guarantee that data is always valid and consistent.

Clustered Processing

Process data in real-time without burdening resources.

Queries

Perform simple, accurate, and fast searches across distributed data sets.

How to use Infinispan:

import org.infinispan.client.hotrod.RemoteCache;import org.infinispan.client.hotrod.RemoteCacheManager;import org.springframework.beans.factory.annotation.Autowired;//Cache class
@Component
public class Cache {
//Cache name
private final String CACHE_NAME = "your_cache_name";
//Autowiring RemoteCacheManager object
@Autowired
private RemoteCacheManager remoteCacheManager;
//Cache implementation thorugh RemoteCache object
private RemoteCache<Integer, Integer> cache;
RemoteCache<Integer, Double> getCache() { if ( cache == null ) {
cache = remoteCacheManager.getCache(CACHE_NAME);
}
return cache;
}
public void put(Integer digit, Integervalue){
getCache().put(digit, value);
}
public Object get(Integer digit){
Object value = getCache().get(digit);
return value;
}
public void delete(Integer digit){
getCache().remove(digit);
}
public Integer length() {
return getCache().size();
}
}

RemoteCacheManager is factory for RemoteCaches while RemoteCache provides remote reference to a Hot Rod server/cluster. It implements Cache interface.

In order to be able to use a RemoteCache, the RemoteCacheManager must be started first: this instantiates connections to Hot Rod server(s). When your apllication starts up spring boot will create a RemoteCacheManager bean which will create TCP connections to the hotrod server that you provide in the application.properties file

NOTE: this is an “expensive” object, as it manages a set of persistent TCP connections to the Hot Rod servers. It is recommended to only have one instance of this per JVM, and to cache it between calls to the server (i.e. remoteCache operations).

In the application.properties file or application.yaml file set properties related to infinispan like server url. You can follow this doc for full set of properties. Example:

## infinispan hotrod remote cache settings, details: https://infinispan.org/docs/dev/titles/spring_boot/starter.htmlinfinispan.remote.server-list= ""## timeout values in millisecondsinfinispan.remote.connect-timeout= 500## setup serializationinfinispan.remote.marshaller= org.infinispan.commons.marshall.JavaSerializationMarshaller# Client intelligenceinfinispan.remote.client_intelligence=""# Authenticationinfinispan.remote.use_auth=trueinfinispan.remote.auth_realm=defaultinfinispan.remote.auth_server_name=infinispaninfinispan.remote.auth_username=""infinispan.remote.auth_password=""

There is also another way in which you can use infinispan in spring boot using spring boot annotations.

If we use Spring Boot, then we can utilize the spring-boot-starter-cache starter package to easily add the caching dependencies:

<dependency>     
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
<version>2.4.0</version>
</dependency>

Under the hood, the starter brings the spring-context-support module.

We can enable the caching feature simply by adding the @EnableCaching annotation to any of the configuration classes or MainApplication class:

@SpringBootApplication
@EnableCaching
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}

You can define your cache class like this:

import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class Cache {
//This HashMap will be the local cache which will mimic the actual //cache in infinispan server that we will use to put, get and delete //values
private Map<String, Integer> cacheMap = new ConcurrentHashMap();
private final String CACHE_NAME = "your_cache_name";

@CachePut(value = CACHE_NAME, key = "#string_value")
public Integer put(String string_value, Integer integer_value){
cacheMap.put(string_value, integer_value);
return integer_value;
}

@Cacheable(value = CACHE_NAME, key = "#string_value")
public Integer get(String string_value){
Integer integer_value = cacheMap.get(string_value);
return integer_value;
}

@CacheEvict(value = CACHE_NAME, key = "#string_value")
public void evict(String string_value){
Integer integer_value = cacheMap.remove(string_value);
}

}

In this case we have used spring boot annotations:

  • CachePut: If a method or multiple mehods in a class are annotated with this annotation then whenever those methods are called then cache put method of Cache interface is called which will associate the specified value with the specified key in this cache
  • Cacheable: We can enable caching behavior for a method by annotating it with @Cacheable, and parameterize it with the name of the cache where the results would be stored as done above.
  • CacheEvict: This is used to indicate the removal of one or more/all values so that fresh values can be loaded into the cache again.

The difference between @Cacheable and @CachePut is that @Cacheable will skip running the method, whereas @CachePut will actually run the method and then put its results in the cache because of this only we have annotated the put method with CachePut so that whenever we call the put method it will execute the function and put the key:value par in the cache while get method is annotated with Cacheable and the get() call will first check the cache address before actually invoking the method and then caching the result.

Similar to above specify infinispan server url and other properties in your application.properties or application.yaml file

There is just a small issue when we use these annotations which is when we use @CacheEvict and we have set some cache settings for infinispan cache like max-idle( to specify the amount of time, in milliseconds, that entries can remain idle after last access) or lifespan(to specify the amount of time, in milliseconds, that entries can stay in the cache), you can look at the docs and based on the time set infinispan server removes the value from cache after lifespan but that value will still be present in our local cache that is our cacheMap and you can verify that by printing the size of our cacheMap. It happens because whenever some value is removed from the cache by infinispan then there is no way for our local cache to know that and therefore it keeps that value in cacheMap. Method annotated with @CacheEvict annotation will not be executed when infinispan removes some value and therefore our cacheMap size will keep on increasing so if you have a use case where you know that cacheMap size is not going to increase rapidly then you can move ahead with second implementation otherwise you might get JVM OOM error. A better approach of implementing infinispan cache would be to use RemoteCacheManager object which whenever called will make a call to the hotrod server and get the cache maintained by the infinispan server.

--

--