EHCache + Tomcat + Terracota + Jsr107 + Spring + @ CacheEvict(allEntries = true)= UnsupportedOperationException:实现我

时间:2018-04-24 15:45:08

标签: spring-mvc java-8 terracotta ehcache-3 jsr107

我设法加入EhCache和Terracota进行分布式集群(项目在https://github.com/ehcache/ehcache3/releases/download/v3.4.0/ehcache-clustered-3.4.0-kit.zip)并进行Spring配置集成,如:

import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.cache.CacheManager;
import javax.cache.Caching;
import org.ehcache.clustered.client.config.ClusteredStoreConfiguration;
import org.ehcache.clustered.client.config.builders.ClusteredResourcePoolBuilder;
import org.ehcache.clustered.client.config.builders.ClusteringServiceConfigurationBuilder;
import org.ehcache.clustered.client.config.builders.ServerSideConfigurationBuilder;
import org.ehcache.clustered.common.Consistency;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.core.config.DefaultConfiguration;
import org.ehcache.expiry.Expirations;
import org.ehcache.jsr107.EhcacheCachingProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.jcache.JCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import net.crezco.util.CustomProperties;

@Configuration
@EnableCaching
@Component
public class CacheConfig extends CachingConfigurerSupport {

    private CustomProperties props;

    private CacheManager cacheManager;

    @Autowired
    public CacheConfig(CustomProperties props) {
        this.props = props;
    }

    @Bean
    @Override
    public org.springframework.cache.CacheManager cacheManager() {
        cacheManager = createClusteredCacheManager();
        return new JCacheCacheManager(cacheManager);
    }

    private CacheManager createClusteredCacheManager() {
        URI clusterUri = URI.create(props.readCacheLocation());
        Consistency consistency = Consistency.STRONG;
        long sizeInMb = 10;
        int ttl = 90; // 90s
        long size = 100;

        ClusteringServiceConfigurationBuilder clusteringServiceConfigurationBuilder = ClusteringServiceConfigurationBuilder.cluster(clusterUri);
        ServerSideConfigurationBuilder serverSideConfigurationBuilder = (clusteringServiceConfigurationBuilder.autoCreate()).defaultServerResource("main");

        ResourcePoolsBuilder.newResourcePoolsBuilder();
        org.ehcache.config.CacheConfiguration<Object, Object> cacheConfiguration = CacheConfigurationBuilder
                .newCacheConfigurationBuilder(Object.class, Object.class, ResourcePoolsBuilder.heap(size).with(ClusteredResourcePoolBuilder.clusteredDedicated(sizeInMb, MemoryUnit.MB)))
                .withExpiry(Expirations.timeToLiveExpiration(new org.ehcache.expiry.Duration(ttl, TimeUnit.SECONDS))).add(new ClusteredStoreConfiguration(consistency)).build();

        Map<String, org.ehcache.config.CacheConfiguration<?, ?>> caches = createCacheConfigurations(cacheConfiguration);

        EhcacheCachingProvider provider = getCachingProvider();
        DefaultConfiguration configuration = new DefaultConfiguration(caches, provider.getDefaultClassLoader(), serverSideConfigurationBuilder.build());
        return provider.getCacheManager(provider.getDefaultURI(), configuration);
    }

    private Map<String, org.ehcache.config.CacheConfiguration<?, ?>> createCacheConfigurations(org.ehcache.config.CacheConfiguration<Object, Object> cacheConfiguration) {
        Map<String, org.ehcache.config.CacheConfiguration<?, ?>> caches = new HashMap<>();
        caches.put("iterableCountryCache", cacheConfiguration);
        caches.put("elementCountryCache", cacheConfiguration);
        return caches;
    }

    private EhcacheCachingProvider getCachingProvider() {
        return (EhcacheCachingProvider) Caching.getCachingProvider();
    }
}

然后,在经理上:

@Cacheable(cacheNames = "elementCountryCache", key = "#id + #langCode")
public CountryRes getById(Long id, User user, String langCode) {
    return getByIdTemplate(id, user, langCode);
}

@Cacheable(cacheNames = "iterableCountryCache", key = "#query.toCacheKeyString()")
public Iterable<CountryRes> findAll(SearchQuery<CountryRes> query, User user, String langCode) {
    return super.findAll(query, user, langCode);
}

@CacheEvict(value = "iterableCountryCache", allEntries = true)
public CountryRes save(CountryRes res, User user, String langCode) {
    return saveTemplate(res, user, langCode);
}

@Caching(evict = { @CacheEvict(value = "iterableCountryCache", allEntries = true), @CacheEvict(value = "elementCountryCache", key = "#res.getNativeId() + #langCode") })
public CountryRes update(CountryRes res, User user, String langCode) {
    return updateTemplate(res, user, langCode);
}

@Caching(evict = { @CacheEvict(value = "iterableCountryCache", allEntries = true), @CacheEvict(value = "elementCountryCache", allEntries = true) })
public void deleteById(Long id, User user) {
    deleteTemplate(id, user);
}

缓存似乎正常工作。测试时(Junit或手动启动tomcat)findAll&amp; findById函数在第一次尝试后会加速。

但是在尝试保存时会发生异常:

java.lang.UnsupportedOperationException: Implement me
    at org.ehcache.clustered.client.internal.store.ClusteredStore.iterator(ClusteredStore.java:463)
    at org.ehcache.impl.internal.store.tiering.TieredStore.iterator(TieredStore.java:243)
    at org.ehcache.core.Ehcache$Jsr107CacheImpl.removeAll(Ehcache.java:832)
    at org.ehcache.jsr107.Eh107Cache.removeAll(Eh107Cache.java:311)
    at org.springframework.cache.jcache.JCacheCache.clear(JCacheCache.java:108)
    at org.springframework.cache.interceptor.AbstractCacheInvoker.doClear(AbstractCacheInvoker.java:113)
    at org.springframework.cache.interceptor.CacheAspectSupport.performCacheEvict(CacheAspectSupport.java:457)
    at org.springframework.cache.interceptor.CacheAspectSupport.processCacheEvicts(CacheAspectSupport.java:445)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:402)
    at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:314)
    at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:61)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
    at net.crezco.service.core.CountryManager$$EnhancerBySpringCGLIB$$d444b04b.save(<generated>)
    at net.crezco.service.core.CountryManagerTest.createCountryCached(CountryManagerTest.java:217)
    at net.crezco.service.core.CountryManagerTest.testBadUpdate(CountryManagerTest.java:123)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.springframework.test.context.junit4.statements.RunBeforeTestExecutionCallbacks.evaluate(RunBeforeTestExecutionCallbacks.java:73)
    at org.springframework.test.context.junit4.statements.RunAfterTestExecutionCallbacks.evaluate(RunAfterTestExecutionCallbacks.java:83)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

这里有什么想法吗?非常感谢你提前。

1 个答案:

答案 0 :(得分:0)

似乎删除.with(ClusteredResourcePoolBuilder.clusteredDedicated(sizeInMb,MemoryUnit.MB))可以完全访问迭代器。但我不知道为什么也不知道原因,因为它不适合它。