# Caching with Micronaut: Superheroes superquick

### Introduction

Any framework needs to be fast enough to deliver content , Micronaut is no different. In order to deliver content faster, we depend on ***caching***. Micronaut has inbuild support for caching with diffferent cache provider such as Redis, EhCache , Hazelcast etc. Here, we will explore caching implementation with Micronaut. 
 If you wan't the full source code , you can find it below. 

#### Source code :  [https://github.com/CODINGSAINT/super-heroes/tree/05CacheWithMicronaut](https://github.com/CODINGSAINT/super-heroes) 
Let's explore micronaut caching. 
## Table of Content
- [Goal](#goal)
- [Prerequisite](#prerequisite)
* [Approach](#approach)
  - [Adding the cache dependencies of micronaut](#cahceDependecy)
  - [Adding the cache properties to yml](#properties)

  - [Creating Service layer for cache Database (postgres) and Cache](#serviceLayer)
  - [Injecting Service layer to controller ](#controller)
  - [Running the project](#running)

- [Conclusion](#conclusion)
<div id='id-goal'/>
### Goal
The goal of this article is simple. We need a service that demonstrates caching capabilities.
- System must cache the superheroes whenever they are called.
- Every next call to the service should not be hitting the database but our caches.
- Every update on superhero API should also update the cache object. 
- Once any superhero is deleted cache should be invalidated and next time any call to superhero GET API should fetch from the database again.


<div id='id-prerequisite'/>
### Prerequisite
We have created the application with a reactive database (postgres) . We will use same for adding caching capabilities to our projects.
You can check the previous where we added testcontains at  [https://blog.pallav.dev/realtime-testing-micronaut-postgres-and-testcontainer](https://blog.pallav.dev/realtime-testing-micronaut-postgres-and-testcontainer) 
You can also check the entire series at  [https://blog.pallav.dev/series/micronaut](https://blog.pallav.dev/series/micronaut) 


<div id='id-approach'/>
### Approach

<div id='id-cahceDependecy'/>
#### Adding the cache dependencies of micronaut
Add below dependencies to ```pom.xml```

```
<!-- 05 Cache Configs -->
    <dependency>
      <groupId>io.micronaut.cache</groupId>
      <artifactId>micronaut-cache-caffeine</artifactId>
      <scope>compile</scope>
    </dependency>

      <dependency>
          <groupId>io.micronaut.cache</groupId>
          <artifactId>micronaut-cache-management</artifactId>
      </dependency>

    <!-- 05 cache Configs ends-->
```

<div id='id-properties'/>
#### Adding the cache properties to yml
Let us add the properties to application yml ,which will tell the caches the system will configure

```
 #cache related
micronaut:
  caches:
    superheroes:
      charset: 'UTF-8'
    superhero:
      charset: 'UTF-8'
endpoints:
  caches:
    enabled: true
    sensitive: false

```
<div id='id-serviceLayer'/>

#### Creating Service layer for cache Database (postgres) and Cache

Till now we have been injecting DAO to controller , now it's a good use case to create a service layer which will do the talking to cache & db . It act as bridge between controllers and others.
Let us add the service layer . Create a Service class as following with Repository and Cache Injected to it
```
@Singleton
@CacheConfig("superheroes")//1
public class SuperheroService {
    private static final Logger logger = LoggerFactory.getLogger(SuperheroService.class);
    protected ReactiveSuperheroRepository reactiveSuperheroRepository;
    @Inject
    private CacheManager cacheManager;
    SuperheroService(ReactiveSuperheroRepository superheroRepository) {
        this.reactiveSuperheroRepository = superheroRepository;

    }


    public Flux<Superhero> superheroes() {
        logger.info("Fetching all of the superheroes in universe ");
        return reactiveSuperheroRepository.findAll();
    }


    @Cacheable( cacheNames = {"superheroes"}, parameters ={"id"}  )//1
    public Mono<Superhero> superheroesById(Long id) {
        logger.info("Finding the saviour  id {} ", id);
        return reactiveSuperheroRepository.findById(id);

    }

    public Publisher<Superhero> create(Superhero superhero) {
        logger.info("Adding a new saviour {} ", superhero);
        var created = reactiveSuperheroRepository.save(superhero);
        return created;
    }

    @CachePut( cacheNames = "superheroes", parameters = "id")//2
    public Publisher<Superhero> update(Superhero superhero, Long id) {
        logger.info("Updating the old saviour {} ", superhero);
        var updated=reactiveSuperheroRepository.update(superhero);

        return updated;
    }

    @CacheInvalidate(cacheNames = {"superheroes"},parameters = "id" ,async = true)//4
    public Publisher<Long> delete(Long id) {
        var deleted= reactiveSuperheroRepository.deleteById(id);

        return deleted;
    }


}
```

1. ``` CacheConfig```: It is optional to add if we use ```@Cacheable``` but added as just to show
2. ```@Cacheable```:  As the name suggests, tells that this method can be cached ```cacheName``` stores names of the caches and ```parameters``` tells the id with which cache will be created. If the method has only one parameter, it can be avoided.  POST method will add the superhero and once it will be retrieved from the database on ```GET```. As the method is annotated with ```Cachaeable```, next time whenever the same superhero will be called it will be given from cache rather than DB 
3.  ``` CachePut```: Will update the cache with the given ``` parameter``` (key), It will help us when there is a change in superhero properties. It will automatically cache the newer version with the same key. 
4. ``` CacheInvalidate```: removes the cache all together with ``` parameter``` (key). This will invalidate the superhero so when it will be asked to give the same superhero again, we will not be getting the value from cache and a DB hit will happen.

<div id='id-controller'/>
####  Injecting Service layer to controller 
Till now we have been calling the database from Controller but now we will call the Service layer, so we will inject the same and remove the repository (which is moved to service)

```
@Controller("rx/")
public class ReactiveSuperHeroController {
    private static final Logger logger = LoggerFactory.getLogger(SuperHeroController.class);

    private SuperheroService service;

    public ReactiveSuperHeroController(SuperheroService service) {
        this.service = service;
    }

    @Get("superheroes")
    public Flux<Superhero> superheroes() {
        return service.superheroes();
    }

    @Get("superhero/{id}")
    public Mono<Superhero> superheroesById(Long id) {

        return service.superheroesById(id);

    }

    @Post("/superhero")
    Single<Superhero> create(@Valid Superhero superhero) {
        logger.info("Call to add a new saviour {} ", superhero);
        return Single.fromPublisher(service.create(superhero));
    }

    @Put("superhero")
    Single<Superhero> update( @Valid Superhero superhero) {
        return Single.fromPublisher(service.update(superhero, superhero.id()));
    }
    @Delete("superhero/{id}")
    Single<HttpResponse<?>> delete(@NotNull Long id) {
        return Single
                .fromPublisher(service.delete(id))
                .map(deleted->deleted>0?HttpResponse.noContent():HttpResponse.notFound());
    }
}

```

<div id='id-running'/>
### Running the project
Now we can run the project and Create few Superheroes and do CRUD operations. We will keep an eye on logs to see if the method (GET) is being called multiple times. It is expected that the Cachable method will be called only when the call for the superhero is for the first time.

Below is the CURL request to create  (POST)
```
curl --location --request POST 'http://localhost:8080/rx/superhero' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "Justice Hammer",
    "prefix": "Captain",
    "suffix": "Walker",
    "power": "Lightening Thunder"
}'
```

Now we will hit GET multiple times but logs will print only once from the service layer
```
curl --location --request GET 'http://localhost:8080/rx/superhero/1'
curl --location --request GET 'http://localhost:8080/rx/superhero/1'
curl --location --request GET 'http://localhost:8080/rx/superhero/1'
```

We can see in the logs below that the service layer is called once, post that it is not called as the values have been returned from the cache.

We can also update and check still, the GET log will not print as an update on the same hero will be also updated in the cache.  Once deleted it will try again to check from DB as the cache is invalidated.

The logs of the above operation will be 
```
our Superhero[id=null, name=Justice Hammer, prefix=Captain, suffix=Walker, power=Lightening Thunder] 
00:42:06.300 [default-nioEventLoopGroup-1-3] INFO  c.c.service.SuperheroService - Adding a new saviour Superhero[id=null, name=Justice Hammer, prefix=Captain, suffix=Walker, power=Lightening Thunder] 
00:44:44.132 [default-nioEventLoopGroup-1-3] INFO  c.c.service.SuperheroService - Finding the saviour  id 1 

```
<div id='id-conclusion'/>
### Conclusion
We saw that caching has reduced the load on DB and significantly improved performance. If you have not noticed performance benefits, check time taken with the first call and the subsequent (```Cacheable```) method calls 


