Enable customization of properties used to create JCache CacheManager

Closes gh-39350
This commit is contained in:
Andy Wilkinson 2024-06-24 15:07:31 +01:00
parent 5920b27b57
commit 0ad5aa7400
4 changed files with 42 additions and 17 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -38,21 +38,26 @@ import org.springframework.core.io.Resource;
class HazelcastJCacheCustomizationConfiguration { class HazelcastJCacheCustomizationConfiguration {
@Bean @Bean
HazelcastPropertiesCustomizer hazelcastPropertiesCustomizer(ObjectProvider<HazelcastInstance> hazelcastInstance) { HazelcastPropertiesCustomizer hazelcastPropertiesCustomizer(ObjectProvider<HazelcastInstance> hazelcastInstance,
return new HazelcastPropertiesCustomizer(hazelcastInstance.getIfUnique()); CacheProperties cacheProperties) {
return new HazelcastPropertiesCustomizer(hazelcastInstance.getIfUnique(), cacheProperties);
} }
static class HazelcastPropertiesCustomizer implements JCachePropertiesCustomizer { static class HazelcastPropertiesCustomizer implements JCachePropertiesCustomizer {
private final HazelcastInstance hazelcastInstance; private final HazelcastInstance hazelcastInstance;
HazelcastPropertiesCustomizer(HazelcastInstance hazelcastInstance) { private final CacheProperties cacheProperties;
HazelcastPropertiesCustomizer(HazelcastInstance hazelcastInstance, CacheProperties cacheProperties) {
this.hazelcastInstance = hazelcastInstance; this.hazelcastInstance = hazelcastInstance;
this.cacheProperties = cacheProperties;
} }
@Override @Override
public void customize(CacheProperties cacheProperties, Properties properties) { public void customize(Properties properties) {
Resource configLocation = cacheProperties.resolveConfigLocation(cacheProperties.getJcache().getConfig()); Resource configLocation = this.cacheProperties
.resolveConfigLocation(this.cacheProperties.getJcache().getConfig());
if (configLocation != null) { if (configLocation != null) {
// Hazelcast does not use the URI as a mean to specify a custom config. // Hazelcast does not use the URI as a mean to specify a custom config.
properties.setProperty("hazelcast.config.location", toUri(configLocation).toString()); properties.setProperty("hazelcast.config.location", toUri(configLocation).toString());

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -95,7 +95,7 @@ class JCacheCacheConfiguration implements BeanClassLoaderAware {
private CacheManager createCacheManager(CacheProperties cacheProperties, private CacheManager createCacheManager(CacheProperties cacheProperties,
ObjectProvider<JCachePropertiesCustomizer> cachePropertiesCustomizers) throws IOException { ObjectProvider<JCachePropertiesCustomizer> cachePropertiesCustomizers) throws IOException {
CachingProvider cachingProvider = getCachingProvider(cacheProperties.getJcache().getProvider()); CachingProvider cachingProvider = getCachingProvider(cacheProperties.getJcache().getProvider());
Properties properties = createCacheManagerProperties(cachePropertiesCustomizers, cacheProperties); Properties properties = createCacheManagerProperties(cachePropertiesCustomizers);
Resource configLocation = cacheProperties.resolveConfigLocation(cacheProperties.getJcache().getConfig()); Resource configLocation = cacheProperties.resolveConfigLocation(cacheProperties.getJcache().getConfig());
if (configLocation != null) { if (configLocation != null) {
return cachingProvider.getCacheManager(configLocation.getURI(), this.beanClassLoader, properties); return cachingProvider.getCacheManager(configLocation.getURI(), this.beanClassLoader, properties);
@ -111,10 +111,9 @@ class JCacheCacheConfiguration implements BeanClassLoaderAware {
} }
private Properties createCacheManagerProperties( private Properties createCacheManagerProperties(
ObjectProvider<JCachePropertiesCustomizer> cachePropertiesCustomizers, CacheProperties cacheProperties) { ObjectProvider<JCachePropertiesCustomizer> cachePropertiesCustomizers) {
Properties properties = new Properties(); Properties properties = new Properties();
cachePropertiesCustomizers.orderedStream() cachePropertiesCustomizers.orderedStream().forEach((customizer) -> customizer.customize(properties));
.forEach((customizer) -> customizer.customize(cacheProperties, properties));
return properties; return properties;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2019 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -26,15 +26,16 @@ import javax.cache.spi.CachingProvider;
* used by the {@link CachingProvider} to create the {@link CacheManager}. * used by the {@link CachingProvider} to create the {@link CacheManager}.
* *
* @author Stephane Nicoll * @author Stephane Nicoll
* @since 3.4.0
* @see CachingProvider#getCacheManager(java.net.URI, ClassLoader, Properties)
*/ */
interface JCachePropertiesCustomizer { public interface JCachePropertiesCustomizer {
/** /**
* Customize the properties. * Customize the properties.
* @param cacheProperties the cache properties
* @param properties the current properties * @param properties the current properties
* @see CachingProvider#getCacheManager(java.net.URI, ClassLoader, Properties) *
*/ */
void customize(CacheProperties cacheProperties, Properties properties); void customize(Properties properties);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2024 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package org.springframework.boot.autoconfigure.cache;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Properties;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.cache.Caching; import javax.cache.Caching;
@ -76,8 +77,10 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then; import static org.mockito.BDDMockito.then;
import static org.mockito.BDDMockito.willAnswer;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
@ -460,6 +463,23 @@ class CacheAutoConfigurationTests extends AbstractCacheAutoConfigurationTests {
}); });
} }
@Test
void jCacheCacheWithPropertiesCustomizer() {
JCachePropertiesCustomizer customizer = mock(JCachePropertiesCustomizer.class);
willAnswer((invocation) -> {
invocation.getArgument(0, Properties.class).setProperty("customized", "true");
return null;
}).given(customizer).customize(any(Properties.class));
String cachingProviderFqn = MockCachingProvider.class.getName();
this.contextRunner.withUserConfiguration(DefaultCacheConfiguration.class)
.withPropertyValues("spring.cache.type=jcache", "spring.cache.jcache.provider=" + cachingProviderFqn)
.withBean(JCachePropertiesCustomizer.class, () -> customizer)
.run((context) -> {
JCacheCacheManager cacheManager = getCacheManager(context, JCacheCacheManager.class);
assertThat(cacheManager.getCacheManager().getProperties()).containsEntry("customized", "true");
});
}
@Test @Test
void hazelcastCacheExplicit() { void hazelcastCacheExplicit() {
this.contextRunner.withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class)) this.contextRunner.withConfiguration(AutoConfigurations.of(HazelcastAutoConfiguration.class))