IT技术及科技前沿

中文IT博客,为IT专业技术人员提供最全面的信息传播和服务

首页 新随笔 订阅 管理

Overview

Coherence provides cache events using the JavaBean Event model. It is extremely simple to receive the events that you need, where you need them, regardless of where the changes are actually occurring in the cluster. Developers with any experience with the JavaBean model will have no difficulties working with events, even in a complex cluster.

Listener interface and Event object

In the JavaBeans Event model, there is an EventListener interface that all listeners must extend. Coherence provides a MapListener interface, which allows application logic to receive events when data in a Coherence cache is added, modified or removed:

excerpt from com.tangosol.util.MapListener
public interface MapListener
        extends EventListener
    {
    /**
    * Invoked when a map entry has been inserted.
    *
    * @param evt  the MapEvent carrying the insert information
    */
    public void entryInserted(MapEvent evt);

    /**
    * Invoked when a map entry has been updated.
    *
    * @param evt  the MapEvent carrying the update information
    */
    public void entryUpdated(MapEvent evt);
    
    /**
    * Invoked when a map entry has been removed.
    *
    * @param evt  the MapEvent carrying the delete information
    */
    public void entryDeleted(MapEvent evt);
    }

An application object that implements the MapListener interface can sign up for events from any Coherence cache or class that implements the ObservableMap interface, simply by passing an instance of the application's MapListener implementation to one of the addMapListener() methods.

The MapEvent object that is passed to the MapListener carries all of the necessary information about the event that has occurred, including the source (ObservableMap) that raised the event, the identity (key) that the event is related to, what the action was against that identity (insert, update or delete), what the old value was and what the new value is:

excerpt from com.tangosol.util.MapEvent
public class MapEvent
        extends EventObject
    {
    /**
    * Return an ObservableMap object on which this event has actually
    * occured.
    * 
    * @return an ObservableMap object
    */
    public ObservableMap getMap()

    /**
    * Return this event's id. The event id is one of the ENTRY_*
    * enumerated constants.
    *
    * @return an id
    */
    public int getId()

    /**
    * Return a key assosiated with this event.
    * 
    * @return a key
    */
    public Object getKey()

    /**
    * Return an old value assosiated with this event.
    * <p>
    * The old value represents a value deleted from or updated in a map.
    * It is always null for "insert" notifications.
    *
    * @return an old value
    */
    public Object getOldValue()

    /**
    * Return a new value assosiated with this event.
    * <p>
    * The new value represents a new value inserted into or updated in 
    * a map. It is always null for "delete" notifications.
    *
    * @return a new value
    */
    public Object getNewValue()


    // ----- Object methods -------------------------------------------------

    /**
    * Return a String representation of this MapEvent object.
    *
    * @return a String representation of this MapEvent object
    */
    public String toString()


    // ----- constants ------------------------------------------------------

    /**
    * This event indicates that an entry has been added to the map.
    */
    public static final int ENTRY_INSERTED = 1;

    /**
    * This event indicates that an entry has been updated in the map.
    */
    public static final int ENTRY_UPDATED  = 2;

    /**
    * This event indicates that an entry has been removed from the map.
    */
    public static final int ENTRY_DELETED  = 3;
    }

Caches and classes that support events

All Coherence caches implement ObservableMap; in fact, the NamedCache interface that is implemented by all Coherence caches extends the ObservableMap interface. That means that an application can sign up to receive events from any cache, regardless of whether that cache is local, partitioned, near, replicated, using read-through, write-through, write-behind, overflow, disk storage, etc.

Regardless of the cache topology and the number of servers, and even if the modifications are being made by other servers, the events will be delivered to the application's listeners.

In addition to the Coherence caches (those objects obtained through a Coherence cache factory), several other supporting classes in Coherence also implement the ObservableMap interface:

  • ObservableHashMap
  • LocalCache
  • OverflowMap
  • NearCache
  • ReadWriteBackingMap
  • AbstractSerializationCache, SerializationCache and SerializationPagedCache
  • WrapperObservableMap, WrapperConcurrentMap and WrapperNamedCache

