22 Listeners

Pravin Jain

Introduction

 

As a web developer we can create Servlets, Filters and we can also develop Listeners. It is another kind of Java component we can add in our web application. There can be various kind of Listeners created and the main purpose of the Listener is we should be able to do certain things when application starts for example or whenever a new request arrives. So there are various events which occur within the web application within the container or when a web application is being used.

 

Let us see the events for which we can write the various kind of Listeners. We know how the GUI event is handled, we know event delegation model where the Listener is there for handling events. Whenever we write the Listener we need to register it with the event source, in the case of web application, we do not create objects of our components, we understand that the components are not directly created by us but it is going to be created by the container. when the container starts it is the one who is going to create all the components. So we don’t have the chance of actually adding the listeners. So what we normally will be doing here is we don’t have to write the add listeners, but we simply write the class which implements the appropriate listener which would handle a particular kind of event.

 

We don’t have to write the code for add this listener, create the object of the class and add this listener but what we have to do is, we have our deployment descriptor and there we need to make some entry saying i have got the particular Listener by which we can say that this is a particular class by which we are implementing the listener which is known to the web container and then the container would do the registry of the listener with the appropriate source and invoking the appropriate methods in the listener at the appropriate time. Some of the most commonly used listener we are going to see here.

 

Servlet Context Listener

 

Let us say, we might be interested in doing certain things whenever our application starts or whenever there is shutdown of the application, so for that we have got the Listener here called ServletContextListener. In ServletContextListener we have got two methods: public void contextInitialized(ServletContextEvent sce) public void contextIDestroyed(ServletContextEvent sce)

 

contextInitialised is automatically invoked whenever the application starts. We understand that the container creates the object of ServletContext, it invokes this method if it finds that there is some Listener of type ServletContextListener, which has been registered here.

 

If we can write our listener which implements the method called contextInitialised(). ServletContextEvent is a class which extends from the EventObject of java.util package. This one is in our javax.servlet package both ServletContextEvent and ServletContextListener. Sometimes for administrative reasons you might stop the application and start it all over again, So each time the application starts, we know it creates the object of ServletContext and when the ServletContext object is created it would invoke the method called contextInitialised().

 

If someone stops the application or the contaiiner is being shutdown we have the method called contextDestroyed() being invoked on our ServletContextListener.

 

public void contextDestroyed(ServletContextEvent  sce) ServletContextEvent  has the method called getServletContext(). public ServletContext getServletContext()

 

Let us say, we want to create the objects on the start of the application for certain reasons, eg. for the jdbc connection. We have to give some parameters for the jdbc connection. the driver class name such things can be set as parameters and you might like to have the creation of the connection object which is being shared or any such objects which are being shared, for which you might have the context parameter in our web.xml file and you would like to read and create certain objects and make them available. In such a case you could have this method called contextInitialised() override this method in which we have the ServletContextEvent object available as the method parameter and from there we can get the ServletContext object and setup our object.

 

Servlet Context Attribute Listener 

 

Someone might like to keep track of what are the objects being shared, the attributes being added or removed from my ServletContext. So we have another listener here ServletContextAttributeListener, it is an interface. This interface has three methods:

 

public void attributeAdded(ServletContextAttributeEvent scae)

public void attributeRemoved(ServletContextAttributeEvent scae)

public void attributeReplaced(ServletContextAttributeEvent scae)

 

They have parameter ServletContextAttributeEvent. This class extends from our ServletContextEvent class and from this class we know we can get the ServletContext object. Other method here is:

 

public String getAttributeName()

public Object getAttributeValue()

 

So we can get the attribute name and object in our application. So we can write a listener which listens to any changes taking place in the list of objects being shared in the ServletContext. So whatever the attribute added it would trigger the method called attribute Added.

 

Same way Someone removes the attribute it would trigger the method called attributeRemoved. If we are adding the attribute, and if the name being used is something whch is already existing it would invoke the method called  attributeReplaced.

 

Servlet Request Listener 

 

Similarly we have other listeners which are specific to http protocol. So in javax.servlet.http package we have got particular listener interface. For example you are interested in tracking how long my request take the starting and the processing ends i.e. when does the response actually gets deliverd to the client. May be you would like to log them or time them. We do have a listener here for that called ServletRequestListener in javax.servlet package. This listener has got the two methods here:

 

public void requestInitialised(ServletRequestEvent sre)

 

whenever  any  new  requests  arrives  from  the  client  it  uses  this  method.  We  have  this  class ServletRequestEvent in the javax.servlet package. In this we have method called:

 

