Main Tutorials

Spring – How to do dependency injection in your session listener

Spring comes with a “ContextLoaderListener” listener to enable Spring dependency injection into session listener. In this tutorial, it revises this HttpSessionListener example by adding a Spring dependency injection a bean into the session listener.

1. Spring Beans

Create a simple counter service to print total number of sessions created.

File : CounterService.java


package com.mkyong.common;
 
public class CounterService{
 
	public void printCounter(int count){
		System.out.println("Total session created : " + count);
	}

}

File : counter.xml – Bean configuration file.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

	<bean id="counterService" class="com.mkyong.common.CounterService" />
	
</beans>

2. WebApplicationContextUtils

Uses “WebApplicationContextUtils” to get the Spring’s context, and later you can get any declared Spring’s bean in a normal Spring’s way.

File : SessionCounterListener.java


package com.mkyong.common;
 
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
 
public class SessionCounterListener implements HttpSessionListener {
 
     private static int totalActiveSessions;
 
     public static int getTotalActiveSession(){
           return totalActiveSessions;
     }
 
    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
           totalActiveSessions++;
           System.out.println("sessionCreated - add one session into counter");	
           printCounter(arg0);
    }
 
    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {
           totalActiveSessions--;
           System.out.println("sessionDestroyed - deduct one session from counter");	
           printCounter(arg0);
    }	
  
    private void printCounter(HttpSessionEvent sessionEvent){

          HttpSession session = sessionEvent.getSession();

          ApplicationContext ctx = 
                WebApplicationContextUtils.
                      getWebApplicationContext(session.getServletContext());

          CounterService counterService = 
                      (CounterService) ctx.getBean("counterService");

          counterService.printCounter(totalActiveSessions);
    }
}

3. Integration

The only problem is, how your web application know where to load the Spring bean configuration file? The secret is inside the “web.xml” file.

  1. Register “ContextLoaderListener” as the first listener to make your web application aware of the Spring context loader.
  2. Configure the “contextConfigLocation” and define your Spring’s bean configuration file.

File : web.xml


<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  
  <context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/Spring/counter.xml</param-value>
  </context-param>

  <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>
  </listener>

  <listener>
	<listener-class>
            com.mkyong.common.SessionCounterListener
        </listener-class>
  </listener>

  <servlet>
	<servlet-name>Spring DI Servlet Listener</servlet-name>
	<servlet-class>com.mkyong.common.App</servlet-class>
  </servlet>
 
  <servlet-mapping>
	<servlet-name>Spring DI Servlet Listener</servlet-name>
	<url-pattern>/Demo</url-pattern>
  </servlet-mapping>
  
</web-app>

File : App.java


package com.mkyong.common;
 
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
 
public class App extends HttpServlet{
 
  public void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException{
		
        HttpSession session = request.getSession(); //sessionCreated() is executed
        session.setAttribute("url", "mkyong.com"); 
        session.invalidate();  //sessionDestroyed() is executed
		  
        PrintWriter out = response.getWriter();
        out.println("<html>");
        out.println("<body>");
        out.println("<h1>Spring Dependency Injection into Servlet Listenner</h1>");
        out.println("</body>");
        out.println("</html>");	
		
   }
}

Start Tomcat, and access the URL “http://localhost:8080/SpringWebExample/Demo“.

output


sessionCreated - add one session into counter
Total session created : 1
sessionDestroyed - deduct one session from counter
Total session created : 0

See the console output, you get the counter service bean via Spring DI, and print the total number of sessions.

Conclusion

In Spring, the “ContextLoaderListener” is a generic way to integrate Spring Dependency Injection to almost all of the web application.

Download

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
18 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
sanjar
5 years ago

Hi,
I am trying to add the dependency of a spring managed class into my cutstom HTTPSessionListener. I have removed the listener entry from web.xml. sessionDestroyed method is getting called after any session expires but the dependency of xUserMgr is null hence it gives NULLPOINTEREXCEPTIN while calling – updateIsActiveStatusOfLoggedInUserWithHTTPSession.
@Component
public class RangerHttpSessionListener implements HttpSessionListener,ApplicationContextAware {

@Autowired
XUserMgr xUserMgr;

@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
if (applicationContext instanceof WebApplicationContext) {
((WebApplicationContext) applicationContext).getServletContext().addListener(this);
} else {
//Either throw an exception or fail gracefully, up to you
throw new RuntimeException(“Must be inside a web application context”);
}
}

