Code Monkey home page Code Monkey logo

ivangfr / springboot-caching-neo4j Goto Github PK

View Code? Open in Web Editor NEW
4.0 2.0 7.0 2.29 MB

The goal of this project is to explore how caching works. To achieve this, we will implement a simple Spring Boot application called "restaurant-api." We will use Neo4j for storage and select one of the following solutions (Simple, Caffeine, or Redis) for caching.

Java 99.67% Shell 0.33%
spring-boot neo4j caffeine caching redis testcontainers graalvm java spring-native springdoc-openapi jib spring-data-neo4j web mapstruct

springboot-caching-neo4j's Introduction

springboot-caching-neo4j

The goal of this project is to explore how caching works. For it, we are going to implement a simple Spring Boot application called restaurant-api. We are using Neo4j for storage and, for caching, we can pick one of the following providers: Simple, Caffeine or Redis.

Proof-of-Concepts & Articles

On ivangfr.github.io, I have compiled my Proof-of-Concepts (PoCs) and articles. You can easily search for the technology you are interested in by using the filter. Who knows, perhaps I have already implemented a PoC or written an article about what you are looking for.

Project Diagram

project diagram

Applications

  • restaurant-api

    Spring Boot Web Java application that has endpoints to manage restaurants, cities (where the restaurants are located in) and dishes that restaurants have. Data is stored in Neo4j and caching handled by Caffeine or Redis.

    restaurant api swagger

Caching

The application uses 3 caches: CITIES, RESTAURANTS and DISHES.

The caching is applied at controller level. For instance, if you call GET /api/restaurants/123 for the first time, the application will check whether the key 123 is present in the RESTAURANTS cache; if not, it must go to DB to get the information about the restaurant (payload). Let’s say that the payload is:

{ "name": "Happy Pizza", "city": {"id": 1, "name": "Berlin"}, "dishes": [] }

Before the endpoint finishes and returns the result, the key and its payload are saved in RESTAURANTS cache:

{ "123" = {"name": "Happy Pizza", "city": {"id": 1, "name": "Berlin"}, "dishes": []} }

On subsequents calls to GET /api/restaurants/123 (and as far as the data is not evicted), the application just needs to go to the cache and get the value.

By the way, we have implemented more advanced caching logic as the one presented above. For example, imagine that you have a city cached in CITIES cache and a new restaurant is created in that city. In this case, the cache of the city is evicted of CITIES (because the list of restaurants in the city changed) and a new cache for the restaurant is put in RESTAURANTS cache. The same happens when a restaurant is deleted/update or a restaurant dish is added/deleted/updated.

Prerequisites

Start Environment

Open a terminal and, inside springboot-caching-neo4j root folder, run:

docker compose up -d

Running application using Maven

  • In a terminal, make sure you are inside springboot-caching-neo4j root folder;

  • Start the application by picking one of the following cache providers:

    • Simple cache provider

      ./mvnw clean spring-boot:run --projects restaurant-api
    • Caffeine cache provider

      ./mvnw clean spring-boot:run --projects restaurant-api -Dspring-boot.run.profiles=caffeine
    • Redis cache provider

      ./mvnw clean spring-boot:run --projects restaurant-api -Dspring-boot.run.profiles=redis

Running application as a Docker container

  • Build Docker Image

    In a terminal, make sure you are in springboot-caching-neo4j root folder;

    • JVM

      ./docker-build.sh
    • Native

      ./docker-build.sh native
  • Environment Variables

    Environment Variable Description

    SPRING_PROFILES_ACTIVE

    Specify the type of profile to run the application. To use Redis provider for caching set redis. To use Caffeine for caching set caffeine. The default profile will use Simple caching.

    NEO4J_HOST

    Specify host of the Neo4j to use (default localhost)

    NEO4J_PORT

    Specify port of the Neo4j to use (default 7687)

    REDIS_HOST

    Specify host of the Redis to use (default localhost)

    REDIS_PORT

    Specify port of the Redis to use (default 6379)

  • Run Docker Container (for instance, using redis profile)

    docker run --rm --name restaurant-api -p 8080:8080 \
      -e SPRING_PROFILES_ACTIVE=redis -e NEO4J_HOST=neo4j -e REDIS_HOST=redis \
      --network=springboot-caching-neo4j_default \
      ivanfranchin/restaurant-api:1.0.0

Application URL

Application URL

restaurant-api

http://localhost:8080/swagger-ui.html

Simulation

Open a terminal and run the following commands:

  • Create a city

    CITY_ID=$(curl -s -X POST http://localhost:8080/api/cities -H  "Content-Type: application/json" -d '{"name":"Berlin"}' | jq -r .id)
    
    curl -i http://localhost:8080/api/cities/$CITY_ID
  • Create a restaurant in the city

    RESTAURANT_ID=$(curl -s -X POST http://localhost:8080/api/restaurants -H  "Content-Type: application/json" -d '{"cityId":"'$CITY_ID'", "name":"Happy Burger"}' | jq -r .id)
    
    curl -i http://localhost:8080/api/restaurants/$RESTAURANT_ID
  • Create a dish for the restaurant

    DISH_ID=$(curl -s -X POST http://localhost:8080/api/restaurants/$RESTAURANT_ID/dishes -H  "Content-Type: application/json" -d '{"name":"Cheese Burger", "price":9.99}' | jq -r .id)
    
    curl -i http://localhost:8080/api/restaurants/$RESTAURANT_ID/dishes/$DISH_ID

Checking Caching Statistics

Caching statistics can be obtained by calling /actuator/prometheus endpoint:

curl -s http://localhost:8080/actuator/prometheus | grep cacheManager

Shutdown

  • To stop restaurant-api application, go to the terminal where it is running and press Ctrl+C;

  • To stop and remove docker compose containers, network and volumes, go to a terminal and inside springboot-caching-neo4j root folder, run the following command:

    docker compose down -v

Running Unit And Integration Test Cases

  • In a terminal, make sure you are inside springboot-caching-neo4j root folder;

  • Start the tests by picking one on the following cache providers:

    • Simple cache provider

      ./mvnw clean verify --projects restaurant-api
    • Caffeine cache provider

      ./mvnw clean verify --projects restaurant-api -DargLine="-Dspring.profiles.active=caffeine"
    • Redis cache provider

      ./mvnw clean verify --projects restaurant-api -DargLine="-Dspring.profiles.active=redis"

Cleanup

To remove the Docker image created by this project, go to a terminal and, inside springboot-caching-neo4j root folder, run the following script:

./remove-docker-images.sh

TODO

  • Add AOP to log whenever the endpoint is called;

  • Create a bash script that uses Neo4j API to insert some data.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.