Easy Session Sharing in Spring Boot With Spring Session and MySQL
In this tutorial, we will walk you through the configuration of session sharing in a multi-node Spring Boot application.
Join the DZone community and get the full member experience.Join For Free
Session management in multi-node applications presents multiple challenges. When the architecture includes a load balancer, client requests might be routed to different servers each time, and the HTTP session might be lost. In this tutorial, we will walk you through the configuration of session sharing in a multi-node Spring Boot application.Prerequisites: Table of Contents
Session Persistence is a technique for sticking a client to a single server, using application layer information-like a cookie, for example. In this tutorial, we will implement session persistence with the help of HAProxy, a reliable, high performance, TCP/HTTP load balancer.
First, let's create a web application with Okta authentication and run three nodes with HAProxy load balancing using Docker Compose.
Create a Maven project using the Spring Initializr's API.
Unzip the project:
Run the Okta Maven Plugin to register a new account:
If you already have an Okta account registered, use
login instead of
Then, configure your Spring application for authentication using Okta:
It will set up a new OIDC application for you and write your Okta settings to your
Run the application with:
http://localhost:8080 in an incognito window and you should be redirected to the Okta sign-in page.
If you sign in, you will get a 404 error when you're redirected back to your Spring Boot app. This is expected because there's no controller mapped to the
/ endpoint. You can fix this if you want by adding a method like the following to your
Now, let's configure three Docker containers, one for each application node, and an HAProxy container. In the project root folder, create a
docker/docker-compose.yml file, with the following content:
docker/.env file with the following content:
You can find the issuer, clientId, and clientSecret in the
src/main/resources/application.properties, after running the Okta Maven Plugin. Remove the
\ in the issuer's URL after you paste the value. Also, make sure to remove the curly braces around the values.
Dockerfile for the HAProxy container, at
docker/Dockerfile-haproxy and add the following:
Create the configuration file for the HAProxy instance at
I'm not going to dive deep into how to configure HAProxy but take note that, in the
backend servers section, there are the following options:
balance roundrobinsets round-robin as the load balancing strategy.
cookie SERVERUSEDadds a cookie SERVERUSED to the response, indicating the server responding to the request. The client requests will stick to that server.
option redispatchmakes the request be re-dispatched to a different server if the current server fails.
pom.xml to add the Jib Maven Plugin to the
<build> section to create a
webapp Docker image.
webapp container image:
Start all the services with docker-compose:
NOTE: If you get a
URISyntaxException on startup, remove the
\ in the issuer in
HAProxy will be ready after you see the following lines in the logs:
Before you can sign in to your application, you'll need to go to your Okta developer console and add a Login redirect URI for
http://localhost/login/oauth2/code/okta. Otherwise, you'll get a 400 error in the next step. While you're in there, add a Logout redirect URI for
In a browser, go to
http://localhost/greeting. After you sign in, inspect the request cookie
SERVERUSED. An example value is:
Shut down the current node with the following Docker command:
Refresh your browser and wait a few seconds. Check the
SERVERUSED cookie to verify that HAProxy re-dispatched the request to a different node, and the sessionId has changed, meaning the old session was lost.
You can stop the services with
Session Sharing With Spring Session
Storing sessions in an individual node can affect scalability. When scaling up, active sessions will remain in the original nodes and traffic will not be spread equally among nodes. Also, when a node fails, the session in that node is lost. With session sharing, the user session lives in a shared data storage that all server nodes can access.
Next, for a transparent failover with the
redispatch option in HAProxy, let's add session sharing between nodes with Spring Session. For this tutorial, I'll show you how to use MySQL for storing the session.
First, add the following dependencies to the
application.yml, change your
okta.* properties to be in YAML syntax, and add the following key-value pairs:
In this example, you are using HikariCP for the database connection pooling. The option
initializationFailTimeout is set to 0, meaning if a connection cannot be obtained, the pool will start anyways.
You are also instructing Spring Session to always create the schema with the option
application.yml file you just created contains the default datasource properties for the MySQL session storage. As the MySQL database is not up when the tests run, set up an in-memory H2 database so the application tests don't fail.
src/test/resources/application-test.yml file with the following content:
WebApplicationTests.java class to add the
docker/docker-compose.yml to add the database container and the admin application to inspect the session tables. The final configuration should look like the following:
Delete the previous containers and previous
webapp Docker image with the following commands:
In the root folder of the project, rebuild the webapp docker image with Maven:
Start all the services again (
docker-compose up from the
docker directory), and repeat the re-dispatch test (go to
http://localhost/greeting then shutdown the active node with
docker stop docker_webapp#_1). You might see a lot of connection errors until the database is up.
Now the session should be the same after changing the node. How cool is that?!
You can inspect the session data in the admin UI at
http://localhost:8090. Log in with
root and the
MYSQL_ROOT_PASSWORD value that you set in
Learn More about Spring Session and OAuth 2.0
I hope you enjoyed this tutorial and could see the advantages of the session sharing technique for multi-node applications. You can find all the code for this tutorial in GitHub.
Know that there are multiple options for session storage-we selected a database because of the ease of setup-but it might slow down your application. To learn more about session management, check out the following links:
Published at DZone with permission of Jimena Garbarino, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.