How to configure Spring Sessions to use Redis for session storage.

This is a short checklist which will lead you through the process of adding Spring Sessions backed by Redis to a XML-based Spring web application configuration. It will also provide an example repository configuration for MapSessionRepository that can be useful for testing. Although I have gleaned much information about this from other well done tutorials, it’s been a rarity to find all this information together in one document.

Install A Redis Server

Here are a few good links to get you started:

I use Homebrew for Mac OS X, so all I had to do was:

brew install redis

Add These Maven Dependencies

You’ll need to add these dependencies to the Maven pom.xml for your project:

pom.xml

<!-- https://mvnrepository.com/artifact/org.springframework/spring-web -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-web</artifactId>
    <version>4.3.4.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis -->
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>1.7.5.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.session/spring-session -->
<dependency>
    <groupId>org.springframework.session</groupId>
    <artifactId>spring-session</artifactId>
    <version>1.2.2.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
    <version>2.4.2</version>
</dependency>
<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>

You can use https://mvnrepository.com to find the latest versions of these artifacts.

Add These Filters To Your web.xml

Enable the filter for storing HTTP sessions in Spring Sessions with Redis instead of Tomcat. This MUST be loaded before the other filters.

src/main/webapp/WEB-INF/web.xml

<filter>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
	<filter-name>springSessionRepositoryFilter</filter-name>
	<url-pattern>/*</url-pattern>
	<dispatcher>REQUEST</dispatcher>
	<dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener> 

Add These Spring Beans To Your Application Context

The RedisHttpSessionConfiguration bean is set up to automatically add nearly everything you need to support Spring Sessions in Redis. You just need to specify the JedisConnectionFactory to get the Redis connections, and the HttpSessionEventPublisher to keep it in sync with Spring Security.

src/main/resources/META-INF/spring/applicationContext.xml

<bean class="org.springframework.session.data.redis.config.annotation.web.http.RedisHttpSessionConfiguration"/>	<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
	<property name="maxWaitMillis" value="-1"/>
	<property name="maxTotal" value="50"/>
	<property name="maxIdle" value="10"/>
	<property name="blockWhenExhausted" value="true"/>
	<property name="testOnBorrow" value="true"/>
	<property name="testOnReturn" value="false"/>
	<property name="testWhileIdle" value="true"/>
</bean>
<bean id="jedisConnFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
	<property name="hostName" value="${session.redis.host}"/>
	<property name="port" value="${session.redis.port}"/>
	<property name="timeout" value="2000"/>
	<property name="usePool" value="true"/>
	<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>
<bean class="org.springframework.security.web.session.HttpSessionEventPublisher" />

Spring Sessions with MapSessionRepository

If you are having trouble setting up Redis and want to see if your Spring Session’s configuration works without Redis, you can try this alternate set of configuration changes:

src/main/webapp/WEB-INF/web.xml

<filter>
        <filter-name>springSessionRepositoryFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
        <filter-name>springSessionRepositoryFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
</filter-mapping>
<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

src/main/resources/META-INF/spring/applicationContext.xml

<bean class="org.springframework.session.config.annotation.web.http.SpringHttpSessionConfiguration"/>
<bean class="org.springframework.session.MapSessionRepository"/>
<bean class="org.springframework.security.web.session.HttpSessionEventPublisher" />

Note: MapSessionRepository is not recommended for production.

You Oughta Know

You Oughta Know

  • If you are using Annotated Spring Configurations, it’s MUCH SIMPLER to use the @EnableRedisHttpSession annotation here: http://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-spring-configuration
  • Make certain that the Spring Session filters are added BEFORE all of the other filters in your web.xml – especially Spring Security.
  • The EnableRedisKeyspaceNotificationsInitializer is a bean created by the RedisHttpSessionConfiguration responsible for notifying Spring Sessions of Session Created and Session Expired events. If you see an error related to this when your Spring application is starting, check your JedisConnectionFactory configuration.
  • The HttpSessionEventPublisher republishes Session Created and Session Expired events to the Application Queue and is necessary to make sure Spring Security knows when a session has expired. Without this your sessions may expire without expiring your authorization resulting in errors.
  • There are several other SessionRepository implementations including JDBC, Hazelcast, GemFire, and MongoDB.

Further Reading

Here are some of the references that helped me along the way: