Hazelcast 缓存管理器:无法覆盖缓存的 CacheManager
Hazelcast Cache Manager: Cannot overwrite a Cache's CacheManager
在我正在工作的应用程序上,我正在尝试从 Hazelcast 3.6 升级到 3.12.4,我遇到了一些问题,当两个或多个测试一起 运行 时,这些问题很容易重现。这些测试都用 @WebAppConfiguration
注释并包括 Spring 的应用程序配置使用 ContextConfiguration(classes = {AppConfig.class})
作为配置的一部分,我有一个名为 CacheAwareStorage
的 @Bean
启动 CacheManager
。初始化非常基本:
public Cache<T, V> initCache(String name, Class<T> type, Class<T> valueType) {
Cache<T, V> cache = manager.getCache(cacheName, keyType, valueType);
if (cache != null)
{
return cache;
}
cache = manager.createCache(cacheName, config);
return cache;
}
当作为测试套件的一部分刷新上下文时会出现问题,我认为这是在 AbstractTestNGSpringContextTests
中完成的,因为我没有明确刷新上下文。发生以下错误,导致只有第一个 class 测试通过:
GenericWebApplicationContext: Refreshing org.springframework.web.context.support.GenericWebApplicationContext@6170989a
....
WARN GenericWebApplicationContext: Exception encountered during context initialization - cancelling refresh attempt
....
Factory method 'tokenStore' threw exception
nested exception is java.lang.IllegalStateException: Cannot overwrite a Cache's CacheManager.
查看更改的内容,我看到 AbstracthazelcastCacheManager
抛出一个来自 Hazelcast CacheProxy
的 IllegalStateException
。更准确地说,manager.getCache()
-> getCacheUnchecked()
-> 在 createCacheProxy()
中创建缓存代理 -> 并将代理的管理器设置为 cacheProxy.setCacheManager()
中的当前管理器。
从 Hazelcast v3.9 开始,一旦设置了管理器,就不再允许这样做。
对此有什么解决方案?可能是 Hazelcast 中存在错误(没有检查正在设置的管理器是否实际上与现有的管理器不同),但是我正在寻找我可以做的事情。为什么 'getCache()' 尝试重新创建代理是我不明白的另一件事。
我假设我必须做一些事情才能不刷新上下文,但是我不知道我该怎么做(如果有的话)。
问题出在缓存管理器 Bean 的创建方式上。我使用了内部 Hazelcast 缓存管理器,每次都会创建一个新实例。如下使用 JCache API,解决了问题
@Bean
public CacheManager cacheManager() {
HazelcastServerCachingProvider provider = Caching.getCachingProvider(); // or add class name of Hazelcast server caching provider to disambiguate
return provider.getCacheManager(null, null, HazelcastCachingProvider.propertiesByInstanceItself(HAZELCAST_INSTANCE));
}
Hazelcast 团队在这方面的帮助:https://github.com/hazelcast/hazelcast/issues/16212
在我正在工作的应用程序上,我正在尝试从 Hazelcast 3.6 升级到 3.12.4,我遇到了一些问题,当两个或多个测试一起 运行 时,这些问题很容易重现。这些测试都用 @WebAppConfiguration
注释并包括 Spring 的应用程序配置使用 ContextConfiguration(classes = {AppConfig.class})
作为配置的一部分,我有一个名为 CacheAwareStorage
的 @Bean
启动 CacheManager
。初始化非常基本:
public Cache<T, V> initCache(String name, Class<T> type, Class<T> valueType) {
Cache<T, V> cache = manager.getCache(cacheName, keyType, valueType);
if (cache != null)
{
return cache;
}
cache = manager.createCache(cacheName, config);
return cache;
}
当作为测试套件的一部分刷新上下文时会出现问题,我认为这是在 AbstractTestNGSpringContextTests
中完成的,因为我没有明确刷新上下文。发生以下错误,导致只有第一个 class 测试通过:
GenericWebApplicationContext: Refreshing org.springframework.web.context.support.GenericWebApplicationContext@6170989a
....
WARN GenericWebApplicationContext: Exception encountered during context initialization - cancelling refresh attempt
....
Factory method 'tokenStore' threw exception
nested exception is java.lang.IllegalStateException: Cannot overwrite a Cache's CacheManager.
查看更改的内容,我看到 AbstracthazelcastCacheManager
抛出一个来自 Hazelcast CacheProxy
的 IllegalStateException
。更准确地说,manager.getCache()
-> getCacheUnchecked()
-> 在 createCacheProxy()
中创建缓存代理 -> 并将代理的管理器设置为 cacheProxy.setCacheManager()
中的当前管理器。
从 Hazelcast v3.9 开始,一旦设置了管理器,就不再允许这样做。
对此有什么解决方案?可能是 Hazelcast 中存在错误(没有检查正在设置的管理器是否实际上与现有的管理器不同),但是我正在寻找我可以做的事情。为什么 'getCache()' 尝试重新创建代理是我不明白的另一件事。
我假设我必须做一些事情才能不刷新上下文,但是我不知道我该怎么做(如果有的话)。
问题出在缓存管理器 Bean 的创建方式上。我使用了内部 Hazelcast 缓存管理器,每次都会创建一个新实例。如下使用 JCache API,解决了问题
@Bean
public CacheManager cacheManager() {
HazelcastServerCachingProvider provider = Caching.getCachingProvider(); // or add class name of Hazelcast server caching provider to disambiguate
return provider.getCacheManager(null, null, HazelcastCachingProvider.propertiesByInstanceItself(HAZELCAST_INSTANCE));
}
Hazelcast 团队在这方面的帮助:https://github.com/hazelcast/hazelcast/issues/16212