From 43a168a5253467b01ab700d14e1a10072ca7b996 Mon Sep 17 00:00:00 2001 From: saikat Date: Wed, 28 Feb 2024 14:52:16 +0530 Subject: [PATCH 01/14] Add two level of caching --- .../caching/multicache/CacheConfig.java | 90 +++++++++++++++++++ .../baeldung/caching/multicache/Customer.java | 21 +++++ .../multicache/CustomerCacheInterceptor.java | 30 +++++++ .../multicache/CustomerController.java | 22 +++++ .../multicache/CustomerRepository.java | 44 +++++++++ .../caching/multicache/CustomerService.java | 25 ++++++ .../MultipleCachingApplication.java | 12 +++ .../src/main/resources/application.properties | 5 +- 8 files changed, 247 insertions(+), 2 deletions(-) create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java new file mode 100644 index 0000000000..29419f4c12 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java @@ -0,0 +1,90 @@ +package com.baeldung.caching.multicache; + +import com.github.benmanes.caffeine.cache.Caffeine; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.AnnotationCacheOperationSource; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.cache.interceptor.CacheInterceptor; +import org.springframework.cache.interceptor.CacheOperationSource; +import org.springframework.cache.support.SimpleCacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.data.redis.cache.RedisCacheConfiguration; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.connection.RedisStandaloneConfiguration; +import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.RedisSerializationContext; + +import java.time.Duration; +import java.util.Arrays; + +@Configuration +@EnableCaching +public class CacheConfig { + + @Value("${spring.redis.host}") + private String redisHost; + + @Value("${spring.redis.port}") + private int redisPort; + + @Bean + public CaffeineCache caffeineCacheConfig() { + return new CaffeineCache("customerCache", Caffeine.newBuilder() + .expireAfterWrite(Duration.ofMinutes(1)) + .initialCapacity(1) + .maximumSize(2000) + .build()); + } + + @Bean + @Primary + public CacheManager caffeineCacheManager() { + SimpleCacheManager manager = new SimpleCacheManager(); + manager.setCaches(Arrays.asList( + caffeineCacheConfig())); + return manager; + } + + @Bean + public CacheManager redisCacheManager() { + return RedisCacheManager.RedisCacheManagerBuilder + .fromConnectionFactory(redisConnectionFactory()) + .withCacheConfiguration("customerCache", cacheConfiguration()) + .build(); + } + + @Bean + public RedisConnectionFactory redisConnectionFactory() { + RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); + redisStandaloneConfiguration.setHostName(redisHost); + redisStandaloneConfiguration.setPort(redisPort); + return new LettuceConnectionFactory(redisStandaloneConfiguration); + } + + @Bean + public RedisCacheConfiguration cacheConfiguration() { + return RedisCacheConfiguration.defaultCacheConfig() + .entryTtl(Duration.ofMinutes(60)) + .disableCachingNullValues() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); + } + + @Bean + public CacheInterceptor cacheInterceptor() { + CacheInterceptor interceptor = new CustomerCacheInterceptor(caffeineCacheManager()); + interceptor.setCacheOperationSources(cacheOperationSource()); + return interceptor; + } + + @Bean + public CacheOperationSource cacheOperationSource() { + return new AnnotationCacheOperationSource(); + } + +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java new file mode 100644 index 0000000000..4632799a1c --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java @@ -0,0 +1,21 @@ +package com.baeldung.caching.multicache; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +@Setter +public class Customer implements Serializable { + + private String id; + + private String name; + + private String email; +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java new file mode 100644 index 0000000000..2ca1d2b2de --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java @@ -0,0 +1,30 @@ +package com.baeldung.caching.multicache; + +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.interceptor.CacheInterceptor; +import org.springframework.data.redis.cache.RedisCache; + +public class CustomerCacheInterceptor extends CacheInterceptor { + + private final CacheManager caffeineCacheManager; + + public CustomerCacheInterceptor(CacheManager caffeineCacheManager) { + this.caffeineCacheManager = caffeineCacheManager; + } + + @Override + protected Cache.ValueWrapper doGet(Cache cache, Object key) { + Cache.ValueWrapper existingCacheValue = super.doGet(cache, key); + + if (cache.getClass() == RedisCache.class) { + Cache caffeineCache = caffeineCacheManager.getCache(cache.getName()); + if (existingCacheValue != null && caffeineCache != null && caffeineCache.get(key) == null) { + caffeineCache.putIfAbsent(key, existingCacheValue.get()); + } + } + + return existingCacheValue; + } +} + diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java new file mode 100644 index 0000000000..d053754be8 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java @@ -0,0 +1,22 @@ +package com.baeldung.caching.multicache; + +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.RestController; + +@RestController +public class CustomerController { + + private final CustomerService customerService; + + @Autowired + public CustomerController(CustomerService customerService) { + this.customerService = customerService; + } + + @GetMapping("/customer/{id}") + public Customer getCustomer(@PathVariable String id) { + return customerService.getCustomer(id); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java new file mode 100644 index 0000000000..da08e299e5 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java @@ -0,0 +1,44 @@ +package com.baeldung.caching.multicache; + +import org.springframework.stereotype.Service; + +import javax.annotation.PostConstruct; +import java.util.HashMap; +import java.util.Map; + +@Service +public class CustomerRepository { + + private final Map customerMap = new HashMap<>(); + + public Customer getCustomerById(String id) { + return customerMap.get(id); + } + + @PostConstruct + private void setupCustomerRepo() { + Customer product1 = getCustomer("100001", "name1", "name1@mail.com"); + customerMap.put("100001", product1); + + Customer product2 = getCustomer("100002", "name2", "name2@mail.com"); + customerMap.put("100002", product2); + + Customer product3 = getCustomer("100003", "name3", "name3@mail.com"); + customerMap.put("100003", product3); + + Customer product4 = getCustomer("100004", "name4", "name4@mail.com"); + customerMap.put("100004", product4); + + Customer product5 = getCustomer("100005", "name5", "name5@mail.com"); + customerMap.put("100005", product5); + } + + private static Customer getCustomer(String id, String name, String email) { + Customer customer = new Customer(); + customer.setId(id); + customer.setName(name); + customer.setEmail(email); + + return customer; + } +} diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java new file mode 100644 index 0000000000..db24254d83 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java @@ -0,0 +1,25 @@ +package com.baeldung.caching.multicache; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.cache.annotation.Caching; +import org.springframework.stereotype.Service; + +@Service +public class CustomerService { + + private final CustomerRepository customerRepository; + + @Autowired + public CustomerService(CustomerRepository customerRepository) { + this.customerRepository = customerRepository; + } + + @Caching(cacheable = { + @Cacheable(cacheNames = "customerCache", cacheManager = "caffeineCacheManager"), + @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") + }) + public Customer getCustomer(String id) { + return customerRepository.getCustomerById(id); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java new file mode 100644 index 0000000000..862a2993a0 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.caching.multicache; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MultipleCachingApplication { + + public static void main(String[] args) { + SpringApplication.run(MultipleCachingApplication.class, args); + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties b/spring-boot-modules/spring-caching-2/src/main/resources/application.properties index 38f3537d01..97e4f97fcb 100644 --- a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties +++ b/spring-boot-modules/spring-caching-2/src/main/resources/application.properties @@ -9,5 +9,6 @@ spring.jpa.hibernate.ddl-auto=update #setting cache TTL caching.spring.hotelListTTL=43200 # Connection details -#spring.redis.host=localhost -#spring.redis.port=6379 +spring.redis.host=localhost +spring.redis.port=6379 +spring.main.allow-bean-definition-overriding=true From 33ed7196ba17326ebaf589c4842d8eadc3ad5a7a Mon Sep 17 00:00:00 2001 From: saikat Date: Thu, 29 Feb 2024 11:12:18 +0530 Subject: [PATCH 02/14] refactor code and add integration tests --- .../caching/multicache/CacheConfig.java | 43 ++---- .../multicache/CustomerCacheInterceptor.java | 5 +- .../src/main/resources/application.properties | 4 +- ...CustomerServiceCachingIntegrationTest.java | 128 ++++++++++++++++++ .../ItemServiceCachingIntegrationTest.java | 7 +- 5 files changed, 149 insertions(+), 38 deletions(-) create mode 100644 spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java index 29419f4c12..22b223066a 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java @@ -1,7 +1,7 @@ package com.baeldung.caching.multicache; import com.github.benmanes.caffeine.cache.Caffeine; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.AnnotationCacheOperationSource; import org.springframework.cache.annotation.EnableCaching; @@ -15,8 +15,6 @@ import org.springframework.context.annotation.Primary; import org.springframework.data.redis.cache.RedisCacheConfiguration; import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.connection.RedisStandaloneConfiguration; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializationContext; @@ -27,21 +25,6 @@ import java.util.Arrays; @EnableCaching public class CacheConfig { - @Value("${spring.redis.host}") - private String redisHost; - - @Value("${spring.redis.port}") - private int redisPort; - - @Bean - public CaffeineCache caffeineCacheConfig() { - return new CaffeineCache("customerCache", Caffeine.newBuilder() - .expireAfterWrite(Duration.ofMinutes(1)) - .initialCapacity(1) - .maximumSize(2000) - .build()); - } - @Bean @Primary public CacheManager caffeineCacheManager() { @@ -52,25 +35,26 @@ public class CacheConfig { } @Bean - public CacheManager redisCacheManager() { + public CaffeineCache caffeineCacheConfig() { + return new CaffeineCache("customerCache", Caffeine.newBuilder() + .expireAfterWrite(Duration.ofSeconds(3)) + .initialCapacity(1) + .maximumSize(2000) + .build()); + } + + @Bean + public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) { return RedisCacheManager.RedisCacheManagerBuilder - .fromConnectionFactory(redisConnectionFactory()) + .fromConnectionFactory(connectionFactory) .withCacheConfiguration("customerCache", cacheConfiguration()) .build(); } - @Bean - public RedisConnectionFactory redisConnectionFactory() { - RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(); - redisStandaloneConfiguration.setHostName(redisHost); - redisStandaloneConfiguration.setPort(redisPort); - return new LettuceConnectionFactory(redisStandaloneConfiguration); - } - @Bean public RedisCacheConfiguration cacheConfiguration() { return RedisCacheConfiguration.defaultCacheConfig() - .entryTtl(Duration.ofMinutes(60)) + .entryTtl(Duration.ofMinutes(5)) .disableCachingNullValues() .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); } @@ -86,5 +70,4 @@ public class CacheConfig { public CacheOperationSource cacheOperationSource() { return new AnnotationCacheOperationSource(); } - } \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java index 2ca1d2b2de..4c9a981489 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java @@ -17,9 +17,9 @@ public class CustomerCacheInterceptor extends CacheInterceptor { protected Cache.ValueWrapper doGet(Cache cache, Object key) { Cache.ValueWrapper existingCacheValue = super.doGet(cache, key); - if (cache.getClass() == RedisCache.class) { + if (existingCacheValue != null && cache.getClass() == RedisCache.class) { Cache caffeineCache = caffeineCacheManager.getCache(cache.getName()); - if (existingCacheValue != null && caffeineCache != null && caffeineCache.get(key) == null) { + if (caffeineCache != null) { caffeineCache.putIfAbsent(key, existingCacheValue.get()); } } @@ -27,4 +27,3 @@ public class CustomerCacheInterceptor extends CacheInterceptor { return existingCacheValue; } } - diff --git a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties b/spring-boot-modules/spring-caching-2/src/main/resources/application.properties index 97e4f97fcb..49bd715e43 100644 --- a/spring-boot-modules/spring-caching-2/src/main/resources/application.properties +++ b/spring-boot-modules/spring-caching-2/src/main/resources/application.properties @@ -9,6 +9,6 @@ spring.jpa.hibernate.ddl-auto=update #setting cache TTL caching.spring.hotelListTTL=43200 # Connection details -spring.redis.host=localhost -spring.redis.port=6379 +#spring.redis.host=localhost +#spring.redis.port=6379 spring.main.allow-bean-definition-overriding=true diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java new file mode 100644 index 0000000000..919c32fc66 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java @@ -0,0 +1,128 @@ +package com.baeldung.caching.multicache; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.ImportAutoConfiguration; +import org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration; +import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import redis.embedded.RedisServer; + +import javax.annotation.PostConstruct; +import javax.annotation.PreDestroy; + +import java.io.IOException; +import java.util.concurrent.TimeUnit; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@Import({ CacheConfig.class,CustomerService.class }) +@ExtendWith(SpringExtension.class) +@ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) +@EnableCaching +class CustomerServiceCachingIntegrationTest { + + @MockBean + private CustomerRepository customerRepository; + + @Autowired + private CustomerService customerService; + + @Autowired + private CacheManager redisCacheManager; + + @Autowired + private CacheManager caffeineCacheManager; + + @Test + void givenCustomerIsPresentInDb_whenFindCustomerById_thenCustomerReturnedFromDb_And_Cached() { + Customer customer = new Customer("100", "test", "test@mail.com"); + given(customerRepository.getCustomerById("100")) + .willReturn(customer); + + Customer customerCacheMiss = customerService.getCustomer("100"); + + assertThat(customerCacheMiss).isEqualTo(customer); + verify(customerRepository, times(1)).getCustomerById("100"); + assertThat(customerFromRedisCache("100")).isEqualTo(customer); + assertThat(customerFromCaffeineCache("100")).isEqualTo(customer); + } + + @Test + void givenCustomerIsPresentInDb_whenFindCustomerById_CalledTwice_thenCustomerReturnedFromDb_And_Cached() { + Customer customer = new Customer("101", "test", "test@mail.com"); + given(customerRepository.getCustomerById("101")) + .willReturn(customer); + + Customer customerCacheMiss = customerService.getCustomer("101"); + Customer customerCacheHit = customerService.getCustomer("101"); + + assertThat(customerCacheMiss).isEqualTo(customer); + assertThat(customerCacheHit).isEqualTo(customer); + + verify(customerRepository, times(1)).getCustomerById("101"); + assertThat(customerFromRedisCache("101")).isEqualTo(customer); + assertThat(customerFromCaffeineCache("101")).isEqualTo(customer); + } + + @Test + void givenCustomerIsPresentInDb_whenFindCustomerById_CalledThrice_thenCustomerReturnedFromDBFirst_ThenFromCache() throws InterruptedException { + Customer customer = new Customer("102", "test", "test@mail.com"); + given(customerRepository.getCustomerById("102")) + .willReturn(customer); + + Customer customerCacheMiss = customerService.getCustomer("102"); + Customer customerCacheHit = customerService.getCustomer("102"); + + TimeUnit.SECONDS.sleep(4); + + assertThat(customerFromCaffeineCache("102")).isEqualTo(null); + Customer customerCacheHitAgain = customerService.getCustomer("102"); + + verify(customerRepository, times(1)).getCustomerById("102"); + assertThat(customerCacheMiss).isEqualTo(customer); + assertThat(customerCacheHit).isEqualTo(customer); + assertThat(customerCacheHitAgain).isEqualTo(customer); + assertThat(customerFromRedisCache("102")).isEqualTo(customer); + assertThat(customerFromCaffeineCache("102")).isEqualTo(customer); + } + + private Object customerFromRedisCache(String key) { + return redisCacheManager.getCache("customerCache").get(key) != null ? + redisCacheManager.getCache("customerCache").get(key).get() : null; + } + + private Object customerFromCaffeineCache(String key) { + return caffeineCacheManager.getCache("customerCache").get(key) != null ? + caffeineCacheManager.getCache("customerCache").get(key).get() : null; + } + + @TestConfiguration + static class EmbeddedRedisConfiguration { + + private final RedisServer redisServer; + + public EmbeddedRedisConfiguration() throws IOException { + this.redisServer = new RedisServer(); + } + + @PostConstruct + public void startRedis() throws IOException { + redisServer.start(); + } + + @PreDestroy + public void stopRedis() throws IOException { + this.redisServer.stop(); + } + } +} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index 291e729fb9..b070528bf6 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -16,6 +16,7 @@ import redis.embedded.RedisServer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import java.io.IOException; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -66,17 +67,17 @@ class ItemServiceCachingIntegrationTest { private final RedisServer redisServer; - public EmbeddedRedisConfiguration() { + public EmbeddedRedisConfiguration() throws IOException { this.redisServer = new RedisServer(); } @PostConstruct - public void startRedis() { + public void startRedis() throws IOException { redisServer.start(); } @PreDestroy - public void stopRedis() { + public void stopRedis() throws IOException { this.redisServer.stop(); } } From 87826df61a1c78d83ae80aa1c5ad248e030d24eb Mon Sep 17 00:00:00 2001 From: saikat Date: Thu, 29 Feb 2024 11:17:29 +0530 Subject: [PATCH 03/14] update embeddbed redis dependencies to run test in Mac OS as well --- spring-boot-modules/spring-caching-2/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/pom.xml b/spring-boot-modules/spring-caching-2/pom.xml index 4675b5162e..3934a8b22e 100644 --- a/spring-boot-modules/spring-caching-2/pom.xml +++ b/spring-boot-modules/spring-caching-2/pom.xml @@ -51,7 +51,7 @@ ${caffeine.version} - it.ozimov + com.github.codemonstur embedded-redis ${embedded.redis.version} @@ -65,7 +65,7 @@ - 0.7.3 + 1.4.0 3.1.8 From 878509406f99ad0edc20b8fea308d073a03c2ce7 Mon Sep 17 00:00:00 2001 From: saikat Date: Thu, 29 Feb 2024 11:23:54 +0530 Subject: [PATCH 04/14] test updated --- .../ItemServiceCachingIntegrationTest.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index b070528bf6..7865add769 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -1,5 +1,14 @@ package com.baeldung.caching.redis; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import java.io.IOException; +import java.util.Optional; + +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -12,22 +21,17 @@ import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit.jupiter.SpringExtension; + import redis.embedded.RedisServer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import java.io.IOException; -import java.util.Optional; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; @Import({ CacheConfig.class, ItemService.class }) @ExtendWith(SpringExtension.class) @ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) @EnableCaching +@Disabled("This will be fixed.") class ItemServiceCachingIntegrationTest { private static final String AN_ID = "id-1"; From ff0db905bc6d1ef034740d1b890a868719f9d48b Mon Sep 17 00:00:00 2001 From: saikat Date: Thu, 29 Feb 2024 11:29:42 +0530 Subject: [PATCH 05/14] reverted dependencies to check --- spring-boot-modules/spring-caching-2/pom.xml | 8 +++---- ...CustomerServiceCachingIntegrationTest.java | 7 +++--- .../ItemServiceCachingIntegrationTest.java | 23 ++++++++----------- 3 files changed, 16 insertions(+), 22 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/pom.xml b/spring-boot-modules/spring-caching-2/pom.xml index 3934a8b22e..7a4744802a 100644 --- a/spring-boot-modules/spring-caching-2/pom.xml +++ b/spring-boot-modules/spring-caching-2/pom.xml @@ -1,7 +1,7 @@ + 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"> 4.0.0 spring-caching-2 0.1-SNAPSHOT @@ -51,7 +51,7 @@ ${caffeine.version} - com.github.codemonstur + it.ozimov embedded-redis ${embedded.redis.version} @@ -65,7 +65,7 @@ - 1.4.0 + 0.7.3 3.1.8 diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java index 919c32fc66..17faef871c 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java @@ -17,7 +17,6 @@ import redis.embedded.RedisServer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; -import java.io.IOException; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; @@ -111,17 +110,17 @@ class CustomerServiceCachingIntegrationTest { private final RedisServer redisServer; - public EmbeddedRedisConfiguration() throws IOException { + public EmbeddedRedisConfiguration() { this.redisServer = new RedisServer(); } @PostConstruct - public void startRedis() throws IOException { + public void startRedis() { redisServer.start(); } @PreDestroy - public void stopRedis() throws IOException { + public void stopRedis() { this.redisServer.stop(); } } diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index 7865add769..291e729fb9 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -1,14 +1,5 @@ package com.baeldung.caching.redis; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - -import java.io.IOException; -import java.util.Optional; - -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -21,17 +12,21 @@ import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Import; import org.springframework.test.context.junit.jupiter.SpringExtension; - import redis.embedded.RedisServer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; @Import({ CacheConfig.class, ItemService.class }) @ExtendWith(SpringExtension.class) @ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) @EnableCaching -@Disabled("This will be fixed.") class ItemServiceCachingIntegrationTest { private static final String AN_ID = "id-1"; @@ -71,17 +66,17 @@ class ItemServiceCachingIntegrationTest { private final RedisServer redisServer; - public EmbeddedRedisConfiguration() throws IOException { + public EmbeddedRedisConfiguration() { this.redisServer = new RedisServer(); } @PostConstruct - public void startRedis() throws IOException { + public void startRedis() { redisServer.start(); } @PreDestroy - public void stopRedis() throws IOException { + public void stopRedis() { this.redisServer.stop(); } } From 5b7a864ef29a1f5b2bdd115fafe1e4bb8f295d19 Mon Sep 17 00:00:00 2001 From: saikat Date: Fri, 1 Mar 2024 13:08:58 +0530 Subject: [PATCH 06/14] refactor code for customer repository and update embedded redis repository --- spring-boot-modules/spring-caching-2/pom.xml | 8 +-- .../caching/multicache/CacheConfig.java | 3 +- .../multicache/CustomerController.java | 22 ------ .../multicache/CustomerRepository.java | 41 +---------- .../caching/multicache/CustomerService.java | 3 +- ...CustomerServiceCachingIntegrationTest.java | 71 +++++++++---------- .../ItemServiceCachingIntegrationTest.java | 7 +- 7 files changed, 48 insertions(+), 107 deletions(-) delete mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java diff --git a/spring-boot-modules/spring-caching-2/pom.xml b/spring-boot-modules/spring-caching-2/pom.xml index 7a4744802a..3934a8b22e 100644 --- a/spring-boot-modules/spring-caching-2/pom.xml +++ b/spring-boot-modules/spring-caching-2/pom.xml @@ -1,7 +1,7 @@ + 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"> 4.0.0 spring-caching-2 0.1-SNAPSHOT @@ -51,7 +51,7 @@ ${caffeine.version} - it.ozimov + com.github.codemonstur embedded-redis ${embedded.redis.version} @@ -65,7 +65,7 @@ - 0.7.3 + 1.4.0 3.1.8 diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java index 22b223066a..a911bdf161 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java @@ -1,7 +1,6 @@ package com.baeldung.caching.multicache; import com.github.benmanes.caffeine.cache.Caffeine; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.AnnotationCacheOperationSource; import org.springframework.cache.annotation.EnableCaching; @@ -37,7 +36,7 @@ public class CacheConfig { @Bean public CaffeineCache caffeineCacheConfig() { return new CaffeineCache("customerCache", Caffeine.newBuilder() - .expireAfterWrite(Duration.ofSeconds(3)) + .expireAfterWrite(Duration.ofSeconds(1)) .initialCapacity(1) .maximumSize(2000) .build()); diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java deleted file mode 100644 index d053754be8..0000000000 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerController.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.caching.multicache; - -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.RestController; - -@RestController -public class CustomerController { - - private final CustomerService customerService; - - @Autowired - public CustomerController(CustomerService customerService) { - this.customerService = customerService; - } - - @GetMapping("/customer/{id}") - public Customer getCustomer(@PathVariable String id) { - return customerService.getCustomer(id); - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java index da08e299e5..3281e35c76 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java @@ -1,44 +1,7 @@ package com.baeldung.caching.multicache; -import org.springframework.stereotype.Service; +import org.springframework.data.repository.CrudRepository; -import javax.annotation.PostConstruct; -import java.util.HashMap; -import java.util.Map; -@Service -public class CustomerRepository { - - private final Map customerMap = new HashMap<>(); - - public Customer getCustomerById(String id) { - return customerMap.get(id); - } - - @PostConstruct - private void setupCustomerRepo() { - Customer product1 = getCustomer("100001", "name1", "name1@mail.com"); - customerMap.put("100001", product1); - - Customer product2 = getCustomer("100002", "name2", "name2@mail.com"); - customerMap.put("100002", product2); - - Customer product3 = getCustomer("100003", "name3", "name3@mail.com"); - customerMap.put("100003", product3); - - Customer product4 = getCustomer("100004", "name4", "name4@mail.com"); - customerMap.put("100004", product4); - - Customer product5 = getCustomer("100005", "name5", "name5@mail.com"); - customerMap.put("100005", product5); - } - - private static Customer getCustomer(String id, String name, String email) { - Customer customer = new Customer(); - customer.setId(id); - customer.setName(name); - customer.setEmail(email); - - return customer; - } +public interface CustomerRepository extends CrudRepository { } diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java index db24254d83..14a7f293c8 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java @@ -20,6 +20,7 @@ public class CustomerService { @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") }) public Customer getCustomer(String id) { - return customerRepository.getCustomerById(id); + return customerRepository.findById(id) + .orElseThrow(RuntimeException::new); } } \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java index 17faef871c..df53eb2833 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java @@ -17,6 +17,8 @@ import redis.embedded.RedisServer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import java.io.IOException; +import java.util.Optional; import java.util.concurrent.TimeUnit; import static org.assertj.core.api.Assertions.assertThat; @@ -43,56 +45,53 @@ class CustomerServiceCachingIntegrationTest { private CacheManager caffeineCacheManager; @Test - void givenCustomerIsPresentInDb_whenFindCustomerById_thenCustomerReturnedFromDb_And_Cached() { - Customer customer = new Customer("100", "test", "test@mail.com"); - given(customerRepository.getCustomerById("100")) - .willReturn(customer); + void givenCustomerIsPresentInDB_whenGetCustomerById_thenCustomerReturnedFromDBAndCached() { + String CUSTOMER_ID = "100"; + Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); - Customer customerCacheMiss = customerService.getCustomer("100"); + given(customerRepository.findById(CUSTOMER_ID)) + .willReturn(Optional.of(customer)); + + Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); assertThat(customerCacheMiss).isEqualTo(customer); - verify(customerRepository, times(1)).getCustomerById("100"); - assertThat(customerFromRedisCache("100")).isEqualTo(customer); - assertThat(customerFromCaffeineCache("100")).isEqualTo(customer); + verify(customerRepository, times(1)).findById(CUSTOMER_ID); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); } @Test - void givenCustomerIsPresentInDb_whenFindCustomerById_CalledTwice_thenCustomerReturnedFromDb_And_Cached() { - Customer customer = new Customer("101", "test", "test@mail.com"); - given(customerRepository.getCustomerById("101")) - .willReturn(customer); + void givenCustomerIsPresentInDB_whenGetCustomerByIdIsCalledTwice_thenCustomerReturnedFromDBAndCached() { + String CUSTOMER_ID = "101"; + Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); + given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); - Customer customerCacheMiss = customerService.getCustomer("101"); - Customer customerCacheHit = customerService.getCustomer("101"); + Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); + Customer customerCacheHit = customerService.getCustomer(CUSTOMER_ID); assertThat(customerCacheMiss).isEqualTo(customer); assertThat(customerCacheHit).isEqualTo(customer); - - verify(customerRepository, times(1)).getCustomerById("101"); - assertThat(customerFromRedisCache("101")).isEqualTo(customer); - assertThat(customerFromCaffeineCache("101")).isEqualTo(customer); + verify(customerRepository, times(1)).findById(CUSTOMER_ID); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); } @Test - void givenCustomerIsPresentInDb_whenFindCustomerById_CalledThrice_thenCustomerReturnedFromDBFirst_ThenFromCache() throws InterruptedException { - Customer customer = new Customer("102", "test", "test@mail.com"); - given(customerRepository.getCustomerById("102")) - .willReturn(customer); + void givenCustomerIsPresentInDB_whenGetCustomerByIdIsCalledThrice_thenCustomerReturnedFromDBAndCached() throws InterruptedException { + String CUSTOMER_ID = "102"; + Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); + given(customerRepository.findById(CUSTOMER_ID)) + .willReturn(Optional.of(customer)); - Customer customerCacheMiss = customerService.getCustomer("102"); - Customer customerCacheHit = customerService.getCustomer("102"); + Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); + TimeUnit.SECONDS.sleep(2); + Customer customerCacheHit = customerService.getCustomer(CUSTOMER_ID); - TimeUnit.SECONDS.sleep(4); - - assertThat(customerFromCaffeineCache("102")).isEqualTo(null); - Customer customerCacheHitAgain = customerService.getCustomer("102"); - - verify(customerRepository, times(1)).getCustomerById("102"); + verify(customerRepository, times(1)).findById(CUSTOMER_ID); assertThat(customerCacheMiss).isEqualTo(customer); assertThat(customerCacheHit).isEqualTo(customer); - assertThat(customerCacheHitAgain).isEqualTo(customer); - assertThat(customerFromRedisCache("102")).isEqualTo(customer); - assertThat(customerFromCaffeineCache("102")).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); } private Object customerFromRedisCache(String key) { @@ -110,17 +109,17 @@ class CustomerServiceCachingIntegrationTest { private final RedisServer redisServer; - public EmbeddedRedisConfiguration() { + public EmbeddedRedisConfiguration() throws IOException { this.redisServer = new RedisServer(); } @PostConstruct - public void startRedis() { + public void startRedis() throws IOException { redisServer.start(); } @PreDestroy - public void stopRedis() { + public void stopRedis() throws IOException { this.redisServer.stop(); } } diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index 291e729fb9..b070528bf6 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -16,6 +16,7 @@ import redis.embedded.RedisServer; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; +import java.io.IOException; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -66,17 +67,17 @@ class ItemServiceCachingIntegrationTest { private final RedisServer redisServer; - public EmbeddedRedisConfiguration() { + public EmbeddedRedisConfiguration() throws IOException { this.redisServer = new RedisServer(); } @PostConstruct - public void startRedis() { + public void startRedis() throws IOException { redisServer.start(); } @PreDestroy - public void stopRedis() { + public void stopRedis() throws IOException { this.redisServer.stop(); } } From 03f52e6329af6196b9272f56b39528ea06451d55 Mon Sep 17 00:00:00 2001 From: saikat Date: Fri, 1 Mar 2024 16:03:55 +0530 Subject: [PATCH 07/14] refactor code --- .../multicache/MultipleCachingApplication.java | 12 ------------ .../{multicache => twolevelcache}/CacheConfig.java | 5 ++--- .../{multicache => twolevelcache}/Customer.java | 2 +- .../CustomerCacheInterceptor.java | 2 +- .../CustomerRepository.java | 3 +-- .../CustomerService.java | 2 +- .../redis/ItemServiceCachingIntegrationTest.java | 10 +++++----- .../CustomerServiceCachingIntegrationTest.java | 12 ++++++------ 8 files changed, 17 insertions(+), 31 deletions(-) delete mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java rename spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/{multicache => twolevelcache}/CacheConfig.java (95%) rename spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/{multicache => twolevelcache}/Customer.java (87%) rename spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/{multicache => twolevelcache}/CustomerCacheInterceptor.java (95%) rename spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/{multicache => twolevelcache}/CustomerRepository.java (76%) rename spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/{multicache => twolevelcache}/CustomerService.java (94%) rename spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/{multicache => twolevelcache}/CustomerServiceCachingIntegrationTest.java (99%) diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java deleted file mode 100644 index 862a2993a0..0000000000 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/MultipleCachingApplication.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.baeldung.caching.multicache; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class MultipleCachingApplication { - - public static void main(String[] args) { - SpringApplication.run(MultipleCachingApplication.class, args); - } -} \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java similarity index 95% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java rename to spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java index a911bdf161..2072f5806a 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java @@ -1,4 +1,4 @@ -package com.baeldung.caching.multicache; +package com.baeldung.caching.twolevelcache; import com.github.benmanes.caffeine.cache.Caffeine; import org.springframework.cache.CacheManager; @@ -28,8 +28,7 @@ public class CacheConfig { @Primary public CacheManager caffeineCacheManager() { SimpleCacheManager manager = new SimpleCacheManager(); - manager.setCaches(Arrays.asList( - caffeineCacheConfig())); + manager.setCaches(Arrays.asList(caffeineCacheConfig())); return manager; } diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java similarity index 87% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java rename to spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java index 4632799a1c..a2d1a14ea3 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/Customer.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java @@ -1,4 +1,4 @@ -package com.baeldung.caching.multicache; +package com.baeldung.caching.twolevelcache; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java similarity index 95% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java rename to spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java index 4c9a981489..f1a8dca0db 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerCacheInterceptor.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerCacheInterceptor.java @@ -1,4 +1,4 @@ -package com.baeldung.caching.multicache; +package com.baeldung.caching.twolevelcache; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java similarity index 76% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java rename to spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java index 3281e35c76..098112f152 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerRepository.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerRepository.java @@ -1,7 +1,6 @@ -package com.baeldung.caching.multicache; +package com.baeldung.caching.twolevelcache; import org.springframework.data.repository.CrudRepository; - public interface CustomerRepository extends CrudRepository { } diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java similarity index 94% rename from spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java rename to spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java index 14a7f293c8..68e78c9fdb 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/multicache/CustomerService.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java @@ -1,4 +1,4 @@ -package com.baeldung.caching.multicache; +package com.baeldung.caching.twolevelcache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.Cacheable; diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index b070528bf6..e25773305a 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -1,5 +1,10 @@ package com.baeldung.caching.redis; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; @@ -19,11 +24,6 @@ import javax.annotation.PreDestroy; import java.io.IOException; import java.util.Optional; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - @Import({ CacheConfig.class, ItemService.class }) @ExtendWith(SpringExtension.class) @ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java similarity index 99% rename from spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java rename to spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java index df53eb2833..6aa3242c95 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/multicache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java @@ -1,4 +1,9 @@ -package com.baeldung.caching.multicache; +package com.baeldung.caching.twolevelcache; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -21,11 +26,6 @@ import java.io.IOException; import java.util.Optional; import java.util.concurrent.TimeUnit; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; - @Import({ CacheConfig.class,CustomerService.class }) @ExtendWith(SpringExtension.class) @ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) From f959e7a273a56b90e7614b44a7cb1de9e4477f1d Mon Sep 17 00:00:00 2001 From: saikat Date: Sat, 2 Mar 2024 09:43:32 +0530 Subject: [PATCH 08/14] fixed int test issue with redis server --- .../com/baeldung/caching/twolevelcache/CacheConfig.java | 2 +- .../CustomerServiceCachingIntegrationTest.java | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java index 2072f5806a..67d857eb24 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java @@ -35,7 +35,7 @@ public class CacheConfig { @Bean public CaffeineCache caffeineCacheConfig() { return new CaffeineCache("customerCache", Caffeine.newBuilder() - .expireAfterWrite(Duration.ofSeconds(1)) + .expireAfterWrite(Duration.ofSeconds(3)) .initialCapacity(1) .maximumSize(2000) .build()); diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java index 6aa3242c95..b28c70da0c 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java @@ -16,6 +16,7 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Import; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import redis.embedded.RedisServer; @@ -30,6 +31,7 @@ import java.util.concurrent.TimeUnit; @ExtendWith(SpringExtension.class) @ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) @EnableCaching +@TestPropertySource(properties = {"spring.redis.port=7000"}) class CustomerServiceCachingIntegrationTest { @MockBean @@ -84,7 +86,8 @@ class CustomerServiceCachingIntegrationTest { .willReturn(Optional.of(customer)); Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); - TimeUnit.SECONDS.sleep(2); + TimeUnit.SECONDS.sleep(3); + assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(null); Customer customerCacheHit = customerService.getCustomer(CUSTOMER_ID); verify(customerRepository, times(1)).findById(CUSTOMER_ID); @@ -110,7 +113,7 @@ class CustomerServiceCachingIntegrationTest { private final RedisServer redisServer; public EmbeddedRedisConfiguration() throws IOException { - this.redisServer = new RedisServer(); + this.redisServer = new RedisServer(7000); } @PostConstruct From 605568587ec6e11b43f5a05262928652b842c4e7 Mon Sep 17 00:00:00 2001 From: saikat Date: Sat, 2 Mar 2024 11:06:37 +0530 Subject: [PATCH 09/14] Add application file and update entity in model --- .../baeldung/caching/twolevelcache/Customer.java | 4 ++++ .../twolevelcache/TwoLevelCacheApplication.java | 14 ++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java index a2d1a14ea3..b8a1b7d6b2 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java @@ -5,14 +5,18 @@ import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; +import javax.persistence.Entity; +import javax.persistence.Id; import java.io.Serializable; @Data +@Entity @AllArgsConstructor @NoArgsConstructor @Setter public class Customer implements Serializable { + @Id private String id; private String name; diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java new file mode 100644 index 0000000000..867f4c9f91 --- /dev/null +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java @@ -0,0 +1,14 @@ +package com.baeldung.caching.twolevelcache; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.cache.annotation.EnableCaching; + +@SpringBootApplication +@EnableCaching +public class TwoLevelCacheApplication { + + public static void main(String[] args) { + SpringApplication.run(TwoLevelCacheApplication.class, args); + } +} \ No newline at end of file From d5490dd79450186299877f3748c1921ddf3e8872 Mon Sep 17 00:00:00 2001 From: saikat Date: Sat, 2 Mar 2024 14:01:28 +0530 Subject: [PATCH 10/14] rename method --- .../caching/redis/ItemServiceCachingIntegrationTest.java | 1 + .../twolevelcache/CustomerServiceCachingIntegrationTest.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index 07d9f0316b..7134c4727c 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -5,6 +5,7 @@ import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java index b28c70da0c..0bc1a5c1fc 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java @@ -79,7 +79,7 @@ class CustomerServiceCachingIntegrationTest { } @Test - void givenCustomerIsPresentInDB_whenGetCustomerByIdIsCalledThrice_thenCustomerReturnedFromDBAndCached() throws InterruptedException { + void givenCustomerIsPresentInDB_whenGetCustomerByIdIsCalledTwice_AndFirstCacheExpires_thenCustomerReturnedFromDBAndCached() throws InterruptedException { String CUSTOMER_ID = "102"; Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); given(customerRepository.findById(CUSTOMER_ID)) From b182b42c0747967fd31f26d7526472b82fbd2ee6 Mon Sep 17 00:00:00 2001 From: saikat Date: Sat, 2 Mar 2024 15:39:52 +0530 Subject: [PATCH 11/14] fix the imports with latest changes --- .../com/baeldung/caching/twolevelcache/Customer.java | 4 ++-- .../caching/redis/ItemServiceCachingIntegrationTest.java | 4 ++-- .../CustomerServiceCachingIntegrationTest.java | 9 +++------ 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java index b8a1b7d6b2..0b985d35f3 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/Customer.java @@ -1,12 +1,12 @@ package com.baeldung.caching.twolevelcache; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import lombok.Setter; -import javax.persistence.Entity; -import javax.persistence.Id; import java.io.Serializable; @Data diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java index 7134c4727c..01740ba780 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/redis/ItemServiceCachingIntegrationTest.java @@ -20,8 +20,8 @@ import org.springframework.context.annotation.Import; import org.springframework.test.context.junit.jupiter.SpringExtension; import redis.embedded.RedisServer; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.util.Optional; diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java index 0bc1a5c1fc..93f61b5916 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java @@ -16,13 +16,11 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Import; -import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; import redis.embedded.RedisServer; -import javax.annotation.PostConstruct; -import javax.annotation.PreDestroy; - +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; import java.io.IOException; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -31,7 +29,6 @@ import java.util.concurrent.TimeUnit; @ExtendWith(SpringExtension.class) @ImportAutoConfiguration(classes = { CacheAutoConfiguration.class, RedisAutoConfiguration.class }) @EnableCaching -@TestPropertySource(properties = {"spring.redis.port=7000"}) class CustomerServiceCachingIntegrationTest { @MockBean @@ -113,7 +110,7 @@ class CustomerServiceCachingIntegrationTest { private final RedisServer redisServer; public EmbeddedRedisConfiguration() throws IOException { - this.redisServer = new RedisServer(7000); + this.redisServer = new RedisServer(); } @PostConstruct From b2a0a75389267b7fca56e7e90f86d5550df3dfc8 Mon Sep 17 00:00:00 2001 From: saikat Date: Wed, 6 Mar 2024 13:09:58 +0530 Subject: [PATCH 12/14] reformatting from default and update test method names --- .../caching/twolevelcache/CacheConfig.java | 30 +++++++++---------- .../twolevelcache/CustomerService.java | 6 ++-- .../TwoLevelCacheApplication.java | 2 -- ...CustomerServiceCachingIntegrationTest.java | 22 +++++++------- 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java index 67d857eb24..e8642e43ba 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java @@ -26,40 +26,40 @@ public class CacheConfig { @Bean @Primary - public CacheManager caffeineCacheManager() { + public CacheManager caffeineCacheManager(CaffeineCache caffeineCache) { SimpleCacheManager manager = new SimpleCacheManager(); - manager.setCaches(Arrays.asList(caffeineCacheConfig())); + manager.setCaches(Arrays.asList(caffeineCache)); return manager; } @Bean public CaffeineCache caffeineCacheConfig() { return new CaffeineCache("customerCache", Caffeine.newBuilder() - .expireAfterWrite(Duration.ofSeconds(3)) - .initialCapacity(1) - .maximumSize(2000) - .build()); + .expireAfterWrite(Duration.ofSeconds(3)) + .initialCapacity(1) + .maximumSize(2000) + .build()); } @Bean - public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory) { + public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory, RedisCacheConfiguration redisCacheConfiguration) { return RedisCacheManager.RedisCacheManagerBuilder - .fromConnectionFactory(connectionFactory) - .withCacheConfiguration("customerCache", cacheConfiguration()) - .build(); + .fromConnectionFactory(connectionFactory) + .withCacheConfiguration("customerCache", redisCacheConfiguration) + .build(); } @Bean public RedisCacheConfiguration cacheConfiguration() { return RedisCacheConfiguration.defaultCacheConfig() - .entryTtl(Duration.ofMinutes(5)) - .disableCachingNullValues() - .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); + .entryTtl(Duration.ofMinutes(5)) + .disableCachingNullValues() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); } @Bean - public CacheInterceptor cacheInterceptor() { - CacheInterceptor interceptor = new CustomerCacheInterceptor(caffeineCacheManager()); + public CacheInterceptor cacheInterceptor(CacheManager caffeineCacheManager) { + CacheInterceptor interceptor = new CustomerCacheInterceptor(caffeineCacheManager); interceptor.setCacheOperationSources(cacheOperationSource()); return interceptor; } diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java index 68e78c9fdb..20bc91f7b2 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java @@ -16,11 +16,11 @@ public class CustomerService { } @Caching(cacheable = { - @Cacheable(cacheNames = "customerCache", cacheManager = "caffeineCacheManager"), - @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") + @Cacheable(cacheNames = "customerCache", cacheManager = "caffeineCacheManager"), + @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") }) public Customer getCustomer(String id) { return customerRepository.findById(id) - .orElseThrow(RuntimeException::new); + .orElseThrow(RuntimeException::new); } } \ No newline at end of file diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java index 867f4c9f91..9bc2c65e6e 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/TwoLevelCacheApplication.java @@ -2,10 +2,8 @@ package com.baeldung.caching.twolevelcache; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.cache.annotation.EnableCaching; @SpringBootApplication -@EnableCaching public class TwoLevelCacheApplication { public static void main(String[] args) { diff --git a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java index 93f61b5916..3db53198fc 100644 --- a/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java +++ b/spring-boot-modules/spring-caching-2/src/test/java/com/baeldung/caching/twolevelcache/CustomerServiceCachingIntegrationTest.java @@ -44,23 +44,22 @@ class CustomerServiceCachingIntegrationTest { private CacheManager caffeineCacheManager; @Test - void givenCustomerIsPresentInDB_whenGetCustomerById_thenCustomerReturnedFromDBAndCached() { + void givenCustomerIsPresent_whenGetCustomerCalled_thenReturnCustomerAndCacheIt() { String CUSTOMER_ID = "100"; Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); - given(customerRepository.findById(CUSTOMER_ID)) - .willReturn(Optional.of(customer)); + given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); assertThat(customerCacheMiss).isEqualTo(customer); verify(customerRepository, times(1)).findById(CUSTOMER_ID); - assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); } @Test - void givenCustomerIsPresentInDB_whenGetCustomerByIdIsCalledTwice_thenCustomerReturnedFromDBAndCached() { + void givenCustomerIsPresent_whenGetCustomerCalledTwice_thenReturnCustomerAndCacheIt() { String CUSTOMER_ID = "101"; Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); @@ -71,16 +70,15 @@ class CustomerServiceCachingIntegrationTest { assertThat(customerCacheMiss).isEqualTo(customer); assertThat(customerCacheHit).isEqualTo(customer); verify(customerRepository, times(1)).findById(CUSTOMER_ID); - assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); } @Test - void givenCustomerIsPresentInDB_whenGetCustomerByIdIsCalledTwice_AndFirstCacheExpires_thenCustomerReturnedFromDBAndCached() throws InterruptedException { + void givenCustomerIsPresent_whenGetCustomerCalledTwiceAndFirstCacheExpired_thenReturnCustomerAndCacheIt() throws InterruptedException { String CUSTOMER_ID = "102"; Customer customer = new Customer(CUSTOMER_ID, "test", "test@mail.com"); - given(customerRepository.findById(CUSTOMER_ID)) - .willReturn(Optional.of(customer)); + given(customerRepository.findById(CUSTOMER_ID)).willReturn(Optional.of(customer)); Customer customerCacheMiss = customerService.getCustomer(CUSTOMER_ID); TimeUnit.SECONDS.sleep(3); @@ -90,18 +88,18 @@ class CustomerServiceCachingIntegrationTest { verify(customerRepository, times(1)).findById(CUSTOMER_ID); assertThat(customerCacheMiss).isEqualTo(customer); assertThat(customerCacheHit).isEqualTo(customer); - assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); assertThat(customerFromCaffeineCache(CUSTOMER_ID)).isEqualTo(customer); + assertThat(customerFromRedisCache(CUSTOMER_ID)).isEqualTo(customer); } private Object customerFromRedisCache(String key) { return redisCacheManager.getCache("customerCache").get(key) != null ? - redisCacheManager.getCache("customerCache").get(key).get() : null; + redisCacheManager.getCache("customerCache").get(key).get() : null; } private Object customerFromCaffeineCache(String key) { return caffeineCacheManager.getCache("customerCache").get(key) != null ? - caffeineCacheManager.getCache("customerCache").get(key).get() : null; + caffeineCacheManager.getCache("customerCache").get(key).get() : null; } @TestConfiguration From e7d85015e342d073fa46caaea0fb80d5bcba24a1 Mon Sep 17 00:00:00 2001 From: saikat Date: Wed, 6 Mar 2024 13:56:59 +0530 Subject: [PATCH 13/14] autwire via method param --- .../java/com/baeldung/caching/twolevelcache/CacheConfig.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java index e8642e43ba..b1bec0f4a1 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java @@ -58,9 +58,9 @@ public class CacheConfig { } @Bean - public CacheInterceptor cacheInterceptor(CacheManager caffeineCacheManager) { + public CacheInterceptor cacheInterceptor(CacheManager caffeineCacheManager, CacheOperationSource cacheOperationSource) { CacheInterceptor interceptor = new CustomerCacheInterceptor(caffeineCacheManager); - interceptor.setCacheOperationSources(cacheOperationSource()); + interceptor.setCacheOperationSources(cacheOperationSource); return interceptor; } From 126f7626191a56e1405a1a3a210122e6aebc62b9 Mon Sep 17 00:00:00 2001 From: saikat Date: Wed, 6 Mar 2024 15:25:04 +0530 Subject: [PATCH 14/14] reformated --- .../caching/twolevelcache/CacheConfig.java | 22 +++++++++---------- .../twolevelcache/CustomerService.java | 6 ++--- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java index b1bec0f4a1..576bcd97ab 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CacheConfig.java @@ -1,6 +1,7 @@ package com.baeldung.caching.twolevelcache; import com.github.benmanes.caffeine.cache.Caffeine; + import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.AnnotationCacheOperationSource; import org.springframework.cache.annotation.EnableCaching; @@ -35,26 +36,25 @@ public class CacheConfig { @Bean public CaffeineCache caffeineCacheConfig() { return new CaffeineCache("customerCache", Caffeine.newBuilder() - .expireAfterWrite(Duration.ofSeconds(3)) - .initialCapacity(1) - .maximumSize(2000) - .build()); + .expireAfterWrite(Duration.ofSeconds(3)) + .initialCapacity(1) + .maximumSize(2000) + .build()); } @Bean public CacheManager redisCacheManager(RedisConnectionFactory connectionFactory, RedisCacheConfiguration redisCacheConfiguration) { - return RedisCacheManager.RedisCacheManagerBuilder - .fromConnectionFactory(connectionFactory) - .withCacheConfiguration("customerCache", redisCacheConfiguration) - .build(); + return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory) + .withCacheConfiguration("customerCache", redisCacheConfiguration) + .build(); } @Bean public RedisCacheConfiguration cacheConfiguration() { return RedisCacheConfiguration.defaultCacheConfig() - .entryTtl(Duration.ofMinutes(5)) - .disableCachingNullValues() - .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); + .entryTtl(Duration.ofMinutes(5)) + .disableCachingNullValues() + .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer())); } @Bean diff --git a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java index 20bc91f7b2..088b66919c 100644 --- a/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java +++ b/spring-boot-modules/spring-caching-2/src/main/java/com/baeldung/caching/twolevelcache/CustomerService.java @@ -16,11 +16,11 @@ public class CustomerService { } @Caching(cacheable = { - @Cacheable(cacheNames = "customerCache", cacheManager = "caffeineCacheManager"), - @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") + @Cacheable(cacheNames = "customerCache", cacheManager = "caffeineCacheManager"), + @Cacheable(cacheNames = "customerCache", cacheManager = "redisCacheManager") }) public Customer getCustomer(String id) { return customerRepository.findById(id) - .orElseThrow(RuntimeException::new); + .orElseThrow(RuntimeException::new); } } \ No newline at end of file