Application Events

Spring application contexts support a simple form of event publishing and subscription. Spring-specific and application-specific events may be broadcast to any interested beans. This functionality is essentially an implementation of the well-known Observer pattern. While simple is the operative word (the eventing mechanism is certainly not meant to be a competitor to the likes of JMS), this functionality is still useful for a number of use cases.

All events to be published and received with the event framework must extend the ApplicationEvent class, which is itself a subclass of the standard java.util.EventObject class. In order to automatically receive events, a bean must simply implement the ApplicationListener interface and be deployed into the application context. It will be recognized by the context, and receive all events that are published through the context:

 public interface ApplicationListener extends EventListener {    void onApplicationEvent(ApplicationEvent event); } 

Spring includes three standard events:

  • ContextRefreshEvent: This event will be published when the application context gets initialized or refreshed, specifically after all bean definitions have been loaded, and any pre- instantiation of singletons is completed, including injection of dependencies. Essentially, the context is ready for use.

  • ContextClosedEvent: This event will be published when the context has been closed, typically as a result of a close() call. It will actually be called after the destroy method has been called on all singletons.

  • RequestHandledEvent: This event will be published within a WebApplicationContext by the FrameworkServlet from Spring's web MVC code after a request has been handled by the web MVC code. This event is fairly agnostic to web layer technology, so could also be fired by application code, if desired, when using another web framework.

Publishing custom events is straightforward. Application contexts implement the ApplicationEventPublisher interface, whose publishEvent() method may be called for this purpose. A bean that wants to use the application context as an event publisher may implement the ApplicationEventPublisherAware interface, and will automatically be called back by the application context at initialization time with a reference to the application context as the ApplicationEventPublisher. For new code which doesn't already use the context for other purposes, publishing events through the ApplicationEventPublisher interface, as opposed to ApplicationContext directly, is preferred because it will reduce coupling to the context.

Let's look at an example of publishing and receiving events. Consider a Spring-based deployment in which there is a need for a remote monitoring agent to receive a periodic heartbeat signal from the Spring-based app to know that it's still running. We decide to use a timer task to create the heartbeat. Because it's likely there will be multiple parties interested in using the heartbeat, we decide to publish it as an event, for which any interested parties can listen, including in this case a bean that notifies the remote monitoring agent.

First we create the heartbeat timer task as a subclass of java.util.TimerTask. When it executes, it publishes a HeartBeat event. As the class implements ApplicationEventPublisherAware, it automatically receives the context it is deployed into as the event publisher:

 public class HeartbeatTask extends TimerTask implements ApplicationEventPublisherAware {        private ApplicationEventPublisher eventPublisher;        public void run() {     HeartbeatEvent event = new HeartbeatEvent(this);     eventPublisher.publishEvent(event);   }        public void setApplicationEventPublisher(ApplicationEventPublisher eventPublisher) {     this.eventPublisher = eventPublisher;   } } 

This can be configured very simply, as shown below:

 <bean  /> 

Now we use Spring's convenient ScheduledTimerTask and TimerFactoryBean to schedule the task to run every second after the application context starts up:

 <bean        >   <property name="timerTask"><ref local="heartbeatTask"/></property>   <property name="period"><value>1000</value></property> </bean>      <bean        >   <property name="scheduledTimerTasks">     <list>       <ref local="scheduledTask"/>     </list>   </property> </bean> 

Note that the heartBeatTask bean is shown standalone for clarity, but you would probably want to make it an inner bean of timerFactory because it is needed there only. Please see the JavaDocs of these classes for more information, but essentially, the initialization of the TimerFactoryBean (which will happen when singletons are pre-instantiated) triggers it to start the specified scheduled tasks.


Note also that Spring allows much more comprehensive scheduling via the third-party Quartz library.

At this point, we are publishing heartbeat events once a second. We now need to catch them and forward them to the remote agent. We create an event listener for this purpose:

 public class HeartbeatForwarder implements ApplicationListener {        public void onApplicationEvent(ApplicationEvent event) {     if (event instanceof HeartbeatEvent) {     // now tell the remote monitoring agent that we’re     ...     }   } } 

The forwarder implements ApplicationListener, so all that has to be done for it to receive the heartbeat events is to deploy it as a bean in the context:

 <bean  /> 

As you can see, publishing and receiving Spring or application events is quite easy.

Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188 © 2008-2017.
If you may any questions please contact us: