SeamFramework.orgCommunity Documentation

Chapter 2. Servlet event propagation

2.1. Servlet context lifecycle listener
2.2. Application initialization
2.3. Servlet request lifecycle listener
2.4. Servlet response lifecycle listener
2.5. Servlet request context lifecycle listener
2.6. Session lifecycle listener
2.7. Session activation listener

By including the Seam 3 Servlet module in your web application (and performing the necessary listener configuration for pre-Servlet 3.0 environments) you will also have the servlet lifecycle events propagated to the CDI event bridge so you can observe them in your beans. Seam Servlet also fires some additional lifecycle events not offered by the Servlet API, such as when the response is initialized and destroyed.

These events correspond to the javax.servlet.ServletContextListener interface. The event object fired is a javax.servlet.ServletContext (since that's the only relevant information in the javax.servlet.ServletContextEvent object). There are two qualifiers available that can be used for selecting the lifecycle phase of the servlet context (initialize or destroy).

QualifierDescription
@InitializedQualifies the creation event
@DestroyedQualifies the destruction event

If you want to listen to both lifecycle events, leave out the qualifiers:

public void observeServletContext(@Observes ServletContext ctx) {

   // Do something with the "servlet context" object
}

If you are interested in only a particular one, use a qualifer:

public void observeServletContextInitialized(@Observes @Initialized ServletContext ctx) {

   // Do something with the "servlet context" object upon initialization
}

The name of the observer method is insignificant.

The ServletContext initialized event provides an excellent opportunity to perform startup logic as an alterative to using an EJB 3.1 startup singleton. Even better, you can configure the bean to be destroyed immediately following the initialization routine by leaving it as dependent scoped (dependent-scoped observers only live for the duration of the observe method invocation).

Here's an example of entering seed data into the database in a development environment (as indicated by a stereotype annotation named @Development).

@Stateless

@Development
public class SeedDataImporter {
   @PersistenceContext
   private EntityManager em;
   public void loadData(@Observes @Initialized ServletContext ctx) {
      em.persist(new Product(1, "Black Hole", 100.0));
   }
}

If you'd rather not tie yourself to the Servlet API, you can observe the WebApplication rather than the ServletContext. WebApplication is a informational object provided by Seam Servlet that holds select information about the ServletContext such as the application name, context path, server info and start time.

public void loadData(@Observes @Initialized WebApplication webapp) {

   ...
}

You can also use WebApplication with the @Destroyed qualifier to be notified when the web application is stopped.

These events correspond to the javax.servlet.ServletRequestListener interface. The event object fired is a javax.servlet.ServletRequest (since that's the only relevant information in the javax.servlet.ServletRequestEvent object. There are two qualifiers available that can be used for selecting the lifecycle phase of the request (initialize or destroy) and one to filter the observer based on the servlet path.

QualifierDescription
@InitializedQualifies the initialization event
@DestroyedQualifies the destruction event
@PathQualifies the servlet path of the request (no leading slash)

If you want to listen to both lifecycle events, leave out the qualifiers.

public void observeRequest(@Observes ServletRequest request) {

   // Do something with the servlet "request" object
}

If you are interested in only a particular one, use a qualifer

public void observeRequestInitialized(@Observes @Initialized ServletRequest request) {

   // Do something with the servlet "request" object upon initialization
}

You can also listen specifically for a javax.servlet.http.HttpServletRequest simply by changing the expected event type.

public void observeRequestInitialized(@Observes @Initialized HttpServletRequest request) {

   // Do something with the HTTP servlet "request" object upon initialization
}

You can associate an observer with a particular servlet request path (exact match, dropping the leading slash).

public void observeRequestInitialized(@Observes @Initialized @Path("offer") HttpServletRequest request) {

   // Do something with the HTTP servlet "request" object upon initialization
   // only when servlet path /offer is requested
}

The name of the observer method is insignificant.

The Servlet API does not provide a listener for accessing the lifecycle of a response. Therefore, Seam Servlet simulates a response lifecycle listener using CDI events. These events parallel those provided by the javax.servlet.ServletRequestListener inteface. The event object fired is a javax.servlet.ServletResponse. There are two qualifiers available that can be used for selecting the lifecycle phase of the response (initialize or destroy) and one to filter the observer based on the servlet path.

QualifierDescription
@InitializedQualifies the initialization event
@DestroyedQualifies the destruction event
@PathQualifies the servlet path of the request (no leading slash)

If you want to listen to both lifecycle events, leave out the qualifiers.

public void observeResponse(@Observes ServletResponse response) {

   // Do something with the servlet "response" object
}

If you are interested in only a particular one, use a qualifer

public void observeResponseInitialized(@Observes @Initialized ServletResponse response) {

   // Do something with the servlet "response" object upon initialization
}

You can also listen specifically for a javax.servlet.http.HttpServletResponse simply by changing the expected event type.

public void observeResponseInitialized(@Observes @Initialized HttpServletResponse response) {

   // Do something with the HTTP servlet "response" object upon initialization
}

If you need access to the ServletRequest and/or the ServletContext objects at the same time, you can simply add them as parameters to the observer methods. For instance, let's assume you want to manually set the character encoding of the request and response.

public void setupEncoding(@Observes @Initialized ServletResponse res, ServletRequest req) throws Exception {

   if (this.override || req.getCharacterEncoding() == null) {
      req.setCharacterEncoding(encoding);
      if (override) {
         res.setCharacterEncoding(encoding);
      }
   }
}

The name of the observer method is insignificant.

Rather than having to observe the request and response as separate events, or include the request object as an parameter on a response observer, it would be convenient to be able to observe them as a pair. That's why Seam Servlet fires an synthetic lifecycle event for the wrapper type ServletRequestContext. The ServletRequestContext holds the ServletRequest and the ServletResponse objects, and also provides access to the ServletContext. There are two qualifiers available that can be used for selecting the lifecycle phase of the request context (initialize or destroy) and one to filter the observer based on the servlet path.

QualifierDescription
@InitializedQualifies the initialization event
@DestroyedQualifies the destruction event
@PathQualifies the servlet path of the request (no leading slash)

Let's revisit the character encoding observer and examine how it can be simplified by this event:

public void setupEncoding(@Observes @Initialized ServletRequestContext ctx) throws Exception {

   if (this.override || ctx.getRequest().getCharacterEncoding() == null) {
      ctx.getRequest().setCharacterEncoding(encoding);
      if (override) {
         ctx.getResponse().setCharacterEncoding(encoding);
      }
   }
}

You can also observe the HttpServletRequestContext to be notified only on HTTP requests.

Since observers that have access to the response can commit it, an HttpServletRequestContext observer that receives the initialized event can effectively work as a filter or even a Servlet. Let's consider a primitive welcome page filter that redirects visitors to the start page:

public void redirectToStartPage(@Observes @Path("") @Initialized HttpServletRequestContext ctx)

      throws Exception {
   String startPage = ctx.getResponse().encodeRedirectURL(ctx.getContextPath() + "/start.jsf");
   ctx.getResponse().sendRedirect(startPage);
}

Now you never have to write a Servlet listener, Servlet or Filter again!

These events correspond to the javax.servlet.HttpSessionListener interface. The event object fired is a javax.servlet.http.HttpSession (since that's the only relevant information in the javax.servlet.http.HttpSessionEvent object). There are two qualifiers available that can be used for selecting the lifecycle phase of the session (initialize or destroy).

QualifierDescription
@InitializedQualifies the creation event
@DestroyedQualifies the destruction event

If you want to listen to both lifecycle events, leave out the qualifiers. Note that omitting all qualifiers will observe all events with a HttpSession as event object.

public void observeSession(@Observes HttpSession session) {

   // Do something with the "session" object
}

If you are interested in only a particular one, use a qualifer

public void observeSessionInitialized(@Observes @Initialized HttpSession session) {

   // Do something with the "session" object upon being initialized
}

The name of the observer method is insignificant.

These events correspond to the javax.servlet.HttpSessionActivationListener interface. The event object fired is a javax.servlet.http.HttpSession (since that's the only relevant information in the javax.servlet.http.HttpSessionEvent object). There are two qualifiers available that can be used for selecting the activation or passivation of the session.

QualifierDescription
@DidActivateQualifies the activation event
@WillPassivateQualifies the passivation event

If you want to listen to both lifecycle events, leave out the qualifiers. Note that omitting all qualifiers will observe all events with a HttpSession as event object.

public void observeSession(@Observes HttpSession session) {

   // Do something with the "session" object
}

If you are interested in only a particular one, use a qualifer

public void observeSessionCreated(@Observes @WillPassivate HttpSession session) {

   // Do something with the "session" object when it's being passivated
}

The name of the observer method is insignificant.