diff --git a/boot-ultimate-redis/pom.xml b/boot-ultimate-redis/pom.xml
index d80d144b0..7c731ffdc 100644
--- a/boot-ultimate-redis/pom.xml
+++ b/boot-ultimate-redis/pom.xml
@@ -38,6 +38,10 @@
org.springframework.boot
spring-boot-starter-data-redis
+
+ org.apache.commons
+ commons-pool2
+
commons-io
commons-io
diff --git a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/UltimateRedisApplication.java b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/UltimateRedisApplication.java
index 6d83a854c..493083125 100644
--- a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/UltimateRedisApplication.java
+++ b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/UltimateRedisApplication.java
@@ -2,9 +2,7 @@
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.cache.annotation.EnableCaching;
-@EnableCaching
@SpringBootApplication
public class UltimateRedisApplication {
diff --git a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfig.java b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfig.java
index 796f0621c..d67b8efcb 100644
--- a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfig.java
+++ b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfig.java
@@ -1,89 +1,52 @@
package com.example.ultimateredis.config;
+import io.lettuce.core.RedisURI;
import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Map.Entry;
import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.autoconfigure.cache.RedisCacheManagerBuilderCustomizer;
+import org.springframework.boot.autoconfigure.data.redis.LettuceClientConfigurationBuilderCustomizer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.Cache;
-import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
+import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
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.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializationContext;
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties(CacheConfigurationProperties.class)
+@EnableCaching
@Slf4j
public class CacheConfig implements CachingConfigurer {
@Bean
- @Primary
- RedisCacheConfiguration defaultCacheConfig() {
+ RedisCacheManagerBuilderCustomizer redisCacheManagerBuilderCustomizer(
+ CacheConfigurationProperties cacheConfigurationProperties) {
RedisCacheGZIPSerializer serializerGzip = new RedisCacheGZIPSerializer();
-
- return RedisCacheConfiguration.defaultCacheConfig()
- .serializeValuesWith(
- RedisSerializationContext.SerializationPair.fromSerializer(serializerGzip));
- }
-
- @Bean
- LettuceConnectionFactory redisConnectionFactory(CacheConfigurationProperties properties) {
- log.info(
- "Redis (/Lettuce) configuration enabled. With cache timeout {} seconds.",
- properties.getTimeoutSeconds());
-
- RedisStandaloneConfiguration redisStandaloneConfiguration =
- new RedisStandaloneConfiguration();
- redisStandaloneConfiguration.setHostName(properties.getRedisHost());
- redisStandaloneConfiguration.setPort(properties.getRedisPort());
- return new LettuceConnectionFactory(redisStandaloneConfiguration);
- }
-
- @Bean
- RedisTemplate redisTemplate(RedisConnectionFactory cf) {
- RedisTemplate redisTemplate = new RedisTemplate<>();
- redisTemplate.setConnectionFactory(cf);
- return redisTemplate;
+ return builder -> {
+ builder.cacheDefaults()
+ .disableCachingNullValues()
+ .serializeValuesWith(
+ RedisSerializationContext.SerializationPair.fromSerializer(
+ serializerGzip));
+ cacheConfigurationProperties
+ .getCacheExpirations()
+ .forEach(
+ (cacheName, timeout) ->
+ builder.withCacheConfiguration(
+ cacheName,
+ RedisCacheConfiguration.defaultCacheConfig()
+ .entryTtl(Duration.ofSeconds(timeout))));
+ };
}
@Bean
- RedisCacheConfiguration defaultCacheConfiguration(CacheConfigurationProperties properties) {
- return createCacheConfiguration(properties.getTimeoutSeconds());
- }
-
- private RedisCacheConfiguration createCacheConfiguration(long timeoutSeconds) {
- return RedisCacheConfiguration.defaultCacheConfig()
- .entryTtl(Duration.ofSeconds(timeoutSeconds));
- }
-
- @Bean
- CacheManager cacheManager(
- RedisConnectionFactory redisConnectionFactory,
- CacheConfigurationProperties properties,
- RedisCacheConfiguration defaultCacheConfiguration) {
- Map cacheConfigurations = new HashMap<>();
-
- for (Entry cacheNameAndTimeout :
- properties.getCacheExpirations().entrySet()) {
- cacheConfigurations.put(
- cacheNameAndTimeout.getKey(),
- createCacheConfiguration(cacheNameAndTimeout.getValue()));
- }
-
- return RedisCacheManager.builder(redisConnectionFactory)
- .cacheDefaults(defaultCacheConfiguration)
- .withInitialCacheConfigurations(cacheConfigurations)
- .build();
+ LettuceClientConfigurationBuilderCustomizer lettuceClientConfigurationBuilderCustomizer(
+ CacheConfigurationProperties properties) {
+ return clientConfigurationBuilder ->
+ clientConfigurationBuilder.apply(RedisURI.create(properties.getRedisURI()));
}
@Override
diff --git a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfigurationProperties.java b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfigurationProperties.java
index 3a6fedd2f..7d1931cea 100644
--- a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfigurationProperties.java
+++ b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/config/CacheConfigurationProperties.java
@@ -10,8 +10,7 @@
public class CacheConfigurationProperties {
private long timeoutSeconds = 60;
- private int redisPort = 6379;
- private String redisHost = "localhost";
+ private String redisURI;
// Mapping of cacheNames to expire-after-write timeout in seconds
private Map cacheExpirations = new HashMap<>();
}
diff --git a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/repository/ActorRepository.java b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/repository/ActorRepository.java
index 58de28a4a..e2414cc9d 100644
--- a/boot-ultimate-redis/src/main/java/com/example/ultimateredis/repository/ActorRepository.java
+++ b/boot-ultimate-redis/src/main/java/com/example/ultimateredis/repository/ActorRepository.java
@@ -7,6 +7,7 @@
@Repository
public interface ActorRepository extends CrudRepository {
+
Optional findByName(String name);
Optional findByNameAndAge(String name, Integer age);
diff --git a/boot-ultimate-redis/src/main/resources/application.properties b/boot-ultimate-redis/src/main/resources/application.properties
index 551a221fb..42ab39786 100644
--- a/boot-ultimate-redis/src/main/resources/application.properties
+++ b/boot-ultimate-redis/src/main/resources/application.properties
@@ -1,3 +1,6 @@
cache.timeout=60
cache.cacheExpirations.myControlledCache=180
+cache.redis-uri=redis://localhost:6379
+
+spring.mvc.problemdetails.enabled=true
spring.threads.virtual.enabled=true
\ No newline at end of file
diff --git a/boot-ultimate-redis/src/test/java/com/example/ultimateredis/TestUltimateRedisApplication.java b/boot-ultimate-redis/src/test/java/com/example/ultimateredis/TestUltimateRedisApplication.java
index 3e354561c..5541ff0ca 100644
--- a/boot-ultimate-redis/src/test/java/com/example/ultimateredis/TestUltimateRedisApplication.java
+++ b/boot-ultimate-redis/src/test/java/com/example/ultimateredis/TestUltimateRedisApplication.java
@@ -19,8 +19,7 @@ RedisContainer redisContainer(DynamicPropertyRegistry dynamicPropertyRegistry) {
new RedisContainer(DockerImageName.parse("redis").withTag("7.2.5-alpine"))
.withStartupAttempts(5)
.withStartupTimeout(Duration.ofMinutes(10));
- dynamicPropertyRegistry.add("cache.redis-port", redisContainer::getRedisPort);
- dynamicPropertyRegistry.add("cache.redis-host", redisContainer::getRedisHost);
+ dynamicPropertyRegistry.add("cache.redis-uri", redisContainer::getRedisURI);
return redisContainer;
}
diff --git a/httpClients/boot-restclient/src/main/java/com/example/restclient/bootrestclient/config/RestClientConfiguration.java b/httpClients/boot-restclient/src/main/java/com/example/restclient/bootrestclient/config/RestClientConfiguration.java
index 1b3869c67..1b20b257b 100644
--- a/httpClients/boot-restclient/src/main/java/com/example/restclient/bootrestclient/config/RestClientConfiguration.java
+++ b/httpClients/boot-restclient/src/main/java/com/example/restclient/bootrestclient/config/RestClientConfiguration.java
@@ -45,15 +45,15 @@ RestClientCustomizer restClientCustomizer(
httpHeaders -> {
httpHeaders.setContentType(MediaType.APPLICATION_JSON);
httpHeaders.setAccept(List.of(MediaType.APPLICATION_JSON));
- })
- .requestFactory(bufferingClientHttpRequestFactory)
- .requestInterceptor(
- (request, body, execution) -> {
- logRequest(request, body);
- ClientHttpResponse response = execution.execute(request, body);
- logResponse(response);
- return response;
});
+ // .requestFactory(bufferingClientHttpRequestFactory)
+ // .requestInterceptor(
+ // (request, body, execution) -> {
+ // logRequest(request, body);
+ // ClientHttpResponse response = execution.execute(request, body);
+ // logResponse(response);
+ // return response;
+ // });
}
private void logResponse(ClientHttpResponse response) throws IOException {
diff --git a/httpClients/boot-restclient/src/test/java/com/example/restclient/bootrestclient/services/PostServiceTest.java b/httpClients/boot-restclient/src/test/java/com/example/restclient/bootrestclient/services/PostServiceTest.java
new file mode 100644
index 000000000..f6dbecd17
--- /dev/null
+++ b/httpClients/boot-restclient/src/test/java/com/example/restclient/bootrestclient/services/PostServiceTest.java
@@ -0,0 +1,52 @@
+package com.example.restclient.bootrestclient.services;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.springframework.test.web.client.match.MockRestRequestMatchers.*;
+import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
+
+import com.example.restclient.bootrestclient.config.RestClientConfiguration;
+import com.example.restclient.bootrestclient.model.response.PostDto;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import java.util.Optional;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.autoconfigure.web.client.RestClientTest;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.client.MockRestServiceServer;
+
+@RestClientTest(
+ components = {PostService.class, HttpClientService.class, RestClientConfiguration.class})
+class PostServiceTest {
+
+ @Autowired private MockRestServiceServer mockRestServiceServer;
+
+ @Autowired private ObjectMapper objectMapper;
+
+ @Autowired private PostService postService;
+
+ @Test
+ void findPostById() throws JsonProcessingException {
+
+ PostDto postDto = new PostDto(1000L, 583L, "JunitTitle", "Response from RestClientTest");
+ this.mockRestServiceServer
+ .expect(requestTo("https://jsonplaceholder.typicode.com/posts/1"))
+ .andExpect(method(HttpMethod.GET))
+ .andExpect(header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE))
+ .andExpect(header("apiKey", "123456"))
+ .andRespond(
+ withSuccess(
+ objectMapper.writeValueAsString(postDto),
+ MediaType.APPLICATION_JSON));
+
+ Optional optionalPostDto = postService.findPostById(1L);
+
+ assertThat(optionalPostDto).isPresent();
+ assertThat(optionalPostDto.get().title()).isEqualTo("JunitTitle");
+
+ mockRestServiceServer.verify();
+ }
+}