Bootstrapping JSF applications with SystemEvents

SystemEvents offer a nice way to respond to events like system startup or  -teardown.

A frequent use case is to log if the application startup was successfull and if all neccessary resources are available. If a problem occurs during startup the application might respond to it or just send a mail to the developers to notify them about the problem.

I also prefer to have a debugging phase listener (see this post from BalusC) in my application. This listener should only be registered if the application is in development stage. The following example shows how to use SystemEventListeners to register the PhaseListener:

public class BootstrappingListener implements SystemEventListener {

	private static final java.util.logging.Logger LOG = java.util.logging.Logger.getLogger(BootstrappingListener.class.getSimpleName());

	@Override
	public boolean isListenerForSource(final Object obj) {
		boolean result = false;
		result = obj instanceof Application;
		return result;
	}

	@Override
	public void processEvent(final SystemEvent event) throws AbortProcessingException {

		if (event instanceof PostConstructApplicationEvent) {
			performBootstrap((PostConstructApplicationEvent) event);
		} else if (event instanceof PreDestroyApplicationEvent) {
			performTearDown((PreDestroyApplicationEvent) event);
		}

	}

	private void performBootstrap(final PostConstructApplicationEvent event) {

		Application application = event.getApplication();
		ProjectStage stage = application.getProjectStage();

		if (ProjectStage.Development == stage) {

			LifecycleFactory lcFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
			Lifecycle lc = lcFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
			lc.addPhaseListener(new DebugPhaseListener());

		}

		// do other stuff related to bootstrapping:
		// 1) check for availablity of web services
		// 2) init ressources
		// ...

		LOG.info("Application startup");
	}

	private void performTearDown(final PreDestroyApplicationEvent event) {

		LOG.info("Application destroyed");

	}
}

The class implements SystemEventListener, thus the methods isListenerForSource() and processEvent() need to be implemented. The first method recieves an object representing the application, so all we have to do is to make sure that it is a valid instance of javax.faces.application.Application. The processEvent method is where stuff happens: In the implementation above the method delegates to another method, depending on the event to handle. The JSF implementation will publish javax.faces.event.PostConstructApplicationEvent on application startup and javax.faces.event.PreDestroyApplicationEvent on shutdown.

In the example, processEvent() calls performBootstrap() to perform several actions on application startup:

  1. A PhaseListenerfor debugging purposes is installed if  the current ProjectStage is ‘DevelopmentStage’ (Note: you can  define the ProjectStage by setting the context-parameter “javax.faces.PROJECT_STAGE” to either one of “Development”,”Production”,”SystemTest” or “UnitTest”)
  2. Other tasks like:
    1. checking the environment for required ressources (e.g. availability of web-services)
    2. initialisation of resources (e.g. creation and pre-initialization of managed beans)
  3. Write to a log file.

The same principle applys to PreDestroyApplicationEvents. In the example above only logging output is created but other scenarios are possible, including notification of developers and/or admins via email / instant messaging / Twitter.

To have the listener called, it needs to be registered in faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?>

<faces-config
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
    version="2.0">

    <application>

	    <system-event-listener>

	    	<system-event-listener-class>
	    		de.oio.jsf.BootstrappingListener
	    	</system-event-listener-class>

	    	<system-event-class>
	    		javax.faces.event.PostConstructApplicationEvent
	    	</system-event-class>

	    </system-event-listener>

	    <system-event-listener>

	    	<system-event-listener-class>
	    		de.oio.jsf.BootstrappingListener
    		</system-event-listener-class>

	    	<system-event-class>
	    		javax.faces.event.PreDestroyApplicationEvent
    		</system-event-class>

	    </system-event-listener>

    </application>

</faces-config>

The example uses the same class for both events but this only for convenience. Several listener classes may be registered for both events.

While event listeners may also be defined using annotations, this is unfortunately not an option for PostConstructApplicationEvents.

Short URL for this post: http://blog.oio.de/kEYQP
This entry was posted in Build, config and deploy, Java EE, Java Web Frameworks and tagged , , . Bookmark the permalink.

One Response to Bootstrapping JSF applications with SystemEvents

  1. edburns00 says:

    Yes, the reason you can’t use an annotation for the
    PostConstructApplicationEvent is because the annotation scanning doesn’t
    happen soon enough. I have to point out, though, that CDI 1.1 probably
    has some events that you can listen for with the same semantics.

    Does this work?

    import javax.enterprise.context.Dependent;
    import javax.enterprise.event.Observes;
    import javax.enterprise.context.Initialized;

    public class OnStartup {

    public void observeStartup(@Observes @Initialized(ApplicationScoped.class)) {
    // called at startup;
    }
    }

Leave a Reply