Spring Session with JDBC

In this article, we will see how to use Spring Session with JDBC.

 

Introduction

Spring Session provides a transparent approach to resolve limitation of HTTP session. It provides central session management without being tied to container specific solution (e.g. Tomcat, Jetty etc.). It provides different options to store and manage session information. In this article, we will walk through the steps to integrate JDBC with Spring Session.

 

2. Maven dependencies

We will use Spring Boot in this article but will also outline steps to configure Spring session with JDBC for non Spring Boot applications. We will use MySQL for the setup, but you can use any other database of your choice.

 

2.1 Spring Boot Maven Configurations

If you are using Spring Boot, you need to add following dependencies in your application’s pom.xml file:

<dependencies>
    <dependency>
        <groupId>org.springframework.session</groupId>
        <artifactId>spring-session-jdbc</artifactId>
    </dependency>
    <!-- Adding this to  have datasource and other feature available to us -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

We need not add the dependency for Spring session as this will be taken care by Spring Boot. Based on above configurations, Spring Boot auto-configuration will handle rest of the configurations for us. As the last step, we need to inform Spring Boot to use jdbc to store session information. Add following property in the application.properties file:

spring.session.store-type=jdbc # Session store type.

[pullquote align=”normal”]If you are using only a single session module, you can omit above property from your application.properties file. Spring Boot uses that store implementation automatically. If you have over one implementation, you must specify above property. [/pullquote]

2.2 No Spring Boot Configuration

For non Spring Boot project, we need to add the database dependencies and spring-session-jdbc to the pom.xml file:

 

3. Spring JDBC Session Configuration

Before we use our JDBC backed spring session, we need to add few properties in our application.properties file:

spring.datasource.url=jdbc:mysql://localhost:3306/spring-session-jdbc
spring.datasource.username=root
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

In order for Spring session to work with our JDBC configurations, it needs to create a certain table in the DB, we can enable this feature with help of following property

spring.session.jdbc.initialize-schema=always

Once we enable these properties If we specify spring.session.jdbc.initialize-schema=never, then we need to create session tables in manually. Spring session JDBC jar contains SQL scripts to create required schema. You can check this under org.springframework.session.jdbc package.

Spring JDBC session

Here is the schema for MySQL database:

CREATE TABLE SPRING_SESSION (
	PRIMARY_ID CHAR(36) NOT NULL,
	SESSION_ID CHAR(36) NOT NULL,
	CREATION_TIME BIGINT NOT NULL,
	LAST_ACCESS_TIME BIGINT NOT NULL,
	MAX_INACTIVE_INTERVAL INT NOT NULL,
	EXPIRY_TIME BIGINT NOT NULL,
	PRINCIPAL_NAME VARCHAR(100),
	CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;

CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);

CREATE TABLE SPRING_SESSION_ATTRIBUTES (
	SESSION_PRIMARY_ID CHAR(36) NOT NULL,
	ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
	ATTRIBUTE_BYTES BLOB NOT NULL,
	CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
	CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;

 

3.1.  Spring JDBC Session and @EnableJdbcHttpSession

If you are using @EnableJdbcHttpSession, above configuration will not work. The reason spring.session.* do not work for you is because your are using @EnableJdbcHttpSession. That means we are configuring Spring Session explicitly, so Spring Boot backs off with its auto-configuration. To handle this use case, we have following two options.

  1. Don’t use @EnableJdbcHttpSession and let Spring Boot handle it through auto configuration.
  2. Manually create schema if you continue to use @EnableJdbcHttpSession annotation.

 

4. REST Controller

Let’s create a simple REST controller to see session handling in action:

@RestController
public class GreetingController {

    @GetMapping("/")
    public @ResponseBody ResponseEntity<List> getMessage(Model model, HttpSession session) {
        List greetings = (List) session.getAttribute("GREETING_MESSAGES");
        if(greetings == null) {
            greetings = new ArrayList<>();
        }

        return new ResponseEntity<List>(greetings,HttpStatus.OK);
    }

    @PostMapping("/messages")
    public @ResponseBody ResponseEntity<List> saveMessage(@RequestParam("message") String greeting, HttpServletRequest request)
    {
        List greetings = (List) request.getSession().getAttribute("GREETING_MESSAGES");
        if(greetings == null) {
            greetings = new ArrayList<>();
            request.getSession().setAttribute("GREETING_MESSAGES", greetings);
        }
        greetings.add(greeting);
        return new ResponseEntity<List>(greetings,HttpStatus.OK);
    }
}

 

5. Spring Boot Main Class

here is our Spring Boot main class:

@SpringBootApplication
@EnableJdbcHttpSession
public class SpringSessionWithJdbcApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringSessionWithJdbcApplication.class, args);
    }
}

The only interesting point is the @EnableJdbcHttpSession annotation.

 

6. Session Information in Database

If we run our application and hit the end points. Spring Session with JDBC configuration will handle the session management transparently. Here are the screenshots from the database tables for your reference:

 

Spring Session with JDBC

 

Spring Session with JDBC

 

7. Spring Session Magic

Spring session handle this transparently.The @EnableJdbcHttpSession annotation creates a Spring bean with the name of springSessionRepositoryFilter that implements Filter. The filter is what is in charge of replacing the HttpSession implementation to be backed by Spring Session.

 

Summary

In this post, we saw how to use Spring Session with JDBC. We discussed the distinct steps to configure and use JDBC backed session management for our application.Please refer to our GitHub repository for updated code base.