JavaSpaces Notifications

  GigaSpaces 5.X

Documentation Home
Quick Start Guide
Release Notes

Previous release

  Search Here
Searching GigaSpaces Platform 5.X Documentation

                                               

Summary: Registering to receive notifications when objects are added or modified in the space – unicast, multicast and tokenized notifications.

This page is specific to:
GigaSpaces 5.x

If you're interested in another version, click it below:
GigaSpaces 6.0
GigaSpaces 6.5

Overview

Some applications need to know when a new Entry is written to the space. For this reason, there is a standard notify method in the JavaSpaces API:

EventRegistration notify(Entry template,
Transaction txn, RemoteEventListener listener, long lease, MarshalledObject handback);

A client that wants to receive notifications of new Entries arriving at the space prepares a template and uses the notify space method to register the template in the space. When a new Entry that matches the template arrives at the space, the notify method of the RemoteEventListener supplied in the registration is invoked, supplying the space with a RemoteEvent object. Do not confuse the JavaSpaces notify method, used for registering the template, with the notify method of the RemoteEventListener, that is a callback method invoked by the space.

New in GigaSpaces 5.1
Registering for notifications on the take operation in FIFO mode is supported in GigaSpaces version 5.1 and onwards.
The space includes a special mechanism that detects clients that cannot consume the notifications sent fast enough – i.e. slow consumers. For more details, refer to the Slow Consumer section.

The RemoteEventListener object supplied in the JavaSpaces notify method may be the client itself, or any other remote listener that the client wishes to receive the event. This gives enormous flexibility, and enables various event-fetching models, like filtering and polling. For example, a mobile client may use the Jini Mailbox Service to hold events until it reconnects to the network. The RemoteEventListener object is a remote object, and its stub is used by the space to invoke the notify callback. Hence, the proxy of the listener must be annotated with a suitable code base, so that the space can download it on demand. This usually means that the client or someone acting for the client should run an HTTP server to serve class files or jar files, and that the client should annotate the code base via the java.rmi.server.codebase system property.

To ease the development and deployment of the notify method, a com.j_spaces.core.client.NotifyDelegator class is provided. This class provides several enhancements:

  • No client code base needs to be set.
  • Provides the ability to get the entry that triggered the event in the space.
  • Allows registration for specific notification events, for example, write, update, take and LeaseExpiration events.
  • Delivers events in FIFO order.
  • Supports both TCP and UPD transmission protocols (configurable delivery models: Multicast/Unicast).
  • Supports server-side notification filtering capabilities (currently only for UDP transmission mode). The NotifyDelegator is a convenient and efficient mechanism for multicasting messaging to multiple recipients through the space. Every recipient can register for notification by creating a NotifyDelegator object. The sender of the message can write an Entry with a limited lease time to the space. The recipients will receive the entry through the remote event. New recipients will have the opportunity to get old messages from the space through read. The messages will be cleaned automatically through the expiration mechanism.

Here is the NotifyDelegator constructor signature:

NotifyDelegator(IJSpace space,
Entry template, Transaction txn, RemoteEventListener listener, long lease,
MarshalledObject handback, boolean fifoEnabled, int notifyMask)

Creates a new delegator that can receive ordered notifications.

  • space – the space to register for notification.
  • template – the template to use for notification.
  • txn – the transaction to use for notification.
  • lease – the lease of the notification template.
  • handback – the handback to use for notification.
  • fifoEnabled – enables/disables ordered notifications.
  • notifyMask – available Notify Types:
    • NotifyModifiers.NOTIFY_WRITE
    • NotifyModifiers.NOTIFY_UPDATE
    • NotifyModifiers.NOTIFY_TAKE
    • NotifyModifiers.NOTIFY_LEASE_EXPIRATION
    • NotifyModifiers.NOTIFY_ALL
      When persisting a space using the JDBC SA or an indexed file, the notify registrations are persisted together with the space Entries by default. This allows the space to re-register itself in case it recovers from the database when the client is still alive, and the registration lease has not expired.
      If you do not desire this behavior, construct transient notify registration. In this case, the space doesn't persist the notify registration.