public String getServletRequest()

 

which is the request object which has been created. The parameters in the request are this is how available to the listener. So both the objects ServletRequest and ServletContext are available to us over here.

 

public void requestDestroyed(ServletRequestEvent sre)

 

When the processing is over and the response is sent back to the client at that time this method is invoked.

 

Servlet Request Attribute Listener 

 

We  also  have  another  listener  called  ServletRequestAttributeListener  which  would  listen  to  the changes in the list of objects shared by in the ServletRequest.

 

As we have seen earlier like ServletRequest has the methods like:

 

public void addAttribute(String name, Object value)

public void removeAttribute(String name)

public Object getAttribute(String name)

public Enumeration<String> getAttributeNames()

 

Here we have got ServletRequestAttributeListener this listener has got methods called:

 

public void attributeAdded(ServletRequestAttributeEvent srae)

public void attributeRemoved(ServletRequestAttributeEvent srae)

public void attributeReplaced(ServletRequestAttributeEvent srae)

 

Similar methods but the parameter here are ServletRequestAttributeEvent, it is extending from ServletRequestEvent. So, here also we get the object of the ServletRequest as well as we can get the name of the attribute and the attribute which has been added removed or which is being replaced that object is available.

 

So, we got methods for getting hold of the request object and the attribute name and the value of the attribute. So similar to the ServletContextAttributeListener we have our ServletRequestAttributeListener. But this is related to ServletRequest.

 

HttpSessionListener 

 

So these are in the javax.servlet package. So four listeners here going to the http specific thing. Another place where the objects are being shared is nothing but the HttpSession. We have seen earlier how HttpSession is useful for tracking the client. So now here also we have got listeners which will be related to the HttpSession. The HttpSession related listeners we have one of the listener here is the HttpSessionListener which is related to the creation of a new session and destruction of a session whenever session is getting destroyed.

 

HttpSessionAttributeListener and HttpSessionBindingListener 

 

Similarly another one is related to the attributes. Now this attribute related listener is also there which would sound similar to the attribute listeners we have seen earlier. As far as these listeners are concerned most of these listeners were added in the specifications version 2.3. But as far as the HttpSession is concerned we had a listener related to HttpSession right from servlet specification 1.1. So in servlet specification 1.1 itself we had a listener which would be related to what we now call as an attribute. i.e. if someone is trying to share objects within the HttpSession and someone wants to listen changes in the list of objects being shared i.e whenever an object is being bound or unbound, it used to be called as bound and unbound, so we have old listener, it was there right from specification 1.1. So, we have one listener interface which is HttpSessionBindingListener and the corresponding event is HttpSessionBindingEvent. These are legacy events. As far as HttpSessionBindingListener is concerned, we have almost similar thing being done by the HttpSessionAttributeListener.

 

HttpSession Activation Listener 

 

You might be deploying a web container in a cluster, so that its being used in a cluster. So there is a question of managing the session and their attributes in a cluster which might go across various hosts in the cluster. In a cluster we have multiple machines being used as if it is one single server. The request go to one server at one time but for the same client he has to have the same list of attributes even if the request is being handled by the different node of the cluster. So we have like activation and passivation taking place of the HttpSession. HttpSession becomes active at one place for this client and it switches when the request comes for another time, from the same client. So we got  listener indicating for the purpose that there is a switching taking place from one particular node to another node within the cluster, as far as the HttpSession is concerned.

 

Listeners related to the HttpSession:

 

HttpSessionListener – We have these two methods:

 

public void sessionCreated(HttpSessionEvent e)

public void sessionDestroyed(HttpSessionEvent e)

 

In the HttpSessionEvent we will have the method to get the session object and from the session we can get hold of the SessionContext, there is a method to get the context as we have seen in the earlier module. This is useful when we are interested in knowing, when the particular session starts and when the particular session ends. sessionDestroyed is particularly useful because many times in our application we understand that may be you might have some application where someone logs in, we start tracking him, so we create a session at that time and when somebody logs out we will naturally try to destroy the session. And when it is logging out, we have certain activities to be done if it done by using servlet and during logout.

 

But instead of that it might be the better idea to have the logout related things, that yes this client is no longer there and I am no longer going to track this client. Instead of doing it there such activities could be done on sessionDetroyed. This is something like even if it is not using the logout the session may get expire and if the session is expiring this is the method which is getting invoked on the http session. That way the use of sessionDestroyed is recommended instead of doing something specific on destruction and removing session.

 

