Spring Boot: Hazelcast for Session Replication

NOTE: This is an updated version of a previous blog. This article contains updated information.

You can use Hazelcast for HTTP session replication between multiple replicas of your Spring Boot application. For example, imagine that you have a classic example of an online shop with customer’s items stored in the session. Users start to add products to their chart and suddenly one of your application service replica crashes. As a result, users lose all their charts and get angry. That is not the outcome one expects from highly available services. That is why you want to have the session shared by all application service replicas.

In this blog post, I explain how to set up session replication for a Spring Boot application using Hazelcast. You can find the source code for this blog post here.

Spring Boot Application

Let’s have a simple web application with the following controller and HTML template.

// WebController.java
@Controller
@RequestMapping("/")
public class WebController {

    @RequestMapping(value = "/")
    public String index(HttpSession httpSession) {
        Integer hits = (Integer) httpSession.getAttribute("hits");
        if (hits == null) {
            hits = 0;
        }
        httpSession.setAttribute("hits", ++hits);

        return "index";
    }
}
<!-- index.html -->
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<body>
		<h3>Session Id</h3>
		<p th:text="${#httpSession.id}"/>
		<h3>Hits</h3>
		<p th:text="${#httpSession.getAttribute('hits')}"/>
	</body>
</html>

When you start the application and open the browser at http://localhost:8080, you should see information with the current session ID and the number of hits (number of times you refreshed the browser).

Now, the problem is that if you start two instances of your application, then the counts for each of them would be completely separate. That is because each Spring Boot application replica stores its sessions separately. What’s more, if one of the application crashes, the session data is lost. That is what we want to change with the use of Hazelcast.

Using Hazelcast for Sessions Replication

To use Hazelcast for session replication in your Spring Boot application, you need to:

  • add hazelcast-all dependency
  • add Hazelcast configuration
  • add WebFilter configuration bean

Here are the added parts in pom.xml and Application.java.

<!-- pom.xml -->
<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast-all</artifactId>
    <version>4.0.2</version>
</dependency>
// Application.java
@Bean
public Config config() {
    return new Config();
}

@Bean
public WebFilter webFilter(HazelcastInstance hazelcastInstance) {

    Properties properties = new Properties();
    properties.put("instance-name", hazelcastInstance.getName());
    properties.put("sticky-session", "false");

    return new WebFilter(properties);
}

This way, we defined the Hazelcast configuration and used the embedded Hazelcast instance to enable session replication.

Starting the Application

To start two replicas of the application, run the following commands.

mvn spring-boot:run
SERVER_PORT=8081 mvn spring-boot:run

You should see in the logs that both embedded Hazelcast instances formed one cluster.

Members {size:2, ver:2} [
        Member [172.24.148.110]:5702 - e01c5b53-4dd8-492c-974c-7f4a7e195fb8 this
        Member [172.24.148.110]:5701 - 27305639-b75c-4f41-84e5-6cd87995511b
]

Testing the Application

Open the browser at http://localhost:8080. You should see the following content.

Now, open the browser at http://localhost:8081. You should see that the hit has increased.

That means that both applications share the same session data store.

What’s more?

Spring Boot is well integrated with Hazelcast. You can check the other blog post Caching with Spring Boot and Hazelcast. You can also set up your Hazelcast in the client-server topology instead of using embedded Hazelcast.