[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>
  + *    &#064;CacheListener
  + *    public class SingleEventListener
  + *    {
  + *       &#064;CacheStarted
  + *       public void doSomething(Event event)
  + *       {
  + *          System.out.println(&quot;Cache started.  Details = &quot; + event);
  + *       }
  + *    }
  + * </pre>
  + * <p/>
  + * <h4>Example 2 - Method receiving multiple events</h4>
  + * <pre>
  + *    &#064;CacheListener
  + *    public class MultipleEventListener
  + *    {
  + *       &#064;CacheStarted
  + *       &#064;CacheStopped
  + *       public void doSomething(Event event)
  + *       {
  + *          if (event.getType() == Event.Type.CACHE_STARTED)
  + *             System.out.println(&quot;Cache started.  Details = &quot; + event);
  + *          else if (event.getType() == Event.Type.CACHE_STOPPED)
  + *             System.out.println(&quot;Cache stopped.  Details = &quot; + event);
  + *       }
  + *    }
  + * </pre>
  + * <p/>
  + * <h4>Example 3 - Multiple methods receiving the same event</h4>
  + * <pre>
  + *    &#064;CAcheListener
  + *    public class SingleEventListener
  + *    {
  + *       &#064;CacheStarted
  + *       public void handleStart(Event event)
  + *       {
  + *          System.out.println(&quot;Cache started&quot;);
  + *       }
  + * <p/>
  + *       &#064;CacheStarted
  + *       &#064;CacheStopped
  + *       &#064;CacheBlocked
  + *       &#064;CacheUnblocked
  + *       &#064;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>
  + *    &#064;CacheListener
  + *    public class TxGuaranteedListener
  + *    {
  + *       private class TxEventQueue
  + *       {
  + *          private ConcurrentMap&lt;Transaction, Queue&lt;Event&gt;&gt; map = new ConcurrentHashMap&lt;Transaction, Queue&lt;Event&gt;&gt;();
  + * <p/>
  + *          public void offer(Event event)
  + *          {
  + *             Queue&lt;Event&gt; queue = getQueue(event.getContext().getTransaction());
  + *             queue.offer(event);
  + *          }
  + * <p/>
  + *          private Queue&lt;Event&gt; getQueue(Transaction transaction)
  + *          {
  + *             Queue&lt;Event&gt; queue = map.get(transaction);
  + *             if (queue == null)
  + *             {
  + *                queue = new ConcurrentLinkedQueue&lt;Event&gt;();
  + *                map.putIfAbsent(transaction, queue);
  + *             }
  + * <p/>
  + *             return queue;
  + *          }
  + * <p/>
  + *          public Queue&lt;Event&gt; 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.
  + *       &#064;NodeModified
  + *       &#064;NodeMoved
  + *       &#064;NodeCreated
  + *       &#064;NodeRemoved
  + *       public void handle(Event event)
  + *       {
  + *          events.offer(event);
  + *       }
    * <p/>
  + *       &#064;TransactionCompleted
  + *       public void handleTx(TransactionCompletedEvent event)
  + *       {
  + *          Queue&lt;Event&gt; completed = events.takeAll(event.getTransaction());
  + *          if (completed != null &amp;&amp; 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