private static CopyOnWriteArrayList listOfSession = new CopyOnWriteArrayList();

@Override
public void sessionCreated(HttpSessionEvent event) {
listOfSession.add(event.getSession());
}

@Override
public void sessionDestroyed(HttpSessionEvent event) {
if (!listOfSession.isEmpty()) {
updateIsActiveStatusForAuthSession(event.getSession());
listOfSession.remove(event.getSession());
}
}

private void updateIsActiveStatusForAuthSession(HttpSession session) {
xUserMgr.updateIsActiveStatusOfLoggedInUserWithHTTPSession(session.getId(),1);
}

public static CopyOnWriteArrayList getActiveSessionOnServer() {
return listOfSession;
}

}

Paul
7 years ago

Hi,
I’m trying to run a sql delete in my session listener using spring4

Using HttpSession session = sessionEvent.getSession();

ApplicationContext ctx =
WebApplicationContextUtils.
getWebApplicationContext(session.getServletContext());

PatientService pService =
(PatientService) ctx.getBean(“patientService”);

I can access my service, which has access to my dao objects.

However my dao objects are always null.

Is there any way of accessing my dao objects from within a session listener?

Any help would be greatly appreciated.

Thanks

Kartik singaravel
7 years ago

Hey MKyong. Thanks for the wonderful tutorial. I am currently learning Spring. I had one doubt. In the
SessionCounterListener bean you are using HttpSessionListener and getting the “counterservice” bean using
web application utils. Cant we do the same using ApplicationContextAware along with HTTPSessionListener
as aplicationcontextaware also returns the application context and using that also we can get the counterservice bean.
(Correct me if i am wrong).

mouammine
8 years ago

I thank you for this tuto but You can precise why we use the listener in Spring application

Mark
10 years ago

Call this function in your session listener to make the ‘Autowired’ annotation work:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

H
10 years ago

Thx 🙂 works

Bhargava
10 years ago

Thanks for the post

Mudit
11 years ago

Hi ,

I have problem in maintaining session in Springs. I first user logs in to the application and then the second users logs in . The First user is geeting the data of the second user.

I did the google … but didn’t got any help ..

Pls help

James Watkins
11 years ago

I know this is only an example, but static variables should never be used in listeners like this, because they will cause unexpected behavior when you hit a production environment. A reliable data source should be used to keep track of counting sessions. However, this is a simple example and data sources are out of scope. Just remember don’t use static in production code.

Raghunandana
11 years ago

Sir,How to validate sessions in normal spring web application without using spring security

AT
12 years ago

Hi ,

Is There a way to set dependencies here ?
For example , if the loading of my xml in contextConfigLocation depends on a spring remote service , Can I tell the listener to wait till the remote service is available ?

Adochiny
12 years ago

Lovely thanks for sharing.

Sebastian
12 years ago

Hi mkyong!

Is it possible to inject the “CounterService” with annotations? I would prefer something like that:

 
package com.mkyong.common;
 
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
 
public class SessionCounterListener implements HttpSessionListener {
 
     private static int totalActiveSessions;

     @Autowired
     private CounterService counterService;
 
     public static int getTotalActiveSession(){
           return totalActiveSessions;
     }
 
    @Override
    public void sessionCreated(HttpSessionEvent arg0) {
           totalActiveSessions++;
           System.out.println("sessionCreated - add one session into counter");	
           printCounter(arg0);
    }
 
    @Override
    public void sessionDestroyed(HttpSessionEvent arg0) {
           totalActiveSessions--;
           System.out.println("sessionDestroyed - deduct one session from counter");	
           printCounter(arg0);
    }	
 
    private void printCounter(HttpSessionEvent sessionEvent){
          HttpSession session = sessionEvent.getSession();
          counterService.printCounter(totalActiveSessions);
    }

    public void setCounterService(CounterService counterService) {
          this.counterService = counterService;
    }
   
    public CounterService getCounterService() {
          return counterService;
    }
}

I didn’t get it with @Autowired. I also tried to annotate the class with @Component and I configured the following in my Spring configuration:



Do you have an idea?

Best regards,
Sebastian

PS: Very good pages!

suresh
13 years ago

org.postgresql.util.PSQLException: ERROR: relation “qrtz_locks” does not exist

i am getting this error ,, any comment

Emmanuel
13 years ago

You can integrate Quartz in Spring on Web application by using this example?

Vlad
11 years ago
Reply to  mkyong

Any idea how to make DI with annotations? Tried it different ways still getting null exception on my service.