Spring Webflux and @Cacheable Annotation
This commit is contained in:
parent
3ab032d095
commit
19437f2e13
3
pom.xml
3
pom.xml
|
@ -7,6 +7,9 @@
|
|||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-modules</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<modules>
|
||||
<module>spring-webflux-caching</module>
|
||||
</modules>
|
||||
<name>parent-modules</name>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
<?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.baeldung.spring</groupId>
|
||||
<artifactId>spring-webflux-caching</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>spring-webflux-caching</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Spring WebFlux Caching Sample</description>
|
||||
|
||||
<parent>
|
||||
<groupId>com.baeldung</groupId>
|
||||
<artifactId>parent-boot-2</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../parent-boot-2</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.reactivex.rxjava2</groupId>
|
||||
<artifactId>rxjava</artifactId>
|
||||
<version>2.2.19</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor.addons</groupId>
|
||||
<artifactId>reactor-extra</artifactId>
|
||||
<version>3.4.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
<artifactId>caffeine</artifactId>
|
||||
<version>3.0.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.testcontainers</groupId>
|
||||
<artifactId>mongodb</artifactId>
|
||||
<version>1.16.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
|
@ -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 +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -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<Item, String> {
|
||||
}
|
|
@ -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<String, Object> cache;
|
||||
|
||||
public ItemService(ItemRepository repository) {
|
||||
this.repository = repository;
|
||||
this.cache = Caffeine.newBuilder()
|
||||
.build(this::getItem_withAddons);
|
||||
}
|
||||
|
||||
@Cacheable("items")
|
||||
public Mono<Item> getItem(String id) {
|
||||
return repository.findById(id);
|
||||
}
|
||||
|
||||
public Mono<Item> save(Item item) {
|
||||
return repository.save(item);
|
||||
}
|
||||
|
||||
@Cacheable("items")
|
||||
public Mono<Item> getItem_withCache(String id) {
|
||||
return repository.findById(id).cache();
|
||||
}
|
||||
|
||||
@Cacheable("items")
|
||||
public Mono<Item> getItem_withAddons(String id) {
|
||||
return CacheMono.lookup(cache.asMap(), id)
|
||||
.onCacheMissResume(() -> repository.findById(id).cast(Object.class)).cast(Item.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
logging.level.org.springframework.data.mongodb.core.ReactiveMongoTemplate=DEBUG
|
||||
logging.level.org.springframework.cache=TRACE
|
|
@ -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<Item> glass = itemService.save(new Item("glass", 1.00));
|
||||
|
||||
String id = glass.block().get_id();
|
||||
|
||||
Mono<Item> mono = itemService.getItem(id);
|
||||
Item item = mono.block();
|
||||
|
||||
assertThat(item).isNotNull();
|
||||
assertThat(item.getName()).isEqualTo("glass");
|
||||
assertThat(item.getPrice()).isEqualTo(1.00);
|
||||
|
||||
Mono<Item> 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<Item> glass = itemService.save(new Item("glass", 1.00));
|
||||
|
||||
String id = glass.block().get_id();
|
||||
|
||||
Mono<Item> mono = itemService.getItem_withCache(id);
|
||||
Item item = mono.block();
|
||||
|
||||
assertThat(item).isNotNull();
|
||||
assertThat(item.getName()).isEqualTo("glass");
|
||||
assertThat(item.getPrice()).isEqualTo(1.00);
|
||||
|
||||
Mono<Item> 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<Item> glass = itemService.save(new Item("glass", 1.00));
|
||||
|
||||
String id = glass.block().get_id();
|
||||
|
||||
Mono<Item> mono = itemService.getItem_withAddons(id);
|
||||
Item item = mono.block();
|
||||
|
||||
assertThat(item).isNotNull();
|
||||
assertThat(item.getName()).isEqualTo("glass");
|
||||
assertThat(item.getPrice()).isEqualTo(1.00);
|
||||
|
||||
Mono<Item> mono2 = itemService.getItem_withAddons(id);
|
||||
Item item2 = mono2.block();
|
||||
|
||||
assertThat(item2).isNotNull();
|
||||
assertThat(item2.getName()).isEqualTo("glass");
|
||||
assertThat(item2.getPrice()).isEqualTo(1.00);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue