From 19437f2e13555d701d79d58561590e9815aa59e1 Mon Sep 17 00:00:00 2001 From: Mladen Savic Date: Mon, 8 Nov 2021 17:06:17 +0100 Subject: [PATCH 1/3] Spring Webflux and @Cacheable Annotation --- pom.xml | 3 + spring-webflux-caching/pom.xml | 67 +++++++++++++ .../main/java/com/baeldung/caching/Item.java | 50 ++++++++++ .../com/baeldung/caching/ItemRepository.java | 8 ++ .../com/baeldung/caching/ItemService.java | 42 ++++++++ .../SpringWebfluxCachingApplication.java | 16 ++++ .../src/main/resources/application.properties | 2 + .../MonoFluxResultCachingLiveTest.java | 95 +++++++++++++++++++ 8 files changed, 283 insertions(+) create mode 100644 spring-webflux-caching/pom.xml create mode 100644 spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java create mode 100644 spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java create mode 100644 spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java create mode 100644 spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java create mode 100644 spring-webflux-caching/src/main/resources/application.properties create mode 100644 spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java diff --git a/pom.xml b/pom.xml index f2a53f38b7..9a34ed0afe 100644 --- a/pom.xml +++ b/pom.xml @@ -7,6 +7,9 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT + + spring-webflux-caching + parent-modules pom diff --git a/spring-webflux-caching/pom.xml b/spring-webflux-caching/pom.xml new file mode 100644 index 0000000000..ed9800bce9 --- /dev/null +++ b/spring-webflux-caching/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + com.baeldung.spring + spring-webflux-caching + 1.0.0-SNAPSHOT + spring-webflux-caching + jar + Spring WebFlux Caching Sample + + + com.baeldung + parent-boot-2 + 0.0.1-SNAPSHOT + ../parent-boot-2 + + + + + + org.springframework.boot + spring-boot-starter-webflux + + + io.reactivex.rxjava2 + rxjava + 2.2.19 + + + io.projectreactor.addons + reactor-extra + 3.4.5 + + + com.github.ben-manes.caffeine + caffeine + 3.0.4 + + + org.springframework.boot + spring-boot-starter-data-mongodb-reactive + + + com.fasterxml.jackson.core + jackson-databind + + + org.springframework.boot + spring-boot-starter-test + test + + + io.projectreactor + reactor-test + test + + + org.testcontainers + mongodb + 1.16.2 + test + + + + \ No newline at end of file diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java b/spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java new file mode 100644 index 0000000000..127975b0e7 --- /dev/null +++ b/spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java @@ -0,0 +1,50 @@ +package com.baeldung.caching; + +import org.springframework.data.annotation.Id; +import org.springframework.data.mongodb.core.mapping.Document; + +@Document +public class Item { + + @Id + private String _id; + private String name; + private double price; + + public Item(String name, double price) { + this.name = name; + this.price = price; + } + + public Item() { + } + + public String get_id() { + return _id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getPrice() { + return price; + } + + public void setPrice(double price) { + this.price = price; + } + + @Override + public String toString() { + return "Item{" + + "id='" + _id + '\'' + + ", name='" + name + '\'' + + ", price=" + price + + '}'; + } +} diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java b/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java new file mode 100644 index 0000000000..a76489623e --- /dev/null +++ b/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java @@ -0,0 +1,8 @@ +package com.baeldung.caching; + +import org.springframework.data.mongodb.repository.ReactiveMongoRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ItemRepository extends ReactiveMongoRepository { +} diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java b/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java new file mode 100644 index 0000000000..9dc9ba1642 --- /dev/null +++ b/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java @@ -0,0 +1,42 @@ +package com.baeldung.caching; + +import com.github.benmanes.caffeine.cache.Caffeine; +import com.github.benmanes.caffeine.cache.LoadingCache; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import reactor.cache.CacheMono; +import reactor.core.publisher.Mono; + +@Service +public class ItemService { + + private final ItemRepository repository; + private final LoadingCache cache; + + public ItemService(ItemRepository repository) { + this.repository = repository; + this.cache = Caffeine.newBuilder() + .build(this::getItem_withAddons); + } + + @Cacheable("items") + public Mono getItem(String id) { + return repository.findById(id); + } + + public Mono save(Item item) { + return repository.save(item); + } + + @Cacheable("items") + public Mono getItem_withCache(String id) { + return repository.findById(id).cache(); + } + + @Cacheable("items") + public Mono getItem_withAddons(String id) { + return CacheMono.lookup(cache.asMap(), id) + .onCacheMissResume(() -> repository.findById(id).cast(Object.class)).cast(Item.class); + } + +} diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java b/spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java new file mode 100644 index 0000000000..7331576bd5 --- /dev/null +++ b/spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java @@ -0,0 +1,16 @@ +package com.baeldung.caching; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +@SpringBootApplication +@EnableMongoRepositories +@EnableCaching +public class SpringWebfluxCachingApplication { + + public static void main(String[] args) { + SpringApplication.run(SpringWebfluxCachingApplication.class, args); + } +} diff --git a/spring-webflux-caching/src/main/resources/application.properties b/spring-webflux-caching/src/main/resources/application.properties new file mode 100644 index 0000000000..23414da2dd --- /dev/null +++ b/spring-webflux-caching/src/main/resources/application.properties @@ -0,0 +1,2 @@ +logging.level.org.springframework.data.mongodb.core.ReactiveMongoTemplate=DEBUG +logging.level.org.springframework.cache=TRACE \ No newline at end of file diff --git a/spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java b/spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java new file mode 100644 index 0000000000..bf96b35dcb --- /dev/null +++ b/spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java @@ -0,0 +1,95 @@ +package com.baeldung.caching; + + +import org.assertj.core.api.Assertions; +import org.junit.ClassRule; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.DynamicPropertyRegistry; +import org.springframework.test.context.DynamicPropertySource; +import org.testcontainers.containers.MongoDBContainer; +import org.testcontainers.utility.DockerImageName; +import reactor.core.publisher.Mono; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest +public class MonoFluxResultCachingLiveTest { + + + @Autowired + ItemService itemService; + + final static MongoDBContainer mongoDBContainer = new MongoDBContainer(DockerImageName.parse("mongo:4.0.10")); + + @DynamicPropertySource + static void mongoDbProperties(DynamicPropertyRegistry registry) { + mongoDBContainer.start(); + registry.add("spring.data.mongodb.uri", mongoDBContainer::getReplicaSetUrl); + } + +@Test +public void givenItem_whenGetItemIsCalled_thenMonoIsCached() { + Mono glass = itemService.save(new Item("glass", 1.00)); + + String id = glass.block().get_id(); + + Mono mono = itemService.getItem(id); + Item item = mono.block(); + + assertThat(item).isNotNull(); + assertThat(item.getName()).isEqualTo("glass"); + assertThat(item.getPrice()).isEqualTo(1.00); + + Mono mono2 = itemService.getItem(id); + Item item2 = mono2.block(); + + assertThat(item2).isNotNull(); + assertThat(item2.getName()).isEqualTo("glass"); + assertThat(item2.getPrice()).isEqualTo(1.00); +} + + @Test + public void givenItem_whenGetItemWithCacheIsCalled_thenMonoResultIsCached() { + Mono glass = itemService.save(new Item("glass", 1.00)); + + String id = glass.block().get_id(); + + Mono mono = itemService.getItem_withCache(id); + Item item = mono.block(); + + assertThat(item).isNotNull(); + assertThat(item.getName()).isEqualTo("glass"); + assertThat(item.getPrice()).isEqualTo(1.00); + + Mono mono2 = itemService.getItem_withCache(id); + Item item2 = mono2.block(); + + assertThat(item2).isNotNull(); + assertThat(item2.getName()).isEqualTo("glass"); + assertThat(item2.getPrice()).isEqualTo(1.00); + } + + @Test + public void givenItem_whenGetItemWithAddonsIsCalled_thenMonoResultIsCached() { + Mono glass = itemService.save(new Item("glass", 1.00)); + + String id = glass.block().get_id(); + + Mono mono = itemService.getItem_withAddons(id); + Item item = mono.block(); + + assertThat(item).isNotNull(); + assertThat(item.getName()).isEqualTo("glass"); + assertThat(item.getPrice()).isEqualTo(1.00); + + Mono mono2 = itemService.getItem_withAddons(id); + Item item2 = mono2.block(); + + assertThat(item2).isNotNull(); + assertThat(item2.getName()).isEqualTo("glass"); + assertThat(item2.getPrice()).isEqualTo(1.00); + } + +} From 4dc1a31a5b406ad62cb97ff1aa2c3b1d4d0b534d Mon Sep 17 00:00:00 2001 From: Mladen Savic Date: Thu, 11 Nov 2021 15:47:37 +0100 Subject: [PATCH 2/3] Spring Webflux and @Cacheable Annotation - moved to different module --- pom.xml | 3 - spring-5-webflux/pom.xml | 20 ++++++ .../com/baeldung/spring}/caching/Item.java | 2 +- .../spring}/caching/ItemRepository.java | 2 +- .../baeldung/spring}/caching/ItemService.java | 2 +- .../SpringWebfluxCachingApplication.java | 2 +- .../resources/application-cache.properties | 0 .../MonoFluxResultCachingLiveTest.java | 6 +- spring-webflux-caching/pom.xml | 67 ------------------- 9 files changed, 27 insertions(+), 77 deletions(-) rename {spring-webflux-caching/src/main/java/com/baeldung => spring-5-webflux/src/main/java/com/baeldung/spring}/caching/Item.java (96%) rename {spring-webflux-caching/src/main/java/com/baeldung => spring-5-webflux/src/main/java/com/baeldung/spring}/caching/ItemRepository.java (85%) rename {spring-webflux-caching/src/main/java/com/baeldung => spring-5-webflux/src/main/java/com/baeldung/spring}/caching/ItemService.java (96%) rename {spring-webflux-caching/src/main/java/com/baeldung => spring-5-webflux/src/main/java/com/baeldung/spring}/caching/SpringWebfluxCachingApplication.java (93%) rename spring-webflux-caching/src/main/resources/application.properties => spring-5-webflux/src/main/resources/application-cache.properties (100%) rename {spring-webflux-caching/src/test/java/com/baeldung => spring-5-webflux/src/test/java/com/baeldung/spring}/caching/MonoFluxResultCachingLiveTest.java (96%) delete mode 100644 spring-webflux-caching/pom.xml diff --git a/pom.xml b/pom.xml index 9a34ed0afe..f2a53f38b7 100644 --- a/pom.xml +++ b/pom.xml @@ -7,9 +7,6 @@ com.baeldung parent-modules 1.0.0-SNAPSHOT - - spring-webflux-caching - parent-modules pom diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index 69de83c227..cd3564d404 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -66,11 +66,31 @@ + + io.projectreactor.addons + reactor-extra + 3.4.5 + + + com.github.ben-manes.caffeine + caffeine + 3.0.4 + + + org.springframework.boot + spring-boot-starter-data-mongodb-reactive + io.projectreactor reactor-test test + + org.testcontainers + mongodb + 1.16.2 + test + com.squareup.okhttp3 mockwebserver diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/Item.java similarity index 96% rename from spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java rename to spring-5-webflux/src/main/java/com/baeldung/spring/caching/Item.java index 127975b0e7..7b79ff7503 100644 --- a/spring-webflux-caching/src/main/java/com/baeldung/caching/Item.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/Item.java @@ -1,4 +1,4 @@ -package com.baeldung.caching; +package com.baeldung.spring.caching; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document; diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/ItemRepository.java similarity index 85% rename from spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java rename to spring-5-webflux/src/main/java/com/baeldung/spring/caching/ItemRepository.java index a76489623e..27c97de36a 100644 --- a/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemRepository.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/ItemRepository.java @@ -1,4 +1,4 @@ -package com.baeldung.caching; +package com.baeldung.spring.caching; import org.springframework.data.mongodb.repository.ReactiveMongoRepository; import org.springframework.stereotype.Repository; diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/ItemService.java similarity index 96% rename from spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java rename to spring-5-webflux/src/main/java/com/baeldung/spring/caching/ItemService.java index 9dc9ba1642..b24b54521e 100644 --- a/spring-webflux-caching/src/main/java/com/baeldung/caching/ItemService.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/ItemService.java @@ -1,4 +1,4 @@ -package com.baeldung.caching; +package com.baeldung.spring.caching; import com.github.benmanes.caffeine.cache.Caffeine; import com.github.benmanes.caffeine.cache.LoadingCache; diff --git a/spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/SpringWebfluxCachingApplication.java similarity index 93% rename from spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java rename to spring-5-webflux/src/main/java/com/baeldung/spring/caching/SpringWebfluxCachingApplication.java index 7331576bd5..5266e33775 100644 --- a/spring-webflux-caching/src/main/java/com/baeldung/caching/SpringWebfluxCachingApplication.java +++ b/spring-5-webflux/src/main/java/com/baeldung/spring/caching/SpringWebfluxCachingApplication.java @@ -1,4 +1,4 @@ -package com.baeldung.caching; +package com.baeldung.spring.caching; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; diff --git a/spring-webflux-caching/src/main/resources/application.properties b/spring-5-webflux/src/main/resources/application-cache.properties similarity index 100% rename from spring-webflux-caching/src/main/resources/application.properties rename to spring-5-webflux/src/main/resources/application-cache.properties diff --git a/spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java b/spring-5-webflux/src/test/java/com/baeldung/spring/caching/MonoFluxResultCachingLiveTest.java similarity index 96% rename from spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java rename to spring-5-webflux/src/test/java/com/baeldung/spring/caching/MonoFluxResultCachingLiveTest.java index bf96b35dcb..322b3c5aa5 100644 --- a/spring-webflux-caching/src/test/java/com/baeldung/caching/MonoFluxResultCachingLiveTest.java +++ b/spring-5-webflux/src/test/java/com/baeldung/spring/caching/MonoFluxResultCachingLiveTest.java @@ -1,11 +1,10 @@ -package com.baeldung.caching; +package com.baeldung.spring.caching; -import org.assertj.core.api.Assertions; -import org.junit.ClassRule; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.testcontainers.containers.MongoDBContainer; @@ -15,6 +14,7 @@ import reactor.core.publisher.Mono; import static org.assertj.core.api.Assertions.assertThat; @SpringBootTest +@ActiveProfiles("cache") public class MonoFluxResultCachingLiveTest { diff --git a/spring-webflux-caching/pom.xml b/spring-webflux-caching/pom.xml deleted file mode 100644 index ed9800bce9..0000000000 --- a/spring-webflux-caching/pom.xml +++ /dev/null @@ -1,67 +0,0 @@ - - - 4.0.0 - com.baeldung.spring - spring-webflux-caching - 1.0.0-SNAPSHOT - spring-webflux-caching - jar - Spring WebFlux Caching Sample - - - com.baeldung - parent-boot-2 - 0.0.1-SNAPSHOT - ../parent-boot-2 - - - - - - org.springframework.boot - spring-boot-starter-webflux - - - io.reactivex.rxjava2 - rxjava - 2.2.19 - - - io.projectreactor.addons - reactor-extra - 3.4.5 - - - com.github.ben-manes.caffeine - caffeine - 3.0.4 - - - org.springframework.boot - spring-boot-starter-data-mongodb-reactive - - - com.fasterxml.jackson.core - jackson-databind - - - org.springframework.boot - spring-boot-starter-test - test - - - io.projectreactor - reactor-test - test - - - org.testcontainers - mongodb - 1.16.2 - test - - - - \ No newline at end of file From 69975a655268338ea62cebf40d89f956acaf37ab Mon Sep 17 00:00:00 2001 From: Mladen Savic Date: Sun, 14 Nov 2021 14:13:47 +0100 Subject: [PATCH 3/3] Spring Webflux and @Cacheable Annotation - reverted to older version of caffeine for jdk compatibility --- spring-5-webflux/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-5-webflux/pom.xml b/spring-5-webflux/pom.xml index cd3564d404..d6afb686fc 100644 --- a/spring-5-webflux/pom.xml +++ b/spring-5-webflux/pom.xml @@ -74,7 +74,7 @@ com.github.ben-manes.caffeine caffeine - 3.0.4 + 2.9.2 org.springframework.boot