Use spring.cache.config with JCache

According to the spec, specifying a custom URI when retrieving a
`javax.cache.CacheManager` might be used as a way to transmit the
location of a custom configuration file to initialize the underlying
cache manager.

If `spring.cache.config` is set, we use that information to retrieve a
CacheManager with that configuration file. Unfortunately, hazelcast does
not support this feature so we are setting the property key it expects
instead.

See https://github.com/hazelcast/hazelcast/issues/4943

Closes gh-2743
pull/2744/head
Stephane Nicoll 10 years ago
parent b586bce3b7
commit fbe9774890

@ -16,8 +16,10 @@
package org.springframework.boot.autoconfigure.cache; package org.springframework.boot.autoconfigure.cache;
import java.io.IOException;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Properties;
import javax.cache.CacheManager; import javax.cache.CacheManager;
import javax.cache.Caching; import javax.cache.Caching;
import javax.cache.configuration.MutableConfiguration; import javax.cache.configuration.MutableConfiguration;
@ -37,6 +39,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAwareOrderComparator; import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
@ -64,9 +67,8 @@ class JCacheCacheConfiguration {
private List<JCacheManagerCustomizer> cacheManagerCustomizers; private List<JCacheManagerCustomizer> cacheManagerCustomizers;
@Bean @Bean
public JCacheCacheManager cacheManager() { public JCacheCacheManager cacheManager() throws IOException {
CacheManager cacheManager = createCacheManager(this.cacheProperties.getJcache() CacheManager cacheManager = createCacheManager();
.getProvider());
List<String> cacheNames = this.cacheProperties.getCacheNames(); List<String> cacheNames = this.cacheProperties.getCacheNames();
if (!CollectionUtils.isEmpty(cacheNames)) { if (!CollectionUtils.isEmpty(cacheNames)) {
for (String cacheName : cacheNames) { for (String cacheName : cacheNames) {
@ -77,11 +79,29 @@ class JCacheCacheConfiguration {
return new JCacheCacheManager(cacheManager); return new JCacheCacheManager(cacheManager);
} }
private CacheManager createCacheManager(String cachingProvider) { private CacheManager createCacheManager() throws IOException {
if (StringUtils.hasText(cachingProvider)) { CachingProvider cachingProvider = getCachingProvider(this.cacheProperties
return Caching.getCachingProvider(cachingProvider).getCacheManager(); .getJcache().getProvider());
Resource configLocation = this.cacheProperties.resolveConfigLocation();
if (configLocation != null) {
return cachingProvider.getCacheManager(configLocation.getURI(),
cachingProvider.getDefaultClassLoader(), createCacheManagerProperties(configLocation));
} }
return Caching.getCachingProvider().getCacheManager(); return cachingProvider.getCacheManager();
}
private CachingProvider getCachingProvider(String cachingProviderFqn) {
if (StringUtils.hasText(cachingProviderFqn)) {
return Caching.getCachingProvider(cachingProviderFqn);
}
return Caching.getCachingProvider();
}
private Properties createCacheManagerProperties(Resource configLocation) throws IOException {
Properties properties = new Properties();
// Hazelcast does not use the URI as a mean to specify a custom config.
properties.setProperty("hazelcast.config.location", configLocation.getURI().toString());
return properties;
} }
private javax.cache.configuration.Configuration<?, ?> getDefaultCacheConfiguration() { private javax.cache.configuration.Configuration<?, ?> getDefaultCacheConfiguration() {

@ -16,6 +16,7 @@
package org.springframework.boot.autoconfigure.cache; package org.springframework.boot.autoconfigure.cache;
import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -50,6 +51,8 @@ import org.springframework.context.annotation.AnnotationConfigApplicationContext
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@ -250,6 +253,30 @@ public class CacheAutoConfigurationTests {
"spring.cache.jcache.provider=" + wrongCachingProviderFqn); "spring.cache.jcache.provider=" + wrongCachingProviderFqn);
} }
@Test
public void jCacheCacheWithConfig() throws IOException {
String cachingProviderFqn = MockCachingProvider.class.getName();
String configLocation = "org/springframework/boot/autoconfigure/cache/hazelcast-specific.xml";
load(JCacheCustomConfiguration.class, "spring.cache.type=jcache",
"spring.cache.jcache.provider=" + cachingProviderFqn,
"spring.cache.config=" + configLocation);
JCacheCacheManager cacheManager = validateCacheManager(JCacheCacheManager.class);
Resource configResource = new ClassPathResource(configLocation);
assertThat(cacheManager.getCacheManager().getURI(), is(configResource.getURI()));
}
@Test
public void jCacheCacheWithWrongConfig() {
String cachingProviderFqn = MockCachingProvider.class.getName();
String configLocation = "org/springframework/boot/autoconfigure/cache/does-not-exist.xml";
thrown.expect(BeanCreationException.class);
thrown.expectMessage("spring.cache.config");
thrown.expectMessage(configLocation);
load(JCacheCustomConfiguration.class, "spring.cache.type=jcache",
"spring.cache.jcache.provider=" + cachingProviderFqn,
"spring.cache.config=" + configLocation);
}
@Test @Test
public void ehCacheCacheWithCaches() { public void ehCacheCacheWithCaches() {
load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache"); load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache");
@ -268,7 +295,7 @@ public class CacheAutoConfigurationTests {
} }
@Test @Test
public void ehCacheCacheWithLocation() { public void ehCacheCacheWithConfig() {
load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache", load(DefaultCacheConfiguration.class, "spring.cache.type=ehcache",
"spring.cache.config=cache/ehcache-override.xml"); "spring.cache.config=cache/ehcache-override.xml");
EhCacheCacheManager cacheManager = null; EhCacheCacheManager cacheManager = null;
@ -296,7 +323,7 @@ public class CacheAutoConfigurationTests {
} }
@Test @Test
public void hazelcastCacheWithLocation() { public void hazelcastCacheWithConfig() {
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast", load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast",
"spring.cache.config=org/springframework/boot/autoconfigure/cache/hazelcast-specific.xml"); "spring.cache.config=org/springframework/boot/autoconfigure/cache/hazelcast-specific.xml");
HazelcastCacheManager cacheManager = validateCacheManager(HazelcastCacheManager.class); HazelcastCacheManager cacheManager = validateCacheManager(HazelcastCacheManager.class);
@ -306,12 +333,11 @@ public class CacheAutoConfigurationTests {
} }
@Test @Test
public void hazelcastWithWrongLocation() { public void hazelcastWithWrongConfig() {
this.thrown.expect(BeanCreationException.class); this.thrown.expect(BeanCreationException.class);
this.thrown.expectMessage("foo/bar/unknown.xml"); this.thrown.expectMessage("foo/bar/unknown.xml");
load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast", load(DefaultCacheConfiguration.class, "spring.cache.type=hazelcast",
"spring.cache.config=foo/bar/unknown.xml"); "spring.cache.config=foo/bar/unknown.xml");
System.out.println(this.context.getBean(CacheManager.class).getClass());
} }
@Test @Test
@ -333,6 +359,27 @@ public class CacheAutoConfigurationTests {
} }
} }
@Test
public void hazelcastAsJCacheWithConfig() throws IOException {
String cachingProviderFqn = HazelcastCachingProvider.class.getName();
String configLocation = "org/springframework/boot/autoconfigure/cache/hazelcast-specific.xml";
JCacheCacheManager cacheManager = null;
try {
load(DefaultCacheConfiguration.class, "spring.cache.type=jcache",
"spring.cache.jcache.provider=" + cachingProviderFqn,
"spring.cache.config="+configLocation);
cacheManager = validateCacheManager(JCacheCacheManager.class);
Resource configResource = new ClassPathResource(configLocation);
assertThat(cacheManager.getCacheManager().getURI(), is(configResource.getURI()));
}
finally {
if (cacheManager != null) {
cacheManager.getCacheManager().close();
}
}
}
@Test @Test
public void jCacheCacheWithCachesAndCustomizer() { public void jCacheCacheWithCachesAndCustomizer() {
String cachingProviderFqn = HazelcastCachingProvider.class.getName(); String cachingProviderFqn = HazelcastCachingProvider.class.getName();

@ -48,6 +48,8 @@ public class MockCachingProvider implements CachingProvider {
public CacheManager getCacheManager(URI uri, ClassLoader classLoader, public CacheManager getCacheManager(URI uri, ClassLoader classLoader,
Properties properties) { Properties properties) {
CacheManager cacheManager = mock(CacheManager.class); CacheManager cacheManager = mock(CacheManager.class);
given(cacheManager.getURI()).willReturn(uri);
given(cacheManager.getClassLoader()).willReturn(classLoader);
final Map<String, Cache> caches = new HashMap<String, Cache>(); final Map<String, Cache> caches = new HashMap<String, Cache>();
given(cacheManager.getCacheNames()).willReturn(caches.keySet()); given(cacheManager.getCacheNames()).willReturn(caches.keySet());
given(cacheManager.getCache(anyString())).willAnswer(new Answer<Cache>() { given(cacheManager.getCache(anyString())).willAnswer(new Answer<Cache>() {
@ -74,7 +76,7 @@ public class MockCachingProvider implements CachingProvider {
@Override @Override
public ClassLoader getDefaultClassLoader() { public ClassLoader getDefaultClassLoader() {
return null; return mock(ClassLoader.class);
} }
@Override @Override

Loading…
Cancel
Save