36 Using JCache Events

You can create and register event listeners to handle JCache events.

The JCache event model is defined in the javax.cache.event package and described in chapter 8 of the Java Caching API Specification .

This chapter includes the following sections:

36.1 Overview of Using JCache Events

The JCache event model allows applications to receive and process events that represent observable changes to the entries in a cache. The event model uses standard Java event and event listener conventions that are common in Java applications.

A JCache event is defined in the CacheEntryEvent class and is a standard Java event that is specific to cache entries. JCache defines four event types for cache entries:

  • CREATED – Indicates that the cache entry was created

  • UPDATED – Indicates that the cache entry was updated

  • REMOVED – Indicates that the cache entry was removed

  • EXPIRED – Indicates that the cache entry has expired

The JCache event model uses event listeners to handle events and perform any necessary event processing. Each event type has a corresponding event listener interface that can be implemented as required. In addition, event filters can be used to process events before the events are dispatched to a listener. Event listeners and filters can be statically registered on a cache during configuration or dynamically after the cache has been created.

The Coherence JCache provider supports the use of JCache events for local, partitioned, and pass-through caches. The provider makes use of the native Coherence MapListener and MapEvent APIs to implement JCache events. Applications can directly access the underlying NamedCache instance and use the MapListener API; however, doing so directly bypasses additional behavior provided by the JCache Coherence implementation.

36.2 Creating Event Listeners

Each event type has a corresponding event listener interface that extends the CacheEntryListener interface. The event type interfaces include the CacheEntryCreatedListener, CacheEntryUpdatedListener, CacheEntryRemovedListener, and CacheEntryExpiredListener interfaces. A single event listener can choose to implement multiple event type listener interfaces or multiple event listeners can implement the same event type listener interfaces. The following example creates an event listener for CREATED events that emits a log message that includes the event details every time an entry is created in a cache.

Example 36-1 An Example Event Listener Implementation

import java.io.Serializable;
import javax.cache.event.CacheEntryCreatedListener;
import javax.cache.event.CacheEntryEvent;
import javax.cache.event.CacheEntryListenerException;

public class MyCacheEntryListener<K, V>
   implements CacheEntryCreatedListener<K, V>, Serializable
   {
      private static final long serialVersionUID = 1L;
 
   public void onCreated(Iterable<CacheEntryEvent<? extends K, ? extends V>>
      events)
      throws CacheEntryListenerException
      {
         for (CacheEntryEvent<? extends K, ? extends V> event : events)
            {
            System.out.println("Received a " + event);
            }
      }
}

Event listeners that require serialization can use POF serialization. However, POF is not portable among cache provider implementations.

36.3 Creating Event Filters

Cache entry event filters provide the opportunity to evaluate cache events before the events are dispatched to an entry event listener. Event filters allow additional processing to be performed as required. Event filters must implement the CacheEntryEventFilter interface. The following example creates an event filter for CREATED events that stops the event from being dispatched and emits a system message.

Example 36-2 An Example Event Filter Implementation

import java.io.Serializable;
import javax.cache.event.CacheEntryEvent;
import javax.cache.event.CacheEntryEventFilter;
import javax.cache.event.CacheEntryListenerException;
import javax.cache.event.EventType;
 
public class MyCacheEntryEventFilter<K, V>
   implements CacheEntryEventFilter<K, V>, Serializable
   {
      private static final long serialVersionUID = 1L;
 
   public boolean evaluate(CacheEntryEvent<? extends K, ? extends V> event)
      throws CacheEntryListenerException
      {
         boolean result = false;
 
         if (event.getEventType() == EventType.CREATED)
            {
            System.out.println("filter event=" + event + " filter result=" +
               result);
            }
 
         return result;
      }
}

Event filters that require serialization can use POF serialization. However, POF is not portable among cache provider implementations.

36.4 Registering Event Listeners and Filters

Cache entry listeners and event filters can be registered statically on a cache during configuration or dynamically after a cache instance has been created. Either method requires the use of a listener configuration. The configuration is defined in the CacheEntryListenerConfiguration interface. The MutableCacheEntryListenerConfiguration class provides a default implementation that can be used as required and is demonstrated in this section. The configuration is used to specify the listener implementation class to use, the filter implementation class to use, whether to send the old value as part of the event, and whether event notification should be synchronous or asynchronous. The order in which listeners are notified is not guaranteed.

This section includes the following topics:

36.4.1 Registering Event Listeners and Filters During Cache Configuration

To register CacheEntryListener and CacheEntryEventFilter implementations statically during configuration, use the addCacheEntryListenerConfiguration method and include the implementation classes and configure the listener as required. The following example registers the event listener and filter that was created in Example 36-1 and Example 36-2, respectively.

CachingProvider cachingProvider = Caching.getCachingProvider();
CacheManager cacheManager = cachingProvider.getCacheManager();

m_listener = new MyCacheEntryListener();

MutableConfiguration<String, String> config = 
   new MutableConfiguration<String, String>();
config.setTypes(String.class, String.class).addCacheEntryListenerConfiguration(
      new MutableCacheEntryListenerConfiguration<String, String>
      (FactoryBuilder.factoryOf(m_listener),FactoryBuilder.factoryOf(
      new MyCacheEntryEventFilter<String, String>()),true,true));

Cache<String, String> cache = cacheManager.createCache("MyCache", config);

The example configuration sets event notifications to include the old value of the entry and to use synchronous dispatching as indicated by the two true properties.

The removeCacheEntryListenerConfiguration method removes a cache entry listener that was previously registered.

36.4.2 Registering Event Listeners and Filters at Runtime

To register CacheEntryListener and CacheEntryEventFilter implementations dynamically on a cache instance at runtime, use the RegisterCacheEntryListener method and include the implementation classes and configure the listener as required. The following example registers the event listener and filter that was created in Example 36-1 and Example 36-2, respectively.

CachingProvider cachingProvider = Caching.getCachingProvider();
CacheManager cacheManager = cachingProvider.getCacheManager();

m_listener = new MyCacheEntryListener();

MutableConfiguration<String, String> config = 
   new MutableConfiguration<String, String>();
config.setTypes(String.class, String.class);

Cache<String, String> cache = cacheManager.createCache("MyCache", config);

cache.registerCacheEntryListener(
   new MutableCacheEntryListenerConfiguration<String, String>
   (FactoryBuilder.factoryOf(m_listener),FactoryBuilder.factoryOf(
   new MyCacheEntryEventFilter<String, String>()),false,false));

The example configuration sets event notifications to not include the old value of the entry and to use asynchronous dispatching as indicated by the two false properties.

The deregisterCacheEntryListener method removes a cache entry listener that was previously registered.