Кэш закрыт, что вызывает исключение при запуске набора тестов - PullRequest
0 голосов
/ 10 ноября 2018

У меня возникла проблема, аналогичная описанной в этом вопросе .

У меня есть набор тестов, который отлично работает в среде разработки. Один из тестов не выполняется при выполнении в конвейерах Bitbucket со следующим исключением:

org.springframework.dao.InvalidDataAccessApiUsageException: Cache[model.Role] is closed; nested exception is java.lang.IllegalStateException: Cache[model.Role] is closed
    at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:364)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:225)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:527)
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:242)
   ....

Я хочу попробовать принятое решение , но я не знаю, как применить его к моему проекту. второе решение зависит от файла ehcache.xml. У меня нет этого файла, все настроено в JavaConfig. Как я могу принять предложенные решения для EhCache + JCache (JSR-107) в JavaConfig?

Моя конфигурация кеша:

@Configuration
@EnableCaching
public class CacheConfig {

    private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration =
            Eh107Configuration.fromEhcacheCacheConfiguration(CacheConfigurationBuilder
                    .newCacheConfigurationBuilder(Object.class, Object.class,
                            ResourcePoolsBuilder.newResourcePoolsBuilder()
                                    .heap(100, EntryUnit.ENTRIES))
                    .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(60)))
                    .build());

    @Bean
    public JCacheManagerCustomizer cacheManagerCustomizer() {
        return cm -> {
            createIfNotExists(cm, "model.Role");
            createIfNotExists(cm, "model.User.roles");
            // ...
        };
    }

    private void createIfNotExists(CacheManager cacheManager, String cacheName) {
        if (cacheManager.getCache(cacheName) == null) {
            cacheManager.createCache(cacheName, jcacheConfiguration);
        }
    }
}

Зависимости Gradle:

implementation group: 'org.springframework.boot', name: 'spring-boot-starter-cache'
implementation group: 'javax.cache', name: 'cache-api'
implementation group: 'org.ehcache', name: 'ehcache'
implementation group: 'org.hibernate', name: 'hibernate-jcache'

Неудачный тест:

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class SecondLevelCacheTest {
    @Autowired
    private RoleRepository roleRepository;
    private CacheManager manager;

    @Before
    public void initCacheManager() {
        CachingProvider provider = Caching.getCachingProvider();
        manager = provider.getCacheManager();

        final String cacheRegion = "model.Role";
        manager.getCache(cacheRegion).clear();
    }

    @Test
    public final void givenEntityIsLoaded_thenItIsCached() {
        final String cacheRegion = "model.Role";

        boolean hasNext = manager.getCache(cacheRegion).iterator().hasNext();
        final Role role = roleRepository.findByName("USER");
        boolean hasNext2 = manager.getCache(cacheRegion).iterator().hasNext();
        final Role role2 = roleRepository.findByName("USER");

        Assert.assertFalse(hasNext);
        Assert.assertTrue(hasNext2);
    }
}

Наиболее популярное решение - «установить для общего свойства значение false в контексте тестирования». Как я могу сделать это в отношении моей конфигурации?

1 Ответ

0 голосов
/ 25 ноября 2018

Предлагаемое решение, о котором вы говорите, основано на Ehcache 2. Вы используете Ehcache 3 (хорошо для вас), поэтому оно недействительно.

Spring позаботится о закрытии CacheManager, поэтому обычно вам ничего не нужно заботиться. Кроме того, вам не нужно обращаться к нему через CachingProvider. Вы можете @Autowired javax.cache.CacheManager и таким образом вы обязательно получите правильный.

Однако вы используете Hibernate. Вы должны убедиться, что Spring и Hibernate используют один и тот же CacheManager. Способ его настройки зависит от версии Spring и Hibernate.

Можем ли мы получить полную трассировку стека? Прямо сейчас кажется, что что-то закрывает CacheManager без отмены регистрации в CachingProvider. Это невозможно, если вы не закрываете org.ehcache.CacheManager, не закрывая javax.cache.CacheManager, оборачивая его. Закрытие позже приведет к отмене регистрации.

...