For a full list of published implementing classes, see the Coherence JavaDoc for ObservableMap.

Signing up for all events

To sign up for events, simply pass an object that implements the MapListener interface to one of the addMapListener methods on ObservableMap:

ObservableMap methods
public void addMapListener(MapListener listener);
public void addMapListener(MapListener listener, Object oKey, boolean fLite);
public void addMapListener(MapListener listener, Filter filter, boolean fLite);

Let's create an example MapListener implementation:

Example MapListener implementation
/**
* A MapListener implementation that prints each event as it receives
* them.
*/
public static class EventPrinter
        extends Base
        implements MapListener
    {
    public void entryInserted(MapEvent evt)
        {
        out(evt);
        }

    public void entryUpdated(MapEvent evt)
        {
        out(evt);
        }

    public void entryDeleted(MapEvent evt)
        {
        out(evt);
        }
    }

Using this implementation, it is extremely simple to print out all events from any given cache (since all caches implement the ObservableMap interface):

cache.addMapListener(new EventPrinter());

Of course, to be able to later remove the listener, it is necessary to hold on to a reference to the listener:

Listener listener = new EventPrinter();
cache.addMapListener(listener);
m_listener = listener; // store the listener in a field

Later, to remove the listener:

Listener listener = m_listener;
if (listener != null)
    {
    cache.removeMapListener(listener);
    m_listener = null; // clean up the listener field
    }

Each addMapListener method on the ObservableMap interface has a corresponding removeMapListener method. To remove a listener, use the removeMapListener method that corresponds to the addMapListener method that was used to add the listener.

Using an inner class as a MapListener

When creating an an inner class to use as a MapListener, or when implementing a MapListener that only listens to one or two types of events (inserts, updates or deletes), you can use the AbstractMapListener base class. For example, the following anonymous inner class prints out only the insert events for the cache:

cache.addMapListener(new AbstractMapListener()
    {
    public void entryInserted(MapEvent evt)
        {
        out(evt);
        }
    });

Configuring a MapListener for a Cache

If the listener should always be on a particular cache, then place it into the cache configuration using the listener element and Coherence will automatically add the listener when it configures the cache.

Cache configurations are often nested. Place the listener element on the outermost cache to ensure that the application is receiving all events for the cache, and not just those occurring on a backing map. See the advanced section below on Backing Map Events for details about what it means to place a listener on a backing map.

Gene's comment:
For all clustered cache schemes ("replicated-scheme", "distributed-scheme", etc), the top level scheme represents one or another concrete implementation of the NamedCache interface which serves as a client view of a clustered construct. It usually contains a "backing-map-scheme" that represents a Map implementation that serves as a local (one per node) implementation of the underlying data storage. Cache configuration allows you to configure without any coding a listener to either clustered or local cache view. Sometimes the same scheme could be used to configure a listener. To provide for this very advanced and unlikely scenario and allow user to specify which listener is desired, the DefaultConfigurableCacheFactory supports an [undocumented] attribute called "target" with valid values of "cache" and "backing-map". Any other value is ignored.

In case of the local cache those two views (cluster vs. local) collide. Without explicitly specifying which view should be listened to, a listener gets registered with both, resulting into the behavior reported by DB guys.

Signing up for Events on specific identities

Signing up for events that occur against specific identities (keys) is just as simple. For example, to print all events that occur against the Integer key "5":

cache.addMapListener(new EventPrinter(), new Integer(5), false);

So the following code would only trigger an event when the Integer key "5" is inserted or updated:

for (int i = 0; i < 10; ++i)
    {
    Integer key   = new Integer(i);
    String  value = "test value for key " + i;
    cache.put(key, value);
    }
posted on 2011-04-12 20:46  孟和2012  阅读(324)  评论(0编辑  收藏  举报