Hibernate L2 Cache with WildFly

What You Will Learn

How to use Infinispan as the built-in Hibernate L2 cache provider in WildFly, exposed through JAX-RS REST endpoints that step through cache operations one by one.

Prerequisites

  • Java 8+

  • WildFly application server

Step 1: Configure the Persistence Unit

WildFly ships with Infinispan as its default Hibernate cache provider. Configure META-INF/persistence.xml to use the WildFly JTA datasource and enable caching:

   <persistence-unit name="events">
      <jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
      <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
      <properties>
         <!-- Create/drop database in each run -->
         <property name="hibernate.hbm2ddl.auto" value="create-drop" />
         <property name="hibernate.show_sql" value="false" />

         <!-- Enables second level cache -->
         <property name="hibernate.cache.use_second_level_cache" value="true"/>
         <!-- Enable query cache -->
         <property name="hibernate.cache.use_query_cache" value="true"/>

         <!-- Generate statistics to see effects of second level cache -->
         <property name="hibernate.generate_statistics" value="true" />

         <!-- Entity specific configuration, e.g. via property:
            hibernate.cache.infinispan.<WAR/EAR name>#<PersistenceManager Unit name>.<Entity FQN>.expiration.max_idle
         -->
         <property name="hibernate.cache.infinispan.wildfly-local.war#events.org.infinispan.tutorial.simple.hibernate.cache.wildfly.local.model.Person.expiration.max_idle"
                   value= "1000"/>
      </properties>
   </persistence-unit>

Step 2: Create the Persistence Manager EJB

A stateless EJB handles entity operations within JTA transactions:

@Stateless
@Interceptors(ClearStatistics.class)
public class PersistenceManager {

   @Inject
   private EntityManager em;

   public void persistEntities() {
      em.persist(new Event("Caught a pokemon!"));
      em.persist(new Event("Hatched an egg"));
      em.persist(new Event("Became a gym leader"));
   }

   public void findEntity(long id, StringBuilder out) {
      Event event = em.find(Event.class, id);
      out.append(String.format("Found entity: %s%n", event));
   }

Step 3: Expose Cache Steps as JAX-RS Endpoints

The REST resource exposes each cache operation as a separate GET endpoint:

@Path("/")
public class InfinispanHibernateCacheWildflyLocal {

   public static final String EVENT_REGION_NAME = "wildfly-local.war#events." + Event.class.getName();
   public static final String PERSON_REGION_NAME = "wildfly-local.war#events." + Person.class.getName();

   @Inject
   private Logger log;

   @Inject
   private EntityManager em;

   @Inject
   private PersistenceManager ejb;

   @GET
   @Path("/hibernate-cache/1")
   @Produces("application/json")
   public String step1_persistEntities() {
      // Persist 3 entities, stats should show 3 second level cache puts
      ejb.persistEntities();
      SecondLevelCacheStatistics eventCacheStats = getCacheStatistics(EVENT_REGION_NAME);
      return printfAssert("Event entity cache puts: %d (expected %d)%n", eventCacheStats.getPutCount(), 3);
   }

Step 4: Run the Tutorial

Build and deploy the WAR to a running WildFly instance:

mvn clean package wildfly:deploy

Then call each step in sequence:

for i in {1..13}; do
  curl http://localhost:8080/wildfly-local/infinispan/hibernate-cache/$i
done

Each endpoint returns the cache statistics for that step, showing puts, hits, misses, and query cache behavior.

What’s Next