From 8f4792e6f53408e4517b9f3c0960c98adbce8c57 Mon Sep 17 00:00:00 2001 From: Jens Wilke Date: Mon, 24 Jan 2022 06:12:48 +0100 Subject: [PATCH] Add cache2k support --- .../build.gradle | 4 + ...acheMeterBinderProvidersConfiguration.java | 17 ++- .../CacheMetricsAutoConfigurationTests.java | 12 +- .../spring-boot-actuator/build.gradle | 2 + .../Cache2kCacheMeterBinderProvider.java | 37 ++++++ .../Cache2kCacheMeterBinderProviderTests.java | 44 +++++++ .../spring-boot-autoconfigure/build.gradle | 2 + .../cache/Cache2kCacheConfiguration.java | 78 ++++++++++++ .../cache/CacheConfigurations.java | 1 + .../autoconfigure/cache/CacheProperties.java | 2 +- .../boot/autoconfigure/cache/CacheType.java | 5 + .../AbstractCacheAutoConfigurationTests.java | 8 ++ .../cache/CacheAutoConfigurationTests.java | 116 ++++++++++++++++++ .../spring-boot-dependencies/build.gradle | 15 +++ 14 files changed, 340 insertions(+), 3 deletions(-) create mode 100644 spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProvider.java create mode 100644 spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProviderTests.java create mode 100644 spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/Cache2kCacheConfiguration.java diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle index 001d00f8a810..b83784640ac2 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/build.gradle @@ -92,6 +92,8 @@ dependencies { optional("org.apache.tomcat.embed:tomcat-embed-el") optional("org.apache.tomcat:tomcat-jdbc") optional("org.aspectj:aspectjweaver") + optional("org.cache2k:cache2k-micrometer") + optional("org.cache2k:cache2k-spring") optional("org.eclipse.jetty:jetty-server") { exclude group: "javax.servlet", module: "javax.servlet-api" } @@ -155,6 +157,7 @@ dependencies { testImplementation("org.aspectj:aspectjrt") testImplementation("org.assertj:assertj-core") testImplementation("org.awaitility:awaitility") + testImplementation("org.cache2k:cache2k-api") testImplementation("org.eclipse.jetty:jetty-webapp") { exclude group: "javax.servlet", module: "javax.servlet-api" } @@ -176,6 +179,7 @@ dependencies { testRuntimeOnly("jakarta.management.j2ee:jakarta.management.j2ee-api") testRuntimeOnly("jakarta.transaction:jakarta.transaction-api") + testRuntimeOnly("org.cache2k:cache2k-core") testRuntimeOnly("org.springframework.security:spring-security-oauth2-jose") testRuntimeOnly("org.springframework.security:spring-security-oauth2-resource-server") testRuntimeOnly("org.springframework.security:spring-security-saml2-service-provider") diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration.java index 8236f9160594..fd72d69d0a4f 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMeterBinderProvidersConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,11 @@ import com.hazelcast.core.Hazelcast; import com.hazelcast.spring.cache.HazelcastCache; import io.micrometer.core.instrument.binder.MeterBinder; +import org.cache2k.Cache2kBuilder; +import org.cache2k.extra.micrometer.Cache2kCacheMetrics; +import org.cache2k.extra.spring.SpringCache2kCache; +import org.springframework.boot.actuate.metrics.cache.Cache2kCacheMeterBinderProvider; import org.springframework.boot.actuate.metrics.cache.CacheMeterBinderProvider; import org.springframework.boot.actuate.metrics.cache.CaffeineCacheMeterBinderProvider; import org.springframework.boot.actuate.metrics.cache.HazelcastCacheMeterBinderProvider; @@ -41,6 +45,17 @@ @ConditionalOnClass(MeterBinder.class) class CacheMeterBinderProvidersConfiguration { + @Configuration(proxyBeanMethods = false) + @ConditionalOnClass({ Cache2kBuilder.class, SpringCache2kCache.class, Cache2kCacheMetrics.class }) + static class Cache2kCacheMeterBinderProviderConfiguration { + + @Bean + Cache2kCacheMeterBinderProvider cache2kCacheMeterBinderProvider() { + return new Cache2kCacheMeterBinderProvider(); + } + + } + @Configuration(proxyBeanMethods = false) @ConditionalOnClass({ CaffeineCache.class, com.github.benmanes.caffeine.cache.Cache.class }) static class CaffeineCacheMeterBinderProviderConfiguration { diff --git a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMetricsAutoConfigurationTests.java b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMetricsAutoConfigurationTests.java index 8850c2979990..556b53128950 100644 --- a/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMetricsAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-actuator-autoconfigure/src/test/java/org/springframework/boot/actuate/autoconfigure/metrics/cache/CacheMetricsAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,6 +39,16 @@ class CacheMetricsAutoConfigurationTests { .withUserConfiguration(CachingConfiguration.class).withConfiguration( AutoConfigurations.of(CacheAutoConfiguration.class, CacheMetricsAutoConfiguration.class)); + @Test + void autoConfiguredCache2kIsInstrumented() { + this.contextRunner.withPropertyValues("spring.cache.type=cache2k", "spring.cache.cache-names=cache1,cache2") + .run((context) -> { + MeterRegistry registry = context.getBean(MeterRegistry.class); + registry.get("cache.gets").tags("name", "cache1").tags("cacheManager", "cacheManager").meter(); + registry.get("cache.gets").tags("name", "cache2").tags("cacheManager", "cacheManager").meter(); + }); + } + @Test void autoConfiguredCacheManagerIsInstrumented() { this.contextRunner.withPropertyValues("spring.cache.type=caffeine", "spring.cache.cache-names=cache1,cache2") diff --git a/spring-boot-project/spring-boot-actuator/build.gradle b/spring-boot-project/spring-boot-actuator/build.gradle index 57e9b49672c4..3c0961dfa201 100644 --- a/spring-boot-project/spring-boot-actuator/build.gradle +++ b/spring-boot-project/spring-boot-actuator/build.gradle @@ -40,6 +40,8 @@ dependencies { } optional("org.apache.tomcat.embed:tomcat-embed-core") optional("org.aspectj:aspectjweaver") + optional("org.cache2k:cache2k-micrometer") + optional("org.cache2k:cache2k-spring") optional("org.eclipse.jetty:jetty-server") { exclude(group: "javax.servlet", module: "javax.servlet-api") } diff --git a/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProvider.java b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProvider.java new file mode 100644 index 000000000000..d2954b4b46bf --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProvider.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.metrics.cache; + +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.binder.MeterBinder; +import org.cache2k.extra.micrometer.Cache2kCacheMetrics; +import org.cache2k.extra.spring.SpringCache2kCache; + +/** + * {@link CacheMeterBinderProvider} implementation for cache2k. + * + * @author Jens Wilke + * @since 2.7.0 + */ +public class Cache2kCacheMeterBinderProvider implements CacheMeterBinderProvider { + + @Override + public MeterBinder getMeterBinder(SpringCache2kCache cache, Iterable tags) { + return new Cache2kCacheMetrics(cache.getNativeCache(), tags); + } + +} diff --git a/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProviderTests.java b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProviderTests.java new file mode 100644 index 000000000000..ca1635a63f4b --- /dev/null +++ b/spring-boot-project/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/cache/Cache2kCacheMeterBinderProviderTests.java @@ -0,0 +1,44 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.actuate.metrics.cache; + +import java.util.Collections; + +import io.micrometer.core.instrument.binder.MeterBinder; +import org.cache2k.extra.micrometer.Cache2kCacheMetrics; +import org.cache2k.extra.spring.SpringCache2kCacheManager; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link Cache2kCacheMeterBinderProvider}. + * + * @author Stephane Nicoll + */ +class Cache2kCacheMeterBinderProviderTests { + + @Test + void cache2kCacheProvider() { + SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager() + .addCaches((builder) -> builder.name("test")); + MeterBinder meterBinder = new Cache2kCacheMeterBinderProvider().getMeterBinder(cacheManager.getCache("test"), + Collections.emptyList()); + assertThat(meterBinder).isInstanceOf(Cache2kCacheMetrics.class); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index dc32fef9c373..765f303659d2 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -77,6 +77,8 @@ dependencies { optional("com.zaxxer:HikariCP") optional("nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect") optional("org.aspectj:aspectjweaver") + optional("org.cache2k:cache2k-spring") + optional("org.cache2k:cache2k-micrometer") optional("org.eclipse.jetty:jetty-webapp") { exclude group: "javax.servlet", module: "javax.servlet-api" exclude(group: "org.eclipse.jetty", module: "jetty-jndi") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/Cache2kCacheConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/Cache2kCacheConfiguration.java new file mode 100644 index 000000000000..9a14d589aa14 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/Cache2kCacheConfiguration.java @@ -0,0 +1,78 @@ +/* + * Copyright 2012-2022 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.cache; + +import java.util.Collection; + +import org.cache2k.Cache2kBuilder; +import org.cache2k.extra.spring.SpringCache2kCacheManager; +import org.cache2k.extra.spring.SpringCache2kDefaultCustomizer; +import org.cache2k.extra.spring.SpringCache2kDefaultSupplier; + +import org.springframework.beans.factory.ObjectProvider; +import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.util.CollectionUtils; + +/** + * Cache2k cache configuration. + * + * @author Jens Wilke + */ +@Configuration(proxyBeanMethods = false) +@ConditionalOnClass({ Cache2kBuilder.class, SpringCache2kCacheManager.class }) +@ConditionalOnMissingBean(CacheManager.class) +@Conditional(CacheCondition.class) +class Cache2kCacheConfiguration { + + @Bean + SpringCache2kCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers customizers, + ObjectProvider springCache2kDefaultSupplier, + ObjectProvider springCache2kDefaultCustomizer) { + SpringCache2kCacheManager cacheManager = new SpringCache2kCacheManager( + createEffectiveDefaultSupplier(springCache2kDefaultSupplier, springCache2kDefaultCustomizer)); + Collection cacheNames = cacheProperties.getCacheNames(); + if (!CollectionUtils.isEmpty(cacheNames)) { + cacheManager.setDefaultCacheNames(cacheNames); + } + return customizers.customize(cacheManager); + } + + /** + * Use defaults and/or customizer if available + */ + SpringCache2kDefaultSupplier createEffectiveDefaultSupplier( + ObjectProvider springCache2kDefaultSupplier, + ObjectProvider springCache2kDefaultCustomizer) { + SpringCache2kDefaultSupplier defaultSupplier = springCache2kDefaultSupplier.getIfAvailable( + () -> SpringCache2kDefaultSupplier::supplyDefaultBuilder); + SpringCache2kDefaultCustomizer defaultCustomizer = springCache2kDefaultCustomizer.getIfAvailable(); + if (defaultCustomizer != null) { + return () -> { + Cache2kBuilder builder = defaultSupplier.get(); + defaultCustomizer.customize(builder); + return builder; + }; + } + return defaultSupplier; + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigurations.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigurations.java index 608843e3ea1c..193d6e76eab8 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigurations.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheConfigurations.java @@ -41,6 +41,7 @@ final class CacheConfigurations { mappings.put(CacheType.COUCHBASE, CouchbaseCacheConfiguration.class.getName()); mappings.put(CacheType.REDIS, RedisCacheConfiguration.class.getName()); mappings.put(CacheType.CAFFEINE, CaffeineCacheConfiguration.class.getName()); + mappings.put(CacheType.CACHE2K, Cache2kCacheConfiguration.class.getName()); mappings.put(CacheType.SIMPLE, SimpleCacheConfiguration.class.getName()); mappings.put(CacheType.NONE, NoOpCacheConfiguration.class.getName()); MAPPINGS = Collections.unmodifiableMap(mappings); diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java index fa3119ea99da..475e8ae285ae 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java index 8c97cd98eec7..a7185e9cae22 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/cache/CacheType.java @@ -51,6 +51,11 @@ public enum CacheType { */ REDIS, + /** + * Cache2k backed caching. + */ + CACHE2K, + /** * Caffeine backed caching. */ diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/AbstractCacheAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/AbstractCacheAutoConfigurationTests.java index a311a4626661..3045039f1c5d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/AbstractCacheAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/AbstractCacheAutoConfigurationTests.java @@ -22,6 +22,7 @@ import java.util.Map; import com.hazelcast.spring.cache.HazelcastCacheManager; +import org.cache2k.extra.spring.SpringCache2kCacheManager; import org.springframework.boot.autoconfigure.AutoConfigurations; import org.springframework.boot.test.context.assertj.AssertableApplicationContext; @@ -119,6 +120,13 @@ CacheManagerCustomizer hazelcastCacheManagerCustomizer() }; } + @Bean + CacheManagerCustomizer cache2kCacheManagerCustomizer() { + return new CacheManagerTestCustomizer() { + + }; + } + @Bean CacheManagerCustomizer caffeineCacheManagerCustomizer() { return new CacheManagerTestCustomizer<>() { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java index b2947f2a71ae..024b5809240b 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/cache/CacheAutoConfigurationTests.java @@ -32,6 +32,10 @@ import com.hazelcast.core.Hazelcast; import com.hazelcast.core.HazelcastInstance; import com.hazelcast.spring.cache.HazelcastCacheManager; +import org.cache2k.Cache2kBuilder; +import org.cache2k.extra.spring.SpringCache2kCacheManager; +import org.cache2k.extra.spring.SpringCache2kDefaultCustomizer; +import org.cache2k.extra.spring.SpringCache2kDefaultSupplier; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.BeanCreationException; @@ -69,6 +73,7 @@ import org.springframework.test.util.ReflectionTestUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatCode; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -550,6 +555,85 @@ void jCacheCacheWithCachesAndCustomizer() { } } + @Test + void cache2kCacheWithExplicitCaches() { + this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class) + .withPropertyValues("spring.cache.type=cache2k", "spring.cache.cacheNames=foo").run((context) -> { + SpringCache2kCacheManager manager = getCacheManager(context, SpringCache2kCacheManager.class); + assertThat(manager.getCacheNames()).containsOnly("foo"); + Cache foo = manager.getCache("foo"); + foo.get("1"); + assertThat(manager.getNativeCacheManager().getName()).isEqualTo("springDefault"); + }); + } + + @Test + void cache2kDifferentCacheManagerName() { + this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class) + .withBean(SpringCache2kDefaultSupplier.class, () -> () -> { + Cache2kBuilder cache2kBuilder = Cache2kBuilder.forUnknownTypes() + .manager(org.cache2k.CacheManager.getInstance("separate")); + SpringCache2kDefaultSupplier.applySpringDefaults(cache2kBuilder); + return cache2kBuilder; + }).withPropertyValues("spring.cache.type=cache2k", "spring.cache.cacheNames=foo").run((context) -> { + SpringCache2kCacheManager manager = getCacheManager(context, SpringCache2kCacheManager.class); + assertThat(manager.getNativeCacheManager().getName()).isEqualTo("separate"); + }); + } + + @Test + void cache2kCacheWithCustomizers() { + this.contextRunner.withUserConfiguration(DefaultCacheAndCustomizersConfiguration.class) + .withPropertyValues("spring.cache.type=cache2k") + .run(verifyCustomizers("allCacheManagerCustomizer", "cache2kCacheManagerCustomizer")); + } + + @Test + void cache2kCacheWithExplicitCachesAndCustomizer() { + this.contextRunner.withUserConfiguration(Cache2kAddCacheWithCustomizerConfiguration.class) + .withPropertyValues("spring.cache.type=cache2k", "spring.cache.cacheNames=foo,bar").run((context) -> { + SpringCache2kCacheManager manager = getCacheManager(context, SpringCache2kCacheManager.class); + assertThat(manager.getCacheNames()).containsExactlyInAnyOrder("foo", "bar", "viaCustomizer"); + // check that default from customizer is applied + assertThat(manager.getCache("bar").get("any").get()).isEqualTo("defaultViaSupplier"); + assertThat(manager.getCache("viaCustomizer").get("any").get()).isEqualTo("defaultViaSupplier"); + }); + } + + @Test + void cache2kCacheWithDefaultsSupplierAndCustomizer() { + this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class) + .withBean(SpringCache2kDefaultSupplier.class, () -> () -> { + Cache2kBuilder cache2kBuilder = Cache2kBuilder.forUnknownTypes() + .manager(org.cache2k.CacheManager.getInstance("viaSupplier")); + SpringCache2kDefaultSupplier.applySpringDefaults(cache2kBuilder); + return cache2kBuilder; + }) + .withBean(SpringCache2kDefaultCustomizer.class, () -> (b) -> b + .valueType(String.class) + .loader(key -> "viaCustomizer")) + .withPropertyValues("spring.cache.type=cache2k", "spring.cache.cacheNames=foo").run((context) -> { + SpringCache2kCacheManager manager = getCacheManager(context, SpringCache2kCacheManager.class); + assertThat(manager.getNativeCacheManager().getName()).isEqualTo("viaSupplier"); + assertThat(manager.getCache("foo").get("any").get()).isEqualTo("viaCustomizer"); + }); + } + + /** + * Default cannot be changed in CacheManagerCustomizer, if cache names are present in the properties + */ + @Test + void cache2kCacheNamesAndCacheManagerDefaultsYieldsException() { + this.contextRunner.withUserConfiguration(Cache2kAddCacheAndDefaultsWithCustomizerConfiguration.class) + .withBean(SpringCache2kDefaultSupplier.class, () -> () -> + Cache2kBuilder.forUnknownTypes() + .manager(org.cache2k.CacheManager.getInstance("cache2kCacheNamesAndCacheManagerDefaults"))) + .withPropertyValues("spring.cache.type=cache2k", "spring.cache.cacheNames=foo,bar").run((context) -> { + assertThatCode(() -> getCacheManager(context, SpringCache2kCacheManager.class)) + .getRootCause().isInstanceOf(IllegalStateException.class); + }); + } + @Test void caffeineCacheWithExplicitCaches() { this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class) @@ -825,6 +909,38 @@ CacheResolver myCacheResolver() { } + @Configuration(proxyBeanMethods = false) + @EnableCaching + static class Cache2kAddCacheWithCustomizerConfiguration { + + @Bean + CacheManagerCustomizer cache2kCustomizer() { + return (cacheManager) -> cacheManager.addCaches((b) -> b.name("viaCustomizer")); + } + + @Bean + SpringCache2kDefaultSupplier cache2kDefaultConfiguration() { + return () -> SpringCache2kDefaultSupplier.supplyDefaultBuilder().valueType(String.class) + .loader((key) -> "defaultViaSupplier"); + } + + } + + @Configuration(proxyBeanMethods = false) + @EnableCaching + static class Cache2kAddCacheAndDefaultsWithCustomizerConfiguration { + + @Bean + CacheManagerCustomizer cache2kCustomizer() { + return (cacheManager) -> cacheManager + .defaultSetup((b) -> b + .valueType(String.class) + .loader(key -> "defaultViaManagerCustomizer")) + .addCaches((b) -> b.name("viaCustomizer")); + } + + } + @Configuration(proxyBeanMethods = false) @EnableCaching static class CaffeineCacheBuilderConfiguration { diff --git a/spring-boot-project/spring-boot-dependencies/build.gradle b/spring-boot-project/spring-boot-dependencies/build.gradle index 6f0beb399311..4453f67207df 100644 --- a/spring-boot-project/spring-boot-dependencies/build.gradle +++ b/spring-boot-project/spring-boot-dependencies/build.gradle @@ -87,7 +87,22 @@ bom { ] } } + library("cache2k", "2.5.3.Beta") { + group("org.cache2k") { + modules = [ + "cache2k-api", + "cache2k-config", + "cache2k-core", + "cache2k-jcache", + "cache2k-micrometer", + "cache2k-spring" + ] + } + } library("Caffeine", "3.0.5") { + prohibit("[3.0.0,)") { + because "it requires Java 11" + } group("com.github.ben-manes.caffeine") { modules = [ "caffeine",