Use Lease.FOREVER as Notify Registration Lease Time Carefully

Registration for notifications is cancelled automatically when the notification object invalidates – i.e. is cleared by the garbage collector. With abnormal termination of the application, the garbage collector cannot finalize the registration object. This may lead to delays with delivering notifications to live clients, because the space accumulates notification registrations without the ability to clear these once they are invalidated.

The space includes a mechanism that detects stale notify registration using the space schema notifier-retries parameter – once a notification can't be delivered to a client (network failure or a dead client), the space retries to send the notification several times (according the notifier-retries parameter value) and once it fails, the notify registration is removed. If there are many clients terminating their operation in an abnormal manner while having an active event registration, the space might need some time to detect all stale clients and their notify registrations, delaying notification delivery to existing live clients.

The root cause of this behavior is the thread pool within the space engine that is responsible for delivering events to clients. When all pool threads are fully consumed, notification delivery time suffers, due to the time it takes to detect and remove all stale registrations.

For more details about configuring the notification thread pool, see the notify_max_threads space schema property in the Concurrency - Space Schema section.

To reduce the amount of stale registrations, register notification with a reasonable lease time (30 seconds - 2 minutes can be a good interval) and renew these using the net.jini.lease.LeaseRenewalManager every 30 seconds - 2 minutes. This ensures that once the client exists in an abnormal manner, the registration automatically expires and is removed, reducing the chance to fully consume the notification thread pool and delay notification delivery to live clients.

Cancelling Notify Registration

To cancel notify registration:

  • Throw an UnknownEventException from the net.jini.core.event.RemoteEventListener.notify() implementation.
  • Cancel the notify lease using the NotifyDelegator.close method.

Transient Notify Registration

When running the space in persistent mode, you might want to have transient notify registrations. These registrations are not persistent, and aren't recovered once the space is restarted in case the notify registration has not expired. In this case, extend your class from MetaDataEntry and call the MetaDataEntry.makeTransient() as part of the template constructor.

Stale Notify Registration

When the space detects stale notify registration (clients that registered for notify registration do not respond), the notify registration is cancelled. When the space is running in persistent mode, removal of the registrations takes place also in the durable media (database/indexed file).

If you need to terminate the NotifyDelegator before the lease expires, it is recommended to use the NotifyDelegator.close() method. This cancels the template lease and destroys the NotifyDelegator object. It is not recommended to use NotifyDelegator.getEventRegistration().getLease().cancel(),
because this cancels the lease but leaves the NotifyDelegator idle in memory.

Below is and example for usage of the NotifyDelegator:

public class HelloWorld implements RemoteEventListener {
&..
// register a notification
m_Space.snapshot(new Message());
m_Template = new Message();
Lease leases[] = new Lease[10];
// Registering for all Notifies using NOTIFY_ALL - i.e. :
 NOTIFY_WRITE  , NOTIFY_UPDATE  , NOTIFY_TAKE , NOTIFY_LEASE_EXPIRATION
// Events will be delivered in FIFO Mode
m_NotifyDelegator = new NotifyDelegator((IJSpace) m_Space, m_Template,
null, this, Lease.FOREVER, null , true , NotifyModifiers.NOTIFY_ALL);
System.out.println("Notification registered. Registration id: "
+ m_NotifyDelegator.getEventRegistration().getID()
+ " ; Sequence number: "+ m_NotifyDelegator.getEventRegistration().getSequenceNumber());

// write 5 messages to space
System.out.println(getTime() + "Writing 5 messages to space...");
for (int i = 0; i < 5; i++) {
Message msg = new Message();
msg  .content = "Hello World " + i;
leases [i] = m_Space.write(msg, null, 5000);
System.out.println(getTime() + "Wrote entry " + i);
}

// update 5 messages in space
System.out.println(getTime() + "Update 5 messages in space...");
for (int i = 0; i < 5; i++) {
        Message msg = new Message();
        msg.content = "Hello World " + i;
        Message ret = (Message)m_Space.read(msg, null, 1000);
        m_Space.update(ret , null, Lease.FOREVER , 1000);

        System.out.println(getTime() + "update entry " + i);
}

// take 2 messages from space
System.out.println(getTime() + "Take 2 messages from space...");
for (int i = 0; i < 2; i++) {
         Message msg = new Message();
         msg.content = "Hello World " + i;
         Message ret = (Message)m_Space.take(msg, null, 1000);
         System.out.println(getTime() + "Take entry " + i);
}
// sleep
Thread.sleep(5 * 5000);

// Cancel Lease for 3 messages at space
System.out.println(getTime() + "Cancel Lease for 3 messages in space...");
for (int i = 2; i < 5; i++) {
         leases[i].cancel();
         System.out.println(getTime() + "Canceled Lease " + i);
}
}

The client uses the NotifyDelegator to register for notifications on message Entries arriving to the space. The registrations are forever (using Lease.FOREVER), and all types of events are delivered to the registered client (NotifyModifiers.NOTIFY_ALL).

Although developers can use notifications in a transactions context, this example uses notifications under a null transaction. When a notification is made inside a transaction context, the notify template is implicitly dropped in the end of the transaction.

In the example above, the reference to the NotifyDelegator constructor is passed as an argument to the remote listener. In this case, the HelloWorld class implements RemoteEventListener, implementing a notify method:

public void notify(RemoteEvent theEvent) throws UnknownEventException, RemoteException {
String mes = "nGot event:"
                      + " Event Id: " + theEvent.getID() + " Event Sequence Number: "
                      + theEvent.getSequenceNumber();
        try {
               // since we are using NotifyDelegator, we can obtain the entry that
               // triggered the event
               EntryArrivedRemoteEvent arrivedRemoteEvent = (EntryArrivedRemoteEvent) theEvent;
               Message msg = (Message) arrivedRemoteEvent.getEntry();
               mes = mes + " Message Content: " + msg.content;
               int notifyType = arrivedRemoteEvent.getNotifyType();
               System.out.println(getTime() + mes + " - Notify Type:" + notifyType);
        } catch (Exception ex) {

               ex.printStackTrace();
}

}

The RemoteEvent object passed to the notify method contains the following fields:

  • Event Source – uniquely represents the space which the event originates from. This can be used to distinguish events that originate from different spaces.
  • Event ID – uniquely represents the notification registration in the space. This can be used to distinguish between events that are triggered when they match different template registrations.
  • Event Sequence Number – uniquely represents this event from preceding and succeeding events generated on the same notification template. Sequence numbers increase monotonically and are consecutive.
  • Handback – the same handback that was supplied in the event registration (may be null).
  • Event Type – the method that caused the event to be delivered to the registrar (NotifyModifiers.NOTIFY_WRITE, NotifyModifiers.NOTIFY_UPDATE, NotifyModifiers.NOTIFY_TAKE, NotifyModifiers.NOTIFY_LEASE_EXPIRATION).

The Event Source, Event ID, and Event Sequence Number can be compared to their counterparts in the EventRegistration object that is returned by the NotifyDelegator.getEventRegistration method.

The RemoteEvent parameter passed to the notify callback operation can be used to retrieve the Entry that triggered the notify operation using the EntryArrivedRemoteEvent.getEntry() method.

More in this Section

GigaSpaces supports two types of notifications:


Wiki Content Tree


Your Feedback Needed!

We need your help to improve this wiki site. If you have any suggestions or corrections, write to us at techw@gigaspaces.com. Please provide a link to the wiki page you are referring to.

Labels