Wednesday, October 20, 2021

Understanding Hazelcast caching concept using JAVA Springboot

 Generally in web application Frontend i.e AJS or React make a call to Middle ware i.e. Springboot and then springboot make a call data base or other services to get the data to show to the user. This approach is traditional approach and every time the request is made from the FE our call goes to BE via Middle ware to fetch the data and this is not resource efficient and also not good in performance.

How would be if we some how make a cache of the data that we are fetching from BE and whenever any request is made for that DATA we can directly give it from that cache so that our BE call from MW is not required.
I agree there are many scenarion which we need to think

1- If we make an insert/update/delet into the DB in that case we need to update cache values
2- Cache data need to be available as centralize place for distributed application i.e. one application or request change the data and then if the another request or application ask for that data from cache they should be represented with proper values.

Note:- We are taking Springboot as our Middle ware application.

Lets first try to build an simple example where in we will just exposed an url from Springboot and will fetch the data from it.

Please follow below step to setup simple springboot application.

Full url

Now lets try to create a simple controller and service class to satisfy our request and response flow.

SiddhuController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.siddhu;
 
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/siddhu")
public class SiddhuController {
 
    @GetMapping("/{siddhuname}")
    public String getSiddhuName(@PathVariable("siddhuname") String siddhuname)
    {
        return  siddhuname;
    }
}

Lets run the applicaiton and check we are able to get the response

Now lets take the response from our service class as a good practise rather than controller.

SiddhuService.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.siddhu;
 
import org.springframework.stereotype.Service;
 
@Service
public class SiddhuService {
     
    public String getSiddhuNameService(String siddhuname)
    {
        return findNameInDatabase(siddhuname);
    }
 
    public String findNameInDatabase(String siddhuname) {
        // TODO Auto-generated method stub
        //For simplicity we will return the hardcode value but in real scenario think that this method will make a
        // DB call or call another springboot application or call another Webservice. We will try to mimic that
        //using thread.sleep function to stop the execution for 4 sec
        System.out.println("Inside Service SiddhuService :::::::::::::::::::::::::::::::::");
        try {
            Thread.sleep(4000);
        }
        catch(InterruptedException exp)
        {
            exp.printStackTrace();
        }
        return siddhuname;
    }
 
}

Now lets change the controller accordingly

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.siddhu;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/siddhu")
public class SiddhuController {
     
    @Autowired
    private SiddhuService siddhuService;
     
 
    @GetMapping("/{siddhuname}")
    public String getSiddhuName(@PathVariable("siddhuname") String siddhuname)
    {
        //return  siddhuname;
        return siddhuService.getSiddhuNameService(siddhuname);
    }
}

Now lets execute the project and see the out put.

You will be able to see the response but as we added Thread.sleep(4000); response will take 4 sec time to be displayed on the UI.

Now We will try to introduce the hazelcast cache mechnisum and will try to cache this value so that next time when ever the user hit the url rather than going to fetch the value for waiting for 4 sec it will directly fetch values from the cache.

For this we need to modify our code in our service class we had added
@Cacheable(“siddhu”)

this indicate that we are creating a cache with name as “myname” and also in main SpringbootHazelcastApplication class of spring boot add this annotation stating that it enable caching.
@EnableCaching

Till here we can do the caching using spring concurrentHashMap but as we want to do the Hazelcast caching add the following depedencies in the pom.xml.

Finally add the dependencies in our pom.xml

1
2
3
4
5
6
<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast-all</artifactId>
    <version>5.0-BETA-1</version>
</dependency>

Create a new hazelcast.yaml in resource folder and add followig line in it

1
2
3
4
5
hazelcast:
  network:
    join:
      multicast:
        enabled: true

And now start the application you will see we have creat a member of hazelcast

now execute the url http://localhost:8080/siddhu/sdhumale and for first time it will take 4 sec and from the next time it will give immediately response as we are taking the response from the cache.

First hit will take 4 sec as shown below

and second refresh will take less than 1 sec. This is because we have taken the value from Hazelcast

There is Hazelcast management center available that gives you the member that is created along with other information.
You can download it from the below location

Unzip the folder and execute following command

C:\hazelcast-management-center-5.0\bin>start.bat 8081

Now lets try to run our same springboot application on different port and check if we are able to use th cache member in different application running on different port.

As we had used multicast as true this says that hazelcast cache member is shared with all the member so as shown below even though we are htting the different url the time taken to load the data is less then 1 sec.

Lets execute our springboot application on different port using below command.
C:\STS-Workspace\springboot-hazelcast\target>java -jar springboot-hazelcast-example-0.0.1-SNAPSHOT.jar –server.port=8082

you will see we have now two hazelcast member

Now lets hit this url http://localhost:8082/siddhu/sdhumale

you will see it takes hardly 0.2 sec to execute indicating we had shared and used the cache memeber between the two hazelcast member.

Download:-

https://github.com/shdhumale/springboot-hazelcast.git

No comments: