[jboss-cvs] JBossCache/src/org/jboss/cache/notifications/annotation ...
Manik Surtani
manik at jboss.org
Fri Jul 13 05:42:24 EDT 2007
User: msurtani
Date: 07/07/13 05:42:24
Modified: src/org/jboss/cache/notifications/annotation
CacheListener.java
Log:
Updated documentation
Revision Changes Path
1.2 +244 -13 JBossCache/src/org/jboss/cache/notifications/annotation/CacheListener.java
(In the diff below, changes in quantity of whitespace are not shown.)
Index: CacheListener.java
===================================================================
RCS file: /cvsroot/jboss/JBossCache/src/org/jboss/cache/notifications/annotation/CacheListener.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- CacheListener.java 28 Jun 2007 16:53:36 -0000 1.1
+++ CacheListener.java 13 Jul 2007 09:42:24 -0000 1.2
@@ -6,30 +6,261 @@
import java.lang.annotation.Target;
/**
- * Class-level annotation used to annotate an object as being a valid cache listener. Used with the {@link org.jboss.cache.Cache#addCacheListener(Object)} and related APIs.
+ * Class-level annotation used to annotate an object as being a valid cache listener. Used with the
+ * {@link org.jboss.cache.Cache#addCacheListener(Object)} and related APIs.
* <p/>
- * Note that even if a class is annotated with this annotation, it still needs method-level annotation (such as {@link org.jboss.cache.notifications.annotation.CacheStarted})
- * to actually receive notifications.
+ * Note that even if a class is annotated with this annotation, it still needs method-level annotation (such as
+ * {@link org.jboss.cache.notifications.annotation.CacheStarted}) to actually receive notifications.
* <p/>
- * Objects annotated with this annotation - listeners - can be attached to a running {@link org.jboss.cache.Cache} so users can be notified of {@link org.jboss.cache.Cache} events.
+ * Objects annotated with this annotation - listeners - can be attached to a running {@link org.jboss.cache.Cache} so
+ * users can be notified of {@link org.jboss.cache.Cache} events.
* <p/>
- * It is important to note that notifications happen in the same process thread as the invocation to the cache. This means 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
+ * <p/>
+ * 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.
+ * </p>
+ * <p/>
+ * <h4>Delivery Semantics</h4>
+ * <p/>
+ * 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.
+ * </p>
+ * <p/>
+ * <h4>Transactional Semantics</h4>
+ * <p/>
+ * Since the event is delivered during the actual cache call, the transactional
+ * outcome is not yet known. For this reason, <i>events are always delivered, even
+ * if the changes they represent are discarded by their containing transaction</i>.
+ * For applications that must only process events that represent changes in a
+ * completed transaction, {@link org.jboss.cache.notifications.event.TransactionalEvent#getTransaction()} can be used,
+ * along with {@link org.jboss.cache.notifications.event.TransactionCompletedEvent#isSuccessful()} to record events and
+ * later process them once the transaction has been successfully committed.
+ * Example 4 demonstrates this.
+ * </p>
+ * <p/>
+ * <h4>Threading Semantics</h4>
+ * <p/>
+ * A listener implementation must be capable of handling concurrent invocations. Local
+ * notifications reuse the calling thread; remote notifications reuse the network thread.
+ * </p>
+ * <p/>
+ * 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.
+ * </p>
* <p/>
- * In addition, any locks acquired for the operation being performed will still be held for the callback. This needs to be kep in mind
+ * 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.
+ * </p>
+ * <p/>
+ * <p/>
+ * <b>Summary of Notification Annotations</b>
+ * <table border="1" cellpadding="1" cellspacing="1" summary="Summary of notification annotations">
+ * <tr>
+ * <th bgcolor="#CCCCFF" align="left">Annotation</th>
+ * <th bgcolor="#CCCCFF" align="left">Event</th>
+ * <th bgcolor="#CCCCFF" align="left">Description</th>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link CacheStarted}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.CacheStartedEvent}</td>
+ * <td valign="top">A cache was started</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link CacheStopped}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.CacheStoppedEvent}</td>
+ * <td valign="top">A cache was stopped</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link NodeModified}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeModifiedEvent}</td>
+ * <td valign="top">A node was modified</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link NodeMoved}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeMovedEvent}</td>
+ * <td valign="top">A node was moved</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link NodeCreated}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeCreatedEvent}</td>
+ * <td valign="top">A node was created</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link NodeRemoved}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeRemovedEvent}</td>
+ * <td valign="top">A node was removed</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link NodeVisited}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeVisitedEvent}</td>
+ * <td valign="top">A node was visited</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link NodeLoaded}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeLoadedEvent}</td>
+ * <td valign="top">A node was loaded</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link org.jboss.cache.notifications.annotation.NodeEvicted}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeEvictedEvent}</td>
+ * <td valign="top">A node was evicted</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link org.jboss.cache.notifications.annotation.NodeActivated}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodeActivatedEvent}</td>
+ * <td valign="top">A node was activated</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link org.jboss.cache.notifications.annotation.NodePassivated}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.NodePassivatedEvent}</td>
+ * <td valign="top">A node was passivated</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link org.jboss.cache.notifications.annotation.ViewChanged}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.ViewChangedEvent}</td>
+ * <td valign="top">A view change event was detected</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link org.jboss.cache.notifications.annotation.CacheBlocked}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.CacheBlockedEvent}</td>
+ * <td valign="top">A cache block event was detected</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link CacheUnblocked}</td>
+ * <td valign="top">{@link org.jboss.cache.notifications.event.CacheUnblockedEvent}</td>
+ * <td valign="top">A cache unblock event was detected</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link TransactionRegistered}</td>
+ * <td valign@="top">{@link org.jboss.cache.notifications.event.TransactionRegisteredEvent}</td>
+ * <td valign="top">The cache has started to participate in a transaction</td>
+ * </tr>
+ * <tr>
+ * <td valign="top">{@link TransactionCompleted}</td>
+ * <td valign=@"top">{@link org.jboss.cache.notifications.event.TransactionCompletedEvent}</td>
+ * <td valign="top">The cache has completed it's participation in a transaction</td>
+ * </tr>
+ * <p/>
+ * </table>
+ * <p/>
+ * <h4>Example 1 - Method receiving a single event</h4>
+ * <pre>
+ * @CacheListener
+ * public class SingleEventListener
+ * {
+ * @CacheStarted
+ * public void doSomething(Event event)
+ * {
+ * System.out.println("Cache started. Details = " + event);
+ * }
+ * }
+ * </pre>
+ * <p/>
+ * <h4>Example 2 - Method receiving multiple events</h4>
+ * <pre>
+ * @CacheListener
+ * 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);
+ * }
+ * }
+ * </pre>
+ * <p/>
+ * <h4>Example 3 - Multiple methods receiving the same event</h4>
+ * <pre>
+ * @CAcheListener
+ * public class SingleEventListener
+ * {
+ * @CacheStarted
+ * public void handleStart(Event event)
+ * {
+ * System.out.println("Cache started");
+ * }
+ * <p/>
+ * @CacheStarted
+ * @CacheStopped
+ * @CacheBlocked
+ * @CacheUnblocked
+ * @ViewChanged
+ * public void logEvent(Event event)
+ * {
+ * logSystem.logEvent(event.getType());
+ * }
+ * }
+ * </pre>
+ * <p/>
+ * <p/>
+ * <b>Example 4 - Processing only events with a committed transaction.</b>
+ * <p/>
+ * <pre>
+ * @CacheListener
+ * public class TxGuaranteedListener
+ * {
+ * private class TxEventQueue
+ * {
+ * private ConcurrentMap<Transaction, Queue<Event>> map = new ConcurrentHashMap<Transaction, Queue<Event>>();
+ * <p/>
+ * public void offer(Event event)
+ * {
+ * Queue<Event> queue = getQueue(event.getContext().getTransaction());
+ * queue.offer(event);
+ * }
+ * <p/>
+ * private Queue<Event> getQueue(Transaction transaction)
+ * {
+ * Queue<Event> queue = map.get(transaction);
+ * if (queue == null)
+ * {
+ * queue = new ConcurrentLinkedQueue<Event>();
+ * map.putIfAbsent(transaction, queue);
+ * }
+ * <p/>
+ * return queue;
+ * }
+ * <p/>
+ * public Queue<Event> takeAll(Transaction transaction)
+ * {
+ * return map.remove(transaction);
+ * }
+ * }
+ * <p/>
+ * private TxEventQueue events = new TxEventQueue();
* <p/>
- * Also important to note is that all data maps passed in to most listener methods as a part of the {@link org.jboss.cache.notifications.event.Event}
- * implementation are usually read-only defensive copies of the actual data stored in the cache. Therefore it is safe to
- * assume that the collections are static snapshots. If changes to the cache data are to be triggered by such events,
- * make calls on the cache directly rather than attempting to change the data maps. See the javadocs on individual method-targeted
- * annotations for more details on what is passed in.
+ * @NodeModified
+ * @NodeMoved
+ * @NodeCreated
+ * @NodeRemoved
+ * public void handle(Event event)
+ * {
+ * events.offer(event);
+ * }
* <p/>
+ * @TransactionCompleted
+ * public void handleTx(TransactionCompletedEvent event)
+ * {
+ * Queue<Event> completed = events.takeAll(event.getTransaction());
+ * if (completed != null && event.isSuccessful())
+ * System.out.println("Comitted events = " + completed);
+ * }
+ * }
+ * </pre>
*
* @author <a href="mailto:manik at jboss.org">Manik Surtani</a>
+ * @author Jason T. Greene
* @see CacheStarted
* @see CacheStopped
* @see NodeModified
More information about the jboss-cvs-commits
mailing list