Annotation Type Listener


  • @Retention(RUNTIME)
    @Target(TYPE)
    public @interface Listener
    Class-level annotation used to annotate an object as being a valid cache listener. Used with the Listenable.addListener(Object) and related APIs.

    Note that even if a class is annotated with this annotation, it still needs method-level annotation (such as CacheStarted) to actually receive notifications.

    Objects annotated with this annotation - listeners - can be attached to a running Cache so users can be notified of Cache events.

    There can be multiple methods that are annotated to receive the same event, and a method may receive multiple events by using a super type.

    Delivery Semantics

    An event is delivered immediately after the respective operation, but before the underlying cache call returns. For this reason it is important to keep listener processing logic short-lived. If a long running task needs to be performed, it's recommended to use another thread.

    Transactional Semantics

    Since the event is delivered during the actual cache call, the transactional outcome is not yet known. For this reason, events are always delivered, even if the changes they represent are discarded by their containing transaction. For applications that must only process events that represent changes in a completed transaction, TransactionalEvent.getGlobalTransaction() can be used, along with TransactionCompletedEvent.isTransactionSuccessful() to record events and later process them once the transaction has been successfully committed. Example 4 demonstrates this.

    Threading Semantics

    A listener implementation must be capable of handling concurrent invocations. Local notifications reuse the calling thread; remote notifications reuse the network thread.

    Since notifications reuse the calling or network thread, it is important to realise that if your listener implementation blocks or performs a long-running task, the original caller which triggered the cache event may block until the listener callback completes. It is therefore a good idea to use the listener to be notified of an event but to perform any long running tasks in a separate thread so as not to block the original caller.

    In addition, any locks acquired for the operation being performed will still be held for the callback. This needs to be kept in mind as locks may be held longer than necessary or intended to and may cause deadlocking in certain situations. See above paragraph on long-running tasks that should be run in a separate thread.

    Note: The sync parameter on this annotation defaults to true which provides the above semantics. Alternatively, if you set sync to false, then invocations are made in a separate thread, which will not cause any blocking on the caller or network thread. The separate thread is taken from a pool, which can be configured using GlobalConfiguration.listenerThreadPool().

    Summary of Notification Annotations

    Annotation Event Description
    CacheStarted CacheStartedEvent A cache was started
    CacheStopped CacheStoppedEvent A cache was stopped
    CacheEntryModified CacheEntryModifiedEvent A cache entry was modified
    CacheEntryCreated CacheEntryCreatedEvent A cache entry was created
    CacheEntryRemoved CacheEntryRemovedEvent A cache entry was removed
    CacheEntryVisited CacheEntryVisitedEvent A cache entry was visited
    CacheEntryLoaded CacheEntryLoadedEvent A cache entry was loaded
    CacheEntriesEvicted CacheEntriesEvictedEvent A cache entries were evicted
    CacheEntryActivated CacheEntryActivatedEvent A cache entry was activated
    CacheEntryPassivated CacheEntryPassivatedEvent One or more cache entries were passivated
    ViewChanged ViewChangedEvent A view change event was detected
    TransactionRegistered TransactionRegisteredEvent The cache has started to participate in a transaction
    TransactionCompleted TransactionCompletedEvent The cache has completed its participation in a transaction
    CacheEntryInvalidated CacheEntryInvalidatedEvent A cache entry was invalidated by a remote cache. Only if cache mode is INVALIDATION_SYNC or INVALIDATION_ASYNC.

    Example 1 - Method receiving a single event

        @Listener
        public class SingleEventListener
        {
           @CacheStarted
           public void doSomething(Event event)
           {
              System.out.println("Cache started.  Details = " + event);
           }
        }
     

    Example 2 - Method receiving multiple events

        @Listener
        public class MultipleEventListener
        {
           @CacheStarted
           @CacheStopped
           public void doSomething(Event event)
           {
              if (event.getType() == Event.Type.CACHE_STARTED)
                 System.out.println("Cache started.  Details = " + event);
              else if (event.getType() == Event.Type.CACHE_STOPPED)
                 System.out.println("Cache stopped.  Details = " + event);
           }
        }
     

    Example 3 - Multiple methods receiving the same event

        @Listener
        public class SingleEventListener
        {
           @CacheStarted
           public void handleStart(Event event)
           {
              System.out.println("Cache started");
           }
     

    @CacheStarted @CacheStopped @CacheBlocked @CacheUnblocked @ViewChanged public void logEvent(Event event) { logSystem.logEvent(event.getType()); } }

    Example 4 - Processing only events with a committed transaction.

        @Listener
        public class EventHandler
        {
           private ConcurrentMap<GlobalTransaction, Queue<Event>> map = new ConcurrentHashMap<GlobalTransaction, Queue<Event>>();
    
           @TransactionRegistered
           public void startTransaction(TransactionRegisteredEvent event)
           {
              map.put(event.getGlobalTransaction(), new ConcurrentLinkedQueue<Event>());
           }
    
           @CacheEntryCreated
           @CacheEntryModified
           @CacheEntryRemoved
           public void addEvent(TransactionalEvent event)
           {
              map.get(event.getGlobalTransaction()).add(event);
           }
    
           @TransactionCompleted
           public void endTransaction(TransactionCompletedEvent event)
           {
              Queue<Event> events = map.get(event.getGlobalTransaction());
              map.remove(event.getGlobalTransaction());
    
              System.out.println("Ended transaction " + event.getGlobalTransaction().getId());
    
              if(event.isTransactionSuccessful())
              {
                 for(Event e : events)
                 {
                    System.out.println("Event " + e);
                 }
              }
           }
        }
     
    Since:
    4.0
    Author:
    Manik Surtani, Jason T. Greene
    See Also:
    CacheStarted, CacheStopped, CacheEntryModified, CacheEntryCreated, CacheEntryRemoved, CacheEntryVisited, CacheEntryLoaded, CacheEntriesEvicted, CacheEntryActivated, CacheEntryPassivated, ViewChanged, TransactionCompleted, TransactionRegistered, CacheEntryInvalidated, DataRehashed, TopologyChanged, PartitionStatusChanged, PersistenceAvailabilityChanged
    • Optional Element Summary

      Optional Elements 
      Modifier and Type Optional Element Description
      boolean clustered
      Defines whether the annotated listener is clustered or not.
      boolean includeCurrentState
      If set to true then the entire existing state within the cluster is evaluated.
      Listener.Observation observation
      Returns the type of observation level this listener defines.
      boolean primaryOnly
      Specifies whether the event should be fired on the primary data owner of the affected key, or all nodes that see the update.
      boolean sync
      Specifies whether callbacks on any class annotated with this annotation happens synchronously (in the caller's thread) or asynchronously (using a separate thread).
    • Element Detail

      • sync

        boolean sync
        Specifies whether callbacks on any class annotated with this annotation happens synchronously (in the caller's thread) or asynchronously (using a separate thread). Defaults to true.
        Returns:
        true if the expectation is that callbacks are called using the caller's thread; false if they are to be made in a separate thread.
        Since:
        4.0
        Default:
        true
      • primaryOnly

        boolean primaryOnly
        Specifies whether the event should be fired on the primary data owner of the affected key, or all nodes that see the update.

        Note that is value is ignored when clustered() is true.

        Returns:
        true if the expectation is that only the primary data owner will fire the event, false if all nodes that see the update fire the event.
        Since:
        5.3
        Default:
        false
      • clustered

        boolean clustered
        Defines whether the annotated listener is clustered or not. Important: Clustered listener can only be notified for @CacheEntryRemoved, @CacheEntryCreated,
        Returns:
        true if the expectation is that this listener is to be a cluster listener, as in it will receive all notifications for data modifications
        Since:
        7.0
        Default:
        false
      • includeCurrentState

        boolean includeCurrentState
        If set to true then the entire existing state within the cluster is evaluated. For existing matches of the value, an @CacheEntryCreated event is triggered against the listener during registration. This is only supported if the listener is also clustered().

        If using a distributed clustered cache it is possible to retrieve new events before the initial transfer is completed. This is handled since only new events are queued until the segment it belongs to is completed for iteration. This also will help reduce memory strain since a distributed clustered listener will need to eventually retrieve all values from the cache.

        Returns:
        true if the expectation is that when the listener is installed that all of the current data is sent as new events to the listener before receiving new events
        Since:
        7.0
        Default:
        false
      • observation

        Listener.Observation observation
        Returns the type of observation level this listener defines.
        Returns:
        the observation level of this listener
        Since:
        7.2
        See Also:
        Listener.Observation
        Default:
        org.infinispan.notifications.Listener.Observation.BOTH