Невозможно получить кеш из cachemanager, если не вызывается cachemanager.getCacheNames () - PullRequest
0 голосов
/ 14 сентября 2018

Мое приложение использует Spring 4.3.x, EhCache 3.6 и javax Cache 1.1.0. Вот как я настроил javax CacheManager в своем приложении:

    <bean id="jCacheManager" class="org.springframework.cache.jcache.JCacheCacheManager">
        <property name="cacheManager" ref="appCacheManagerFactoryBean" />
    </bean>

    <bean id="appCacheManagerFactoryBean" class="com.example.AppCacheManagerFactoryBean"/>

AppCacheManagerFactoryBean (это просто настроенная версия JCacheManagerFactoryBean) помогает мне настроить глобальный каталог персистентности для моего приложения. Вот как это выглядит:

public class AppCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean,
    DisposableBean {

@Value("${cache.persistenceDir}")
private String persistenceDir;

private CacheManager cacheManager;

@Override
public void afterPropertiesSet() {
    this.cacheManager = buildCacheManager();
}

private CacheManager buildCacheManager()
{
    EhcacheCachingProvider cachingProvider = (EhcacheCachingProvider) Caching.getCachingProvider();
    DefaultConfiguration defaultConfiguration = new DefaultConfiguration(cachingProvider.getDefaultClassLoader(),
            new DefaultPersistenceConfiguration(new File(persistenceDir)));
    return cachingProvider.getCacheManager(cachingProvider.getDefaultURI(), defaultConfiguration);
}


@Override
public CacheManager getObject() {
    return this.cacheManager;
}

@Override
public Class<?> getObjectType() {
    return (this.cacheManager != null ? this.cacheManager.getClass() : CacheManager.class);
}

@Override
public boolean isSingleton() {
    return true;
}


@Override
public void destroy() {
    this.cacheManager.close();
}
}

Вот как я определяю кеши. Я использую Ehcache API для создания своих кэшей, так как некоторые функции, в которых нуждаются мои кэши, недоступны через JCache API.

EhcacheManager ehcacheManager = jCacheCacheManager.getCacheManager().unwrap(EhcacheManager.class);
ehcacheManager.createCache("foo", CacheConfigurationBuilder.newCacheConfigurationBuilder(
                String.class, Foo.class,
                ResourcePoolsBuilder.newResourcePoolsBuilder()
                        .heap(1)
                        .offheap(1, MemoryUnit.GB)
                        .disk(5, MemoryUnit.GB)
        ));

Когда я пытаюсь получить кеш из CacheManager в другом месте моего приложения, выдается исключение нулевого указателя.

Caching.getCachingProvider().getCacheManager().getCache("foo");

Однако, если я получаю кеш после вызова метода getCacheNames () в CacheManager, кеш выбирается нормально.

 Caching.getCachingProvider().getCacheManager().getCacheNames();
 Caching.getCachingProvider().getCacheManager().getCache("foo");

Что я пропустил? Пожалуйста, помогите мне.

1 Ответ

0 голосов
/ 17 сентября 2018

Мой первый вопрос: «Почему бы не использовать встроенную поддержку Spring-cache?»Это не нужно будет делать это.JCacheCacheManager позаботится обо всем.

Тогда ваша проблема в том, что кеш создается непосредственно в Ehcache без прохождения через слой JSR107.Вызов getCacheNames() вызывает обновление списка кэша в JSR107, чтобы заставить его работать.Однако я не уверен, что это глобальное поведение предназначено.Но так оно и работает.

Решение состоит в том, чтобы создать кеш, как и ожидалось, через слой JSR107.Похоже, это

CacheManager cacheManager = jcacheCacheManager.getCacheManager();
cacheManager.createCache("foo",
    Eh107Configuration.fromEhcacheCacheConfiguration(
        CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, Foo.class, ResourcePoolsBuilder.newResourcePoolsBuilder()
                    .heap(1)
                    .offheap(1, MemoryUnit.GB)
                    .disk(5, MemoryUnit.GB))
            .build()));
...