Develop event listeners
Application components that listen for events can use the EventSource.addListener() method to register an event listener object (a type of asynchronous bean) with the event source to which the events will be published. An event source also can fire events in a type-safe manner using any interface.
Notifications between components within a single EAR file are handled by a special event source. See the Using the application notification service topic for more information about notifications.
- Create an event listener object, which can be any type. For example, see the following interface code:
interface SampleEventGroup { void finished(String message); } class myListener implements SampleEventGroup { public void finished(String message) { // This will be called when we 'finish'. } }
- Register the event listener object with the event source. For example, see the following code:
InitialContext ic = ...; EventSource es = (EventSource)ic.lookup("java:comp/websphere/ApplicationNotificationService"); myListener l = new myListener(); es.addListener(l);This enables the myListener.finished() method to be called whenever the event is fired. The following code example shows how this event might be fired:InitialContext ic = ...; EventSource es = (EventSource)ic.lookup("java:comp/websphere/ApplicationNotificationService"); myListener proxy = es.getEventTrigger(myListener.class); // fire the 'event' by calling the method // representing the event on the proxy proxy.finished("done");
Example
We can fire a listenerCountChanged event that produces a proxy for the interface on which the method fires. Calling the method corresponding to the event on the proxy implements the EventSourceEvents interface. The same proxy can be used to send multiple events simultaneously.
The following code example demonstrates how to fire a listenerCountChanged event:
// Imagine this snippet inside an EJB or servlet method. // Make an inner class implementing the required event interfaces. EventSourceEvents listener = new Object() implements EventSourceEvents.class { void listenerCountChanged(EventSource es, int old, int newCount) { try { InitialContext ic = new InitialContext(); // Here, the asynchronous bean can access an environment variable of // the component which created it. int i = (Integer)ic.lookup("java:comp/env/countValue").intValue()); if(newCount == i) { // do something interesting } // call this event when the following code executes: } catch(NamingException e) { } } void listenerExceptionThrown( EventSource es, Object listener, String methodName, Throwable exception) { } void unexpectedException(EventSource es, Object runnable, Throwable exception) { } } // register it. es.addListener(listener); ... // now fire an event which the previous listener receives. EventSourceEvents proxy = (EventSourceEvents) es.getEventTrigger(EventSourceEvents.class, false); proxy.listenerCountChanged(es, 0, 1); // now, fire another event, we can call any of the methods. proxy.listenerCountChanged(es, 4, 5);The output in this example is a proxy for the interface on which the method fires. Then, call the method corresponding to the event on the proxy. This action causes the same method with the same parameters to be called on any event listeners that implement the EventSourceEvents interface and that were previously registered with the EventSource "es". The same proxy can be used to send multiple events simultaneously.
The boolean parameter on the getEventTrigger() method is sameTransaction. When the sameTransaction parameter is false, a new transaction is started for each event listener invoked and these event listeners can be called in parallel to the caller. However, the event() method is blocked until all of the event listeners are notified. If the sameTransaction parameter is true, then the current transaction (if any) on the thread is used for all of the event listeners. The event listeners share the transaction of the method that fired the event. For that reason, all event listeners must run serially in an undetermined order. The order that listeners are called is undefined, and the order in which listeners are registered does not act as a guide for the order used at run time. The method on the proxy does not return until all of the event listeners are called, which means that this action is a synchronous operation.
The parameters that references and listeners pass do not interfere with the function of these references, unless you configure the method to do so. For example, event listeners can be used as collaborators and add data to a map, which was a parameter. Each event listener runs on its own transaction, independent of any transaction that is active on the thread. Extreme care must be taken when the sameTransaction parameter is false because the parameters can be accessed by multiple threads.
- Use the application notification service
During the application lifetime, individual J2EE components (servlets or enterprise beans) within a single EAR file might need to signal each other. There is an event source in the java:comp namespace that is bound into all components within an EAR file that can be used for notification.
- Example: Firing a listenerCountChanged event
We can fire a listenerCountChanged event that produces a proxy for the interface on which the method fires. Calling the method corresponding to the event on the proxy implements the EventSourceEvents interface. The same proxy can be used to send multiple events simultaneously.