So whenever a new session is being created or destroyed this is the interface which would be useful. There are two things possible

 

one is the legacy interface called HttpSessionBindingListener or second is the HttpSessionAttributeLoistener

 

Boih of them use the same event type i.e HttpSessionBindingEvent, ie. our legacy class which is still being used by our new listener HttpSessionAttributeListerner. Similar to the other attribute listener this has the same methods:

 

public void attributeAdded(HttpSessionBindingEvent e)

public void attributeRemoved(HttpSessionBindingEvent e)

public void attributeReplaced(HttpSessionBindingEvent e)

 

The parameter here is HttpSessionBindingEvent, it has methods:

 

public String getName()

public Object getValue()

public HttpSession getSession()

 

The getName() will give us the name of the attribute being added, getValue() gives us the object and getSession() gives us the corresponding session in which this attribute was added, removed or replaced. This is similar to the other attribute listerner.

 

In this you might come across some legacy code where in someone might be using HttpSessionBindingListener. If it is HttpSessionBindingListener in that case the two methods which we have in this interface are :

 

public void sessionBound(HttpSessionBindingEvent e)

public void sessionUnbound(HttpSessionBindingEvent e)

 

sessionBound is when someone adds the attribute, and the parameter here is HttpSessionBindingEvent which have the methods called getName(), getValue() and getSession().

 

Here another thing is if you have an application which has been deployed in the cluster then what would happen? In a cluster there are multiple nodes as a part of a cluster, there may be single point of entry which would be a controlling node where most of the request would come and that controlling node would see depending on the load which node should do the processing where the request should actually be going. So, if you think of a particular client in case of a non cluster where we have a single server machine, we have one place where the ServletContext exists, One place where all the HttpSession objects are created – not much of the problem.

 

But when we have clustering, it is the similar context object which has to be created everywhere. As far as ServletContext is concerned usually when it is added, normally at the start of the application. So whenever it starts a similar copy of objects is created at all the nodes so we have multiple copies of the ServletContext one per node of the cluster. But if we look at the HttpSession object, it gets started because the container decided to start tracking and it is because of the request that comes from the particular client. It was initiated by one of the request reaching one of the node. We might have several nodes in the cluster only one of the nodes has knowledge of this particular client being available. This particular client is being started to be tracked. You may have added some attributes in that particular session.

 

Now these attribute in HttpSession, which have added are available on a particular node. But what happens if the next request from the same client is to a different node for processing because of load balancing, let us say, controller deciding it has to go to a different node. If it goes to a different node what should happen? Should it create new session and all the attribute should be made available how do we manage that? No we don’t have to worry about it. Managing all this is actually the responsibility of the container. There is one important thing what actually is done by the container is. When a container realises that there is a request which is now being handled by a different node and there was a session object already for this particular client in such a case the container would have to manage that all the attribute which are available at the earlier nodes, all this attributes at the similar session actually being recreated all the attributes in the new node where the processing is now going to take place. These objects have to be shifted and this is done on TCP/IP connection. That means it is stream based connections on which all these objects would travel from one machine to the other machine.

 

So if any such thing has to be done our objects should be Serializable. So we have to be careful that any objects which we are managing in the HttpSession objects as far as clustered applications are concerned it is a must that you should have them as an Serializable object otherwise the objects are not going to be available when the shifting of the object has to take place from one node to the other node. In a cluster it will not work if you do not have your attributes added in the HttpSession as not being Serializable. Here we have a listener called HttpSessionActivationListener which has got two mehtods:

 

public void sessionDidActivate(HttpSessionEvent e)

public void sessionWillPassivate(HttpSessionEvent e)

 

Parameter to them HttpSessionEvent. sessionDidActivate is being invoked on the node on which the request is now going to be processed. As it shifts from one node to another. Yes it is here that it has become active. sessionWillPassivate will be invoked on the node on which the HttpSession was last active. Because now it is being passivated on one node and being activated on another node.

 

So we have listeners which keeps track of the nodes, ie., how the shifting of session from one node to another node is taking place.

 

Suggested Reading:

  1. Core Servlets and Java Server Pages Volume2 by Marty Hall & Larry Brown, Second Edition, Pearson Education.
  2. Inside Servlets by Dustin R Callaway, Pearson Education.
  3. Java Server Programming for Professionals by Ivan Bayross, Sharanam Sh ah, Cynhthia Bayross and Vaishali Shah Shroff Publishers and Distributros.
  4. http://download.oracle.com/otndocs/jcp/servlet-3.0-fr-oth-JSpec/