Spring Boot Hazelcast Cache Example

By | 2018-11-11T09:56:16+00:00 October 15th, 2018|Spring Boot|0 Comments

Hazelcast is an in-memory distributed caching mechanism. In this tutorial, I am going to show you how to enable the Spring Boot Hazelcast cache.

Spring Boot Hazelcast Cache:

Hazelcast is an in-memory caching mechanism provided by the spring boot. Spring boot auto-configures the Hazelcast instance if the hazelcast is available in our application’s classpath and the required configuration is available.

Spring Boot Hazelcast Example:

Here I am going to create a simple spring boot rest service to read Items from the database using the hazelcast cache.

Technologies:

  • Spring Boot 2.0.5 RELEASE
  • Hazelcast
  • Spring Boot JDBC
  • MySQL
  • Java 8

Project Structure:

Spring Boot Hazelcast Cache Example

Hazelcast Dependency:

Add the below hazelcast dependencies in pom.xml

hazelcast dependencies
<dependency>
  <groupId>com.hazelcast</groupId>
  <artifactId>hazelcast</artifactId>
</dependency>
<dependency>
  <groupId>com.hazelcast</groupId>
  <artifactId>hazelcast-spring</artifactId>
</dependency>

Complete pom.xml

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.onlinetutorialspoint</groupId>
  <artifactId>SpringBoot_Hazelcast_Cache_Example</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>
  <name>SpringBoot_Hazelcast_Cache_Example</name>
  <description>Spring Boot Hazelcast Cache Example</description>

  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.5.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
  </properties>
  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>com.hazelcast</groupId>
      <artifactId>hazelcast</artifactId>
    </dependency>
    <dependency>
      <groupId>com.hazelcast</groupId>
      <artifactId>hazelcast-spring</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

Database configuration details.

application.properties
server.port=8080
spring.datasource.driver-class-name: com.mysql.jdbc.Driver
spring.datasource.url: jdbc:mysql://localhost:3306/otp
spring.datasource.username: root
spring.datasource.password: Chandu@123

Hazelcast configuration.

Creating a Hazelcast Config bean with the required configuration.

HazelcastCacheConfig.java
package com.onlinetutorialspoint.config;

import com.hazelcast.config.Config;
import com.hazelcast.config.EvictionPolicy;
import com.hazelcast.config.MapConfig;
import com.hazelcast.config.MaxSizeConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class HazelcastCacheConfig {

    @Bean
    public Config hazelcastConfig(){
       return new Config().setInstanceName("hazelcast-instance")
                .addMapConfig(new MapConfig().setName("itemCache")
                .setMaxSizeConfig(new MaxSizeConfig(300,MaxSizeConfig.MaxSizePolicy.FREE_HEAP_SIZE))
                .setEvictionPolicy(EvictionPolicy.LRU)
                .setTimeToLiveSeconds(2000));
    }

}

Mapping the itemCache to hazelCache config and giving eviction policy as LRU (Last Recently Used).

Preparing ItemCache component.

ItemCache.java
package com.onlinetutorialspoint.cache;

import com.onlinetutorialspoint.model.Item;
import com.onlinetutorialspoint.repo.ItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class ItemCache {

    @Autowired
    ItemRepository itemRepo;

    @Cacheable(value="itemCache", key="#id")
    public Item getItem(int id){
        System.out.println("In ItemCache Component..");
        Item item = null;
        try{
            item = itemRepo.getItem(id);
            Thread.sleep(2000);
        }catch(Exception e){
            e.printStackTrace();
        }
        return item;
    }

    @CacheEvict(value="itemCache",key = "#id")
    public int deleteItem(int id){
        System.out.println("In ItemCache Component..");
        return itemRepo.deleteItem(id);
    }

    @CachePut(value="itemCache")
    public void updateItem(Item item){
        System.out.println("In ItemCache Component..");
        itemRepo.updateItem(item);
    }
}

@Cachable: Is used to adding the cache behavior to a method. We can also give the name to it, where the cache results would be saved.
@CacheEvict: Is used to remove the one or more cached values. allEntries=true parameter allows us to remove all entries from the cache.
@CachePut: Is used to update the cached value.

Creating an Item model

Item.java
package com.onlinetutorialspoint.model;

import java.io.Serializable;

public class Item implements Serializable {
    private int id;
    private String name;
    private String category;

    public Item() {
    }

    public Item(int id, String name, String category) {
        this.id = id;
        this.name = name;
        this.category = category;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getCategory() {
        return category;
    }

    public void setCategory(String category) {
        this.category = category;
    }
}

Creating Item Repository responsible to read items from MySQL database using JdbcTemplate.

ItemRepository.java
package com.onlinetutorialspoint.repo;

import com.onlinetutorialspoint.model.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

@Repository
public class ItemRepository {

    @Autowired
    JdbcTemplate template;

    /*Getting a specific item by item id from table*/
    public Item getItem(int itemId){
        System.out.println("Reading Item From Repository..");
        String query = "SELECT * FROM ITEM WHERE ID=?";
        return template.queryForObject(query,new Object[]{itemId},new BeanPropertyRowMapper<>(Item.class));
    }

    /*delete an item from database*/
    public int deleteItem(int id){
        String query = "DELETE FROM ITEM WHERE ID =?";
        int size = template.update(query,id);
        return size;
    }

    /*update an item from database*/
    public void updateItem(Item item){
        String query = "UPDATE ITEM SET name=?, category=? WHERE id =?";
        template.update(query,
                new Object[] {
                        item.getName(),item.getCategory(), Integer.valueOf(item.getId())
                });
    }

}

Creating rest endpoints to access item data

ItemController.java
package com.onlinetutorialspoint.controller;

import com.onlinetutorialspoint.cache.ItemCache;
import com.onlinetutorialspoint.model.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
public class ItemController {

    @Autowired
    ItemCache itemCache;
    @GetMapping("/item/{itemId}")
    @ResponseBody
    public ResponseEntity<Item> getItem(@PathVariable int itemId){
        System.out.println("RestController..");
        long start = System.currentTimeMillis();
        Item item = itemCache.getItem(itemId);
        long end = System.currentTimeMillis();
        System.out.println("Took : " + ((end - start) / 1000+" sec."));
        return new ResponseEntity<Item>(item, HttpStatus.OK);
    }

    @PutMapping("/updateItem")
    @ResponseBody
    public ResponseEntity<Item> updateItem(@RequestBody Item item){
        if(item != null){
            itemCache.updateItem(item);
        }
        return new ResponseEntity<Item>(item, HttpStatus.OK);
    }

    @DeleteMapping("/delete/{id}")
    @ResponseBody
    public ResponseEntity<Void> deleteItem(@PathVariable int id){
        itemCache.deleteItem(id);
        return new ResponseEntity<Void>(HttpStatus.ACCEPTED);
    }

}

Main class with the @EnablingCache annotation to enable the cache.

SpringBootHazelcastCacheExampleApplication.java
package com.onlinetutorialspoint;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class SpringBootHazelcastCacheExampleApplication {

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

Run the application:

mvn spring-boot: run
mvn spring-boot:run

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.0.5.RELEASE)

2018-10-14 17:43:02.414  INFO 5196 --- [           main] ringBootHazelcastCacheExampleApplication : Starting SpringBootHazelcastCacheExampleApplication on DESKTOP-RN4SMHT with PID 5196 (E:\work\SpringBoot_Hazelcast_Cache_Example\target\classes started by Lenovo in E:\work\SpringBoot_Hazelcast_Cache_Example)
2018-10-14 17:43:02.414  INFO 5196 --- [           main] ringBootHazelcastCacheExampleApplication : No active profile set, falling back to default profiles: default
.....
.....

Access the application

Spring Boot Hazelcast Cache Example output

Console logs:

console
RestController..
In ItemCache Component..
Reading Item From Repository..
Took : 3 sec.

For the first time when we access the item 1, it took 3 Sec to get the data from the database.

Accessing the same item again and observe the log statements.

Spring Boot Hazelcast Cache Example output
console
RestController..
Took : 0 sec.

For the second time, it took zero seconds to get the same data because for this time the data came from the hazelCast cache.

Happy Learning 🙂

Download Example

About the Author:

Hi Folks, you have reach this so far, that shows you like what you are learning. Then why don't you support us to improve for bettor tutorials by leaving your valuable comments and why not you keep in touch with us for latest updates on your favorite blog @ facebook , twitter , Or Google+ ,

Leave A Comment