SpringBoot Hazelcast cache with PostgreSQL backend

Performance is a big problem in software development. And Caching is one solution to speed up system. Hazelcast is an open source in-memory data grid. So in the tutorial, JavaSampleApproach will show you how to use SpringBoot Hazelcast cache with PostGreSQL backend.

Related posts:
How to work with Spring Cache | Spring Boot
SpringBoot Caffeine cache with PostgreSQL backend
Couchbase – How to create Spring Cache Couchbase application with SpringBoot

I. Technologies

– Java 1.8
– Maven 3.3.9
– Spring Tool Suite – Version 3.8.1.RELEASE
– Spring Boot: 1.5.7.RELEASE
– Hazelcast

II. SpringBoot Hazelcast

In the tutorial, we will create a SpringBoot project as below design:

Springboot Hazelcast Cache - Architecture

Spring Boot will auto-configure a HazelcastInstance when having Hazelcast on the classpath. And Spring Boot only configures HazelcastInstance if a Hazelcast configuration is found.

We use dependency hazelcast-spring:


hazelcast-spring had included below dependency:


We can configure Hazelcast via com.hazelcast.config.Config bean. Or use an hazelcast.xml configuration file.
In the application.properties, we specify hazelcast.xml configuration via:


An example of hazelcast.xml:


III. Practice

We create a SpringBoot project as below structure:

SpringBoot Hazelcast Cache - project structure

Step to do:
– Create a SpringBoot project
– Create data model
– Create JPA repository
– Implement cache service
– Initial data with CommandLineRunner
– Run and check results

1. Create a SpringBoot project

We use SpringToolSuite to create a SpringBoot project with below dependencies:






2. Create data model

Create a Customer data model:

package com.javasampleapproach.hazelcast.model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
@Table(name = "customer")
public class Customer implements Serializable{
	private String id;
	@Column(name = "firstname")
	private String firstName;
	@Column(name = "lastname")
	private String lastName;
	public Customer(){
	public Customer(String id, String firstName, String lastName){
		this.id = id;
		this.firstName = firstName;
		this.lastName = lastName;
	public String getId() {
		return this.id;
	public void setId(String id) {
		this.id = id;
	public String getFirstName() {
		return this.firstName;
	public void setFirstName(String firstName) {
		this.firstName = firstName;
	public String getLastName() {
		return this.lastName;
	public void setLastName(String lastName) {
		this.lastName = lastName;
	public String toString() {
		return String.format("Customer[ id=%s, firstName=%s, lastName=%s]", this.id, this.firstName, this.lastName);

Note: need implements Serializable for data model to cache with Hazelcast.

3. Create JPA repository

– Create a CustomerRepository repository:

package com.javasampleapproach.hazelcast.repo;

import org.springframework.data.repository.CrudRepository;

import com.javasampleapproach.hazelcast.model.Customer;

public interface CustomerRepository extends CrudRepository{

– Open application.properties, add data source config:

4. Implement cache service
4.1 Configure Hazelcast

Create a file /src/main/resources/config/hazelcast.xml:


Open application.properties, specify hazelcast.xml location:

4.2 Implement Customer cache
package com.javasampleapproach.hazelcast.service.cache;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

import com.javasampleapproach.hazelcast.model.Customer;
import com.javasampleapproach.hazelcast.repo.CustomerRepository;
@CacheConfig(cacheNames = {"customers"})
public class CustomerCache {
	CustomerRepository customerRepository;
    public Customer getOnCache(String id){
    	System.out.println("############# Backend processing...");
    	// simulation the time for processing
    	try {
		} catch (InterruptedException e) {
    	return customerRepository.findOne(id);
    public Customer putOnCache(String firstName, String id){
		// find a customer in repository
		Customer cust = customerRepository.findOne(id);
		// modify above customer by first-name
		// save to database
        return customerRepository.save(cust);
    @CacheEvict(key = "#id")
    public void evict(String id){

For details about {@Cacheable, @CachePut, @CacheEvict}, we can refer at How to work with Spring Cache | Spring Boot.

4.3 Implement Customer services
package com.javasampleapproach.hazelcast.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.javasampleapproach.hazelcast.model.Customer;
import com.javasampleapproach.hazelcast.service.cache.CustomerCache;
public class CustomerServices {
	CustomerCache customerCache;
    public Customer putCustomer(String firstName, String id){
        return customerCache.putOnCache(firstName, id);
    public Customer get(String id){
    	return customerCache.getOnCache(id);
    public void evict(String id){

5. Initial data with CommandLineRunner
package com.javasampleapproach.hazelcast;

import java.util.Arrays;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

import com.javasampleapproach.hazelcast.model.Customer;
import com.javasampleapproach.hazelcast.repo.CustomerRepository;

public class SpringBootHazelcastApplication implements CommandLineRunner{
	CustomerRepository customerRepo;
	public static void main(String[] args) {
		SpringApplication.run(SpringBootHazelcastApplication.class, args);
	public void run(String... arg0) throws Exception {
		// initial data to PostGreSQL database 
		customerRepo.save(Arrays.asList(new Customer("1", "Jack", "Smith"), 
											new Customer("2", "Adam", "Johnson")));

Note: @EnableCaching is used to enable Hazelcast.

6. Run and check results

– Run the SpringBoot project -> console’s Log:


c.h.instance.DefaultAddressPicker        : [LOCAL] [dev] [3.7.8] Prefer IPv4 stack is true.
c.h.instance.DefaultAddressPicker        : [LOCAL] [dev] [3.7.8] Picked []:5701, using socket ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=5701], bind any local is true
com.hazelcast.system                     : []:5701 [dev] [3.7.8] Hazelcast 3.7.8 (20170525 - 4e820fa) starting at []:5701
com.hazelcast.system                     : []:5701 [dev] [3.7.8] Copyright (c) 2008-2016, Hazelcast, Inc. All Rights Reserved.
com.hazelcast.system                     : []:5701 [dev] [3.7.8] Configured Hazelcast Serialization version : 1
c.h.s.i.o.impl.BackpressureRegulator     : []:5701 [dev] [3.7.8] Backpressure is disabled
com.hazelcast.instance.Node              : []:5701 [dev] [3.7.8] Creating MulticastJoiner
c.h.s.i.o.impl.OperationExecutorImpl     : []:5701 [dev] [3.7.8] Starting 4 partition threads
c.h.s.i.o.impl.OperationExecutorImpl     : []:5701 [dev] [3.7.8] Starting 3 generic threads (1 dedicated for priority tasks)
com.hazelcast.core.LifecycleService      : []:5701 [dev] [3.7.8] []:5701 is STARTING
c.h.n.t.n.NonBlockingIOThreadingModel    : []:5701 [dev] [3.7.8] TcpIpConnectionManager configured with Non Blocking IO-threading model: 3 input threads and 3 output threads

Members [1] {
	Member []:5701 - fd1c39c4-9228-487d-baf2-f4065197fb8f this


– Check PostGreSQL customer table:

SpringBoot Hazelcast Cache - customer table

– Make request 1: http://localhost:8080/api/cachable?id=1

-> Results:
Service process slowly and,

Springboot Hazelcast Cache - request 1

Server has displayed a text on console:

############# Backend processing...

– Make request 2: http://localhost:8080/api/cachable?id=1
Now the response is faster because Customer with id = 1 has been cached before, the application just get data from cache storage.

Springboot Hazelcast Cache - request 2

– Make request 3: http://localhost:8080/api/cacheput?id=1&firstname=Peter
Message is returned on Browser:
Now customer with id=1 is modified: firstname=’Peter’, NOT ‘Jack’.

– Make request 4: http://localhost:8080/api/cachable?id=1
Response is faster BUT the result is difference from first request:

Springboot Hazelcast Cache - request 4

– Make request 5 – Make a cache-evict request: http://localhost:8080/api/cacheevict?id=1
Browser displays:
Now customer with id=1 was evicted from cache storage.

– Make request 6: http://localhost:8080/api/cachable?id=1
Now the behavior of the browser is the same as the first request because customer with id=1 was evicted to cache, and the method under @Cachable is executed.
Service process slowly and result:

############# Backend processing...

Springboot Hazelcast Cache - request 6

IV Sourcecode.


By grokonez | October 5, 2017.

Related Posts

Got Something To Say:

Your email address will not be published. Required fields are marked *