Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: REQUIRED | OPTIONAL | DETAIL: ELEMENT

## org.jboss.cache.pojo.notification.annotation
Annotation Type PojoCacheListener

    @Retention(value=RUNTIME)
    @Target(value=TYPE)
    public @interface PojoCacheListener

Indicates that a class should receive POJO notification events. The class may have zero or more annotated notification methods. Each method may have any name, but must have a method signature that contains the required event type (or super type).

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.

#### Delivery Semantics

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.

#### Transactional Semantics

Since the event is delivered during the actual cache call, the transactional outcome is not yet known. For this reason, events are always delivered, even if the changes they represent are discarded by their containing transaction. For applications that must only process events that represent changes in a completed transaction, `NotificationContext.getTransaction()` can be used, along with `TransactionCompletedEvent.isSuccessful()` to record events and later process them once the transaction has been successfully committed. Example 4 demonstrates this.

#### Threading Semantics

A listener implementation must be capable of handling concurrent invocations. Local notifications reuse the calling thread; remote notifications reuse the network thread.

Summary of Notification Annotations

Annotation | Event | Description
--- | --- | ---
`Attached` | `AttachedEvent` | An object was attached.
`Detached` | `DetachedEvent` | An object was detached.
`FieldModified` | `FieldModifiedEvent` | An attached object's field was modified.
`ListModified` | `ListModifiedEvent` | An attached list was modified.
`SetModified` | `SetModifiedEvent` | An attached set was modified.
`MapModified` | `MapModifiedEvent` | An attached map was modified.
`TransactionRegistered` | `TransactionRegisteredEvent` | A transaction was registered.
`TransactionCompleted` | `TransactionCompletedEvent` | A transaction was completed.

#### Example 1 - Method receiving a single event

        @PojoCacheListener
        public class SingleEventListener
        {
           @Attached
           public void handleAttached(AttachedEvent event)
           {
              System.out.println("Attached = " + event.getSource());
           }
        }

#### Example 2 - Method receiving multiple events

        @PojoCacheListener
        public class MultipleEventListener
        {
           @Attached
           @Detached
           public void handleAttachDetach(Event event)
           {
              if (event instanceof AttachedEvent)
                 System.out.println("Attached = " + event.getSource());
              else if (event instanceof DetachedEvent)
                 System.out.println("Detached = " + event.getSource());
           }
        }

#### Example 3 - Multiple methods receiving the same event

        @PojoCacheListener
        public class SingleEventListener
        {
           @Attached
           public void handleAttached(AttachedEvent event)
           {
              System.out.println("Attached = " event.getSource());
           }
           @Attached
           @Detached
           @FieldModified
           @ListModified
           @MapModified
           @SetModified
           @TransactionRegistered
           @TransactionCompleted
           public void handleAll(Event event)
           {
              System.out.println(event);
           }
        }

Example 4 - Processing only events with a committed transaction.

        @PojoCacheListener
        public class TxGuaranteedListener
        {
           private class TxEventQueue
           {
              private ConcurrentMap<Transaction, Queue<Event>> map = new ConcurrentHashMap<Transaction, Queue<Event>>();

              public void offer(Event event)
              {
                 Queue<Event> queue = getQueue(event.getContext().getTransaction());
                 queue.offer(event);
              }

              private Queue<Event> getQueue(Transaction transaction)
              {
                 Queue<Event> queue = map.get(transaction);
                 if (queue == null)
                 {
                    queue = new ConcurrentLinkedQueue<Event>();
                    map.putIfAbsent(transaction, queue);
                 }

                 return queue;
              }

              public Queue<Event> takeAll(Transaction transaction)
              {
                 return map.remove(transaction);
              }
           }

           private TxEventQueue events = new TxEventQueue();

           @Attached
           @Detached
           @FieldModified
           @ListModified
           @SetModified
           @MapModified
           public void handle(Event event)
           {
              events.offer(event);
           }

           @TransactionCompleted
           public void handleTx(TransactionCompletedEvent event)
           {
              Queue<Event> completed = events.takeAll(event.getContext().getTransaction());
              if (completed != null && event.isSuccessful())
                 System.out.println("Comitted events = " + completed);
           }
        }

Since:
  2.0
Author:
  Jason T. Greene
See Also:
  `CacheListener`

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: REQUIRED | OPTIONAL | DETAIL: ELEMENT

Copyright © 2007 JBoss, a division of Red Hat. All Rights Reserved.