Item Level Event Notifications
Item Level Events can be registered to get notifications for specific key/keys. Besides keys, Item Level Events can also be registered using the CacheItem
class. The notifications can be received when update or remove operations are performed on specified keys. Item Level Events can be registered using RegisterCacheNotification
by providing the implemented callback, EventType
, and EventDataFilter
.
Important
The key must exist in cache for the event to be registered. Only the update or remove event types can be registered for Item Level Events.
The relevant details of registering Item Level Events are discussed, as follows.
Prerequisites
Implement Callback for Event Notifications
You can implement a callback for events where EventType
is specified according to the user's logic for ItemAdded
, ItemUpdated
or ItemRemoved
events. The example below shows how to register callbacks for event notifications.
public void OnCacheDataModification(string key, CacheEventArg args)
{
switch (args.EventType)
{
case EventType.ItemAdded:
Console.WriteLine($"Item with Key '{key}' has been added to cache '{args.CacheName}'");
break;
case EventType.ItemUpdated:
Console.WriteLine($"Item with Key '{key}' has been updated in the cache '{args.CacheName}'");
// Item can be used if EventDataFilter is DataWithMetadata or Metadata
if (args.Item != null)
{
Product updatedProduct = args.Item.GetValue<Product>();
Console.WriteLine($"Updated Item is a Product having name '{updatedProduct.ProductName}' with ID '{updatedProduct.ProductID}' and price '{updatedProduct.UnitPrice}'");
}
break;
case EventType.ItemRemoved:
Console.WriteLine($"Key '{key}' has been removed from the cache '{args.CacheName}'");
break;
}
}
// Precondition: Events have been enabled
// Create a target method
public void onCacheDataModification(String key, CacheEventArg args)
{
switch (args.getEventType())
{
case ItemAdded:
// Key has been added to the cache
break;
case ItemUpdated:
// 'key' has been updated in the cache
// get the updated product
if (args.getItem() != null)
{
Product updateProduct = args.getItem().getValue(Product.class);
// perform operations
}
break;
case ItemRemoved:
// 'key' has been removed from the cache
break;
}
}
class ItemLevelDataModificationListener extends CacheDataModificationListener
{
override def onCacheDataModified(key: String, eventArgs: CacheEventArg): Unit =
{
eventArgs.getEventType match
{
case EventType.ItemAdded =>
// Key has been added to the cache
case EventType.ItemUpdated =>
// 'key' has been updated in the cache
// get the updated product
if (eventArgs.getItem != null)
{
val updateProduct = eventArgs.getItem.getValue(classOf[Product])
// perform operations
}
case EventType.ItemRemoved =>
// 'key' has been removed from the cache
}
}
override def onCacheCleared(cacheName: String): Unit =
{
print("Cache cleared.")
}
}
// Precondition: Events have been enabled
// Create a target method
onCacheDataModified(key, arg)
{
if (null != arg.getEventType())
{
switch (arg.getEventType())
{
// perform operations
case ncache.EventType.ItemUpdated:
// key has been updated in cache
if (args.getItem() != null)
{
Product updateProduct = args.getItem().getValue();
// perform operations
}
break;
case ncache.EventType.ItemRemoved:
// key has been removed from cache
break;
default:
break;
}
}
}
def on_cache_data_modified(key: str, arg: ncache.CacheEventArg):
if arg.get_event_type() is not None:
if arg.get_event_type() is ncache.EventType.ITEM_ADDED:
# Key has been added to cache
print("Item added")
elif arg.get_event_type() is ncache.EventType.ITEM_UPDATED:
# Key has been updated in cache
print("Item updated")
elif arg.get_event_type() is ncache.EventType.ITEM_REMOVED:
# key has been removed from cache
print("Item removed")
Note
To ensure the operation is fail-safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Register Item Notifications
Given that callback has been implemented, a target method is created which contains multiple callbacks. The appropriate EventType
is provided for monitoring only the specific client operations. These event types include ItemUpdated
and ItemRemoved
that must be specified by a separate method call. EventDataFilter
is specified to quantify the amount of information returned upon an event execution.
Note
If EventDataFilter
is not specified, EventDataFilter.None
is set automatically.
Here, we explain that how you can register item notifications for a particular item or set of items.
Register Item Notifications for a Particular Item
In order to register item notification for a single item, use the RegisterCacheNotifications
method by providing a single key, the EventType
and the EventDataFilter
. The following example shows how to register item notifications with the ItemUpdated
event type for a particular item.
// Key of the cache item to be monitored events
string key = "Product:Chai";
// create CacheDataNotificationCallback object
var dataNotificationCallback = new CacheDataNotificationCallback(OnCacheDataUpdation);
// Register notifications for a specific item being updated in cache
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
cache.MessagingService.RegisterCacheNotification(key, dataNotificationCallback, EventType.ItemUpdated, EventDataFilter.DataWithMetadata);
// Callback to Update Event Notifications
public void OnCacheDataUpdation(string key, CacheEventArg args)
{
Console.WriteLine($"Item with Key '{key}' has been updated in the cache '{args.CacheName}'");
// Item can be used if EventDataFilter is DataWithMetadata or Metadata
if (args.Item != null)
{
Product updatedProduct = args.Item.GetValue<Product>();
Console.WriteLine($"Updated Item is a Product having name '{updatedProduct.ProductName}' with ID '{updatedProduct.ProductID}' and price '{updatedProduct.UnitPrice}'");
}
}
try {
// Precondition: Cache is already connected
var dataModificationListener = onCacheDataModification(key, args);
CacheDataModification dataModification = new CacheDataModification(dataModificationListener);
// Register item notification with "ItemUpdated" event type
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
EnumSet<com.alachisoft.ncache.runtime.events.EventType> enumSet = EnumSet.of(EventType.ItemAdded);
cache.getMessagingService().addCacheNotificationListener(key, dataModification, enumSet, EventDataFilter.DataWithMetadata);
// Perform your business logic
} catch (OperationFailedException exception) {
// Exception can occur due to:
// Connection failures
// Operation timeout
} catch (Exception exception) {
// Any generic exception like IllegalArgumentException or NullPointerException
}
try {
// Precondition: Cache is already connected
val key = "Product:1001"
// Register target listener
val dataModificationListener = ItemLevelDataModificationListener()
// Register item notification with "ItemUpdated" event type
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
val enumSet = List(EventType.ItemUpdated)
cache.getMessagingService.addCacheNotificationListener(key, dataModificationListener, enumSet, EventDataFilter.DataWithMetadata)
// Perform your business logic
}
catch {
case exception: Exception => {
// Handle any errors
}
}
try {
// Precondition: Cache is already initialized
let dataModificationListener = new ncache.CacheDataModificationListener(
this.onCacheDataModified,
this.onCacheCleared
);
let key = "Product:1001";
// Register item notifications with 'ItemUpdated' event type
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
let messagingService = await this.cache.getMessagingService();
await messagingService.addCacheNotificationListener(
key,
dataModificationListener,
ncache.EventType.ItemUpdated,
ncache.EventDataFilter.DataWithMetadata
);
} catch (error) {
// Handle any errors
}
try:
# Pre-conditions: Cache is already connected &
key = "Product:1001"
# Register item notifications with 'ITEM_UPDATED' event type
# EventDataFilter as DATA_WITH_META_DATA which returns keys along with their
# entire data
messaging_service = cache.get_messaging_service()
messaging_service.add_cache_notification_listener(
event_listener,
[ncache.EventType.ITEM_UPDATED],
ncache.EventDataFilter.DATA_WITH_META_DATA,
key
)
except Exception as exp:
# Handle errors
Register Item Notifications for a Set of Items
In order to register item notifications for a set of items, use the RegisterCacheNotifications
method by providing an array of keys, the EventType
and the EventDataFilter
. The following example shows how to register item notifications with the ItemUpdated
event type for a set of item.
// Aarray of keys for items that need to be monitored on events
String[] keys = new String[]
{
"Product:Chai", "Product:Coffee", "Product:Juice", "Product:Coke"
};
// create CacheDataNotificationCallback object
var dataNotificationCallback = new CacheDataNotificationCallback(OnCacheDataUpdation);
// Register notifications for specific set of items being updated in cache
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
cache.MessagingService.RegisterCacheNotification(keys, dataNotificationCallback, EventType.ItemUpdated, EventDataFilter.DataWithMetadata);
var dataModificationListener = onCacheDataModification(key, args);
CacheDataModification dataModification = new CacheDataModification(dataModificationListener);
// Fetch all products from database
Product[] products = fetchProductsFromDB();
// Create a new array of keys for which the cache fires notifications
String[] keys = new String[products.length];
int index = 0;
for (var product : products) {
// Generate a unique cache key for this product
keys[index] = "Product:" + product.productID;
index++;
}
// Create EnumSet with ItemUpdated and ItemRemoved event type
EnumSet<EventType> enumSet = EnumSet.of(EventType.ItemUpdated, EventType.ItemRemoved);
// Register item notification with ItemUpdated and ItemRemoved event type
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
var data = cache.getMessagingService().addCacheNotificationListener(key, dataModification, enumSet, EventDataFilter.DataWithMetadata);
// Perform your business logic
// Register target method
val dataModificationListener = ItemLevelDataModificationListener()
// Fetch all products from database
val products = fetchProductsFromDB
// Create a new array of keys for which the cache fires notifications
var keys: List[String] = List()
for (product <- products)
{
// Generate a unique cache key for this product
keys = ("Product:" + product.getProductId) :: keys
}
// Create EnumSet with ItemUpdated and ItemRemoved event type
val eventTypes = List(EventType.ItemUpdated, EventType.ItemRemoved)
// Register item notification with ItemUpdated and ItemRemoved event type
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
cache.getMessagingService.addCacheNotificationListener(keys, dataModificationListener, eventTypes, EventDataFilter.DataWithMetadata)
// Perform your business logic
let dataModificationListener = new ncache.CacheDataModificationListener(
this.onCacheDataModified,
this.onCacheCleared
);
// Fetch all products from database
let products = this.fetchProductsFromDB();
// Create a new array keys with the specified keys for which the cache fires notifications
let keys = new String[products.length]();
var index = 0;
products.forEach((element) => {
keys[index] = "Product:1001";
index++;
});
// Register item notifications with 'ItemUpdated' and 'ItemRemoved' event type
// EventDataFilter as DataWithMetadata which returns keys along with their entire data
let messagingService = await this.cache.getMessagingService();
await messagingService.addCacheNotificationListener(
keys,
dataModificationListener,
ncache.EventType.ItemUpdated,
ncache.EventDataFilter.DataWithMetadata
);
# Register target method
data_modification_listener = event_listener
# Fetch all products from database
products = fetch_products_from_db()
# Create a array keys with the specified keys for which the cache
# fires notifications
keys = []
for product in products:
keys.append("Product:" + str(product.get_product_id()))
# Register item notifications with 'ITEM_UPDATED' and 'ITEM_REMOVED' event type
# EventDataFilter as DATA_WITH_META_DATA which returns keys along with their
# entire data
messaging_service = cache.get_messaging_service()
messaging_service.add_cache_notification_listener(
data_modification_listener,
[ncache.EventType.ITEM_UPDATED],
ncache.EventDataFilter.DATA_WITH_META_DATA,
keys
Register Item Notifications Using CacheItem
CacheItem
is a custom class provided by NCache which can be used to add data to the cache.
Item Level Events can also be registered with a particular key by using the CacheItem.SetCacheDataNotification
method. This method allows you to provide the appropriate information for registering the notifications for the CacheItem
.
The example below registers ItemUpdated
and ItemRemoved
events for a CacheItem
.
string key = "Product:Chai";
// Fetch item from cache
CacheItem cacheItem = cache.GetCacheItem(key);
if(cacheItem == null)
{
Product product = FetchProductFromDB("Chai");
cacheItem = new CacheItem(product);
}
// create CacheDataNotificationCallback object
var dataNotificationCallback = new CacheDataNotificationCallback(OnCacheDataModification);
// Register events with CaceItem with Item Removed and ItemUpdated EventType
// Set the EventDataFilter as DataWithMetadata which returns keys along with their entire data
cacheItem.SetCacheDataNotification(dataNotificationCallback, EventType.ItemRemoved | EventType.ItemUpdated, EventDataFilter.DataWithMetadata);
//Re-inserts the cacheItem into cache with events registered
cache.Insert(key, cacheItem);
var dataModificationListener = onCacheDataModification(key, args);
CacheDataModification dataModification = new CacheDataModification(dataModificationListener);
// Get product from database
Product product = fetchProductFromDB(productid);
// Create a unique cache key for this product
String productKey = "Product:" + product.productID;
// Create a new CacheItem
CacheItem cacheItem = new CacheItem(product);
// Create EnumSet of ItemUpdated and ItemRemoved event types
EnumSet<EventType> enumSet = EnumSet.of(EventType.ItemUpdated, EventType.ItemRemoved);
// Register events with CacheItem with Item Removed and ItemUpdated EventType
// Set the EventDataFilter as DataWithMetadata which returns keys along with their entire data
cacheItem.addCacheDataNotificationListener(dataModification, enumSet, EventDataFilter.DataWithMetadata);
// Insert the cache item in the cache with events registered
cache.insert(productKey, cacheItem);
// Register target method
val dataModificationListener = ItemLevelDataModificationListener()
// Get product from database
val product = fetchProductFromDB("1001")
// Create a unique cache key for this product
val productKey = "Product:" + product.getProductId
// Create a new CacheItem
val cacheItem = new CacheItem(product)
// Create EnumSet of ItemUpdated and ItemRemoved event types
val eventTypes = List(EventType.ItemUpdated, EventType.ItemRemoved)
// Register events with CacheItem with Item Removed and ItemUpdated EventType
// Set the EventDataFilter as DataWithMetadata which returns keys along with their entire data
cacheItem.addCacheDataNotificationListener(dataModificationListener, eventTypes, EventDataFilter.DataWithMetadata)
// Insert the cache item in the cache with events registered
cache.insert(productKey, cacheItem)
let eventListener = new ncache.CacheDataModificationListener(
this.onCacheDataModified,
this.onCacheCleared
);
let messagingService = await this.cache.getMessagingService();
await messagingService.addCacheNotificationListener(
"key",
eventListener,
ncache.EventType.ItemAdded,
ncache.EventDataFilter.Metadata
);
// Get Product from database against given ProductID
let products = this.fetchProductsFromDB();
// Create a unique cache key for this customer.
let key = "Product:1001";
// Register events with CaceItem with Item Removed and ItemUpdated EventType
// Set the EventDataFilter as DataWithMetadata which returns keys along with their entire data
let messagingService2 = await this.cache.getMessagingService();
await messagingService2.addCacheNotificationListener(
eventListener,
ncache.EventType.ItemAdded,
ncache.EventType.ItemRemoved,
ncache.EventType.ItemUpdated,
ncache.EventDataFilter.Metadata
);
let cacheItem = ncache.CacheItem;
//Inserts the cacheItem into cache with events registered
this.cache.insert(key, cacheItem);
# Get Product from database
product = fetch_product_from_db()
# Create a unique cache key for this product.
key = "Product:1001"
# Register events with CacheItem with ITEM_REMOVED and ITEM_UPDATED EventType
# Set the EventDataFilter as DATA_WITH_META_DATA which returns keys along with their entire data
cache_item = ncache.CacheItem(product)
cache_item.add_cache_data_notification_listener(
event_listener,
[ncache.EventType.ITEM_REMOVED, ncache.EventType.ITEM_UPDATED],
ncache.EventDataFilter.DATA_WITH_META_DATA
)
# Inserts the cacheItem into cache with events registered
cache.insert(key, cache_item)
Unregister Item Level Notifications
You can also unregister a previously registered item level notification using
the UnRegisterCacheNotification
method if you don't want to receive further notifications. For Java, use the removeCacheDataModificationListener
method to unregister the registered notifications. Using this method, the appropriate key, callback CacheDataNotificationCallback
and EventType
must be specified.
The following example shows how to unregister notifications for a specific key.
// Key of cached item to un-register events
string key = "Product:Chai";
// callback method triggered on cache item events
var dataNotificationCallback = new CacheDataNotificationCallback(OnCacheDataUpdation);
// Unregister notifications for the ItemUpdated EventType for particular key and specify the callback
cache.MessagingService.UnRegisterCacheNotification(key, dataNotificationCallback, EventType.ItemUpdated);
// Unregister notifications for the ItemRemoved EventType for particular key and specify callback
var dataModificationListener = onCacheDataModification(key, args);
EnumSet<EventType> enumSet = EnumSet.of(EventType.ItemRemoved);
cache.getMessagingService().removeCacheNotificationListener(key, dataModificationListener, enumSet);
// Unregister notifications for the ItemRemoved EventType for particular key
// Specify callback
val dataModificationListener = ItemLevelDataModificationListener()
val enumSet = List(EventType.ItemRemoved)
cache.getMessagingService.removeCacheNotificationListener("Product1001", dataModificationListener, enumSet)
let eventListener;
// Unregister notifications for the ItemRemoved EventType for the
// particular key and specify the callback
await this.cache.removeCacheNotificationListener(
"key",
eventListener,
ncache.EventType.ItemRemoved
);
# Unregister notifications for the ITEM_REMOVED EventType for the
# particular key and specify the callback
cache.get_messaging_service().remove_cache_notification_listener
keys="key",
callablefunction=event_listener,
eventtypes=[ncache.EventType.ITEM_REMOVED]
Additional Resources
NCache provides a sample application for Item Level Event Notifications on GitHub.
See Also
Cache Level Event Notifications
Pub/Sub Messaging
Search Cache with LINQ