Spring Boot Remote Caching

What You Will Learn

How to use Spring Boot’s @EnableCaching with the Infinispan Spring Boot starter to cache and evict data stored in a remote Infinispan Server, using Protobuf serialization.

Prerequisites

  • Java 17+

  • Spring Boot

  • An Infinispan Server running on localhost:11222

Step 1: Add Dependencies

Add the Infinispan Spring Boot remote starter and the ProtoStream processor:

<dependency>
   <groupId>org.infinispan</groupId>
   <artifactId>infinispan-spring-boot4-starter-remote</artifactId>
</dependency>
<dependency>
   <groupId>org.infinispan.protostream</groupId>
   <artifactId>protostream-processor</artifactId>
</dependency>

Step 2: Configure the Connection

In application.properties, point the starter to your Infinispan Server:

infinispan.remote.server-list=127.0.0.1:11222
# activates statistics for actuator
infinispan.remote.statistics=true
infinispan.remote.jmx=true

management.endpoints.web.exposure.include=*

# Security settings. Comment these properties if you are using a non secured server
infinispan.remote.auth-username=admin
infinispan.remote.auth-password=password

Step 3: Define a Protobuf Entity

Use the @Proto annotation to define a cacheable record that will be serialized with Protobuf:

@Proto
public record BasqueName(String id, String name) {}

Step 4: Use @Cacheable and @CacheEvict

Annotate repository methods to cache lookups and evict on removal:

@Component
@CacheConfig(cacheNames = Data.BASQUE_NAMES_CACHE)
public class BasqueNamesRepository {

   private static final Logger logger = Logger.getLogger(MethodHandles.lookup().lookupClass().getName());
   private Map<String, BasqueName> database = new HashMap<>();

   @Cacheable
   public BasqueName findById(String id) {
      logger.info("Call database to FIND name by id '" + id + "'");
      return database.get(id);
   }

   public void create(String id, String name) {
      logger.info("Call database to CREATE name by id '" + id + "'");
      database.put(id, new BasqueName(id, name));
   }

   @CacheEvict
   public void removeById(String id) {
      logger.info("Call database to REMOVE name by id '" + id + "'");
      database.remove(id);
   }

   public int size() {
      return database.size();
   }

}

Step 5: Configure the Remote Cache

Use an InfinispanRemoteCacheCustomizer bean to configure the remote cache and register the Protobuf schema:

@Configuration
public class InfinispanConfiguration {

   @Bean
   @Order(Ordered.HIGHEST_PRECEDENCE)
   public InfinispanRemoteCacheCustomizer caches() {
      return b -> {
         URI cacheConfigUri;
         try {
            cacheConfigUri = this.getClass().getClassLoader().getResource("basquesNamesCache.xml").toURI();
         } catch (URISyntaxException e) {
            throw new RuntimeException(e);
         }

         b.remoteCache(Data.BASQUE_NAMES_CACHE)
                 .configurationURI(cacheConfigUri);

         b.remoteCache(Data.BASQUE_NAMES_CACHE).marshaller(ProtoStreamMarshaller.class);

         // Add marshaller in the client, the class is generated from the interface in compile time
         b.addContextInitializer(new BasquesNamesSchemaBuilderImpl());
      };
   }
}

Step 6: Run the Tutorial

mvn spring-boot:run

The application periodically creates, reads, and removes entries. Watch the logs to see cache hits (no "Call database" message) versus cache misses (with the message).

What’s Next