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



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