[id='cache-notifications_{context}']
= Cache-level notifications

Cache-level events occur on a per-cache basis, and by default are only raised on nodes where the events occur.  Note in a distributed cache these events are only raised on the owners of data being affected.  Examples of cache-level events are entries being added, removed, modified, etc.  These events trigger notifications to listeners registered to a specific cache.

Please see the link:{javadocroot}/org/infinispan/notifications/cachelistener/annotation/package-summary.html[Javadocs on the org.infinispan.notifications.cachelistener.annotation package] for a comprehensive list of all cache-level notifications, and their respective method-level annotations.

NOTE: Please refer to the link:{javadocroot}/org/infinispan/notifications/cachelistener/annotation/package-summary.html[Javadocs on the org.infinispan.notifications.cachelistener.annotation package] for the list of cache-level notifications available in {brandname}.

[discrete]
== Cluster listeners
The cluster listeners should be used when it is desirable to listen to the cache events on a single node.

To do so all that is required is set to annotate your listener as being clustered.

[source,java]
----
include::code_examples/ListenerMyCluster.java[]
----

There are some limitations to cluster listeners from a non clustered listener.

. A cluster listener can only listen to `@CacheEntryModified`, `@CacheEntryCreated`, `@CacheEntryRemoved` and `@CacheEntryExpired` events.  Note this means any other type of event will not be listened to for this listener.
. Only the post event is sent to a cluster listener, the pre event is ignored.

[discrete]
== Event filtering and conversion
All applicable events on the node where the listener is installed will be raised to the listener.  It is possible to dynamically filter what events are raised by using a link:{javadocroot}/org/infinispan/filter/KeyFilter.html[KeyFilter] (only allows filtering on keys) or link:{javadocroot}/org/infinispan/notifications/cachelistener/filter/CacheEventFilter.html[CacheEventFilter] (used to filter for keys, old value, old metadata, new value, new metadata, whether command was retried, if the event is before the event (ie. isPre) and also the command type).

The example here shows a simple `KeyFilter` that will only allow events to be raised when an event modified the entry for the key `Only Me`.

[source,java]
----
include::code_examples/ListenerKeyFilter.java[]
----

This can be useful when you want to limit what events you receive in a more efficient manner.

There is also a link:{javadocroot}/org/infinispan/notifications/cachelistener/filter/CacheEventConverter.html[CacheEventConverter] that can be supplied that allows for converting a value to another before raising the event.  This can be nice to modularize any code that does value conversions.

NOTE: The mentioned filters and converters are especially beneficial when used in conjunction with a Cluster Listener.  This is because the filtering and conversion is done on the node where the event originated and not on the node where event is listened to.  This can provide benefits of not having to replicate events across the cluster (filter) or even have reduced payloads (converter).

[discrete]
== Initial State Events
When a listener is installed it will only be notified of events after it is fully installed.

It may be desirable to get the current state of the cache contents upon first registration of listener by having an event generated of type `@CacheEntryCreated` for each element in the cache.  Any additionally generated events during this initial phase will be queued until appropriate events have been raised.

NOTE: This only works for clustered listeners at this time.  link:https://issues.jboss.org/browse/ISPN-4608[ISPN-4608] covers adding this for non clustered listeners.

[discrete]
== Duplicate Events

It is possible in a non transactional cache to receive duplicate events.  This is possible when the primary owner of a key goes down while trying to perform a write operation such as a put.

{brandname} internally will rectify the put operation by sending it to the new primary owner for the given key automatically, however there are no guarantees in regards to if the write was first replicated to backups.  Thus more than 1 of the following write events (`CacheEntryCreatedEvent`, `CacheEntryModifiedEvent` & `CacheEntryRemovedEvent`) may be sent on a single operation.

If more than one event is generated {brandname} will mark the event that it was generated by a retried command to help the user to know when this occurs without having to pay attention to view changes.

[source,java]
----
include::code_examples/ListenerMyRetry.java[]
----

Also when using a `CacheEventFilter` or `CacheEventConverter` the link:{javadocroot}/org/infinispan/notifications/cachelistener/filter/EventType.html[EventType] contains a method `isRetry` to tell if the event was generated due to retry.
