Thorntail应用中Infinispan作为JCache提供者的配置问题
你碰到的问题很典型——因为Infinispan通过XML配置提前创建了名为foo的缓存,而JSR-107规范要求CacheManager.createCache()在缓存已存在时必须抛出异常,所以你的代码才会报错。下面给你两种实用的解决方案,既能保留JCache的提供者无关性,又能搞定Infinispan的特定属性配置:
方案一:复用XML配置的缓存,统一管理所有属性
既然你已经在infinispan.xml里定义了Infinispan特定的acquire-timeout,那不如把JCache的标准属性也一并放到XML里配置,这样代码里只需要直接获取已存在的缓存即可,完全符合JCache规范,还能保持代码的提供者无关性。
第一步:修改infinispan.xml,加入JCache标准属性
Infinispan的XML配置支持直接定义JCache的标准属性,把你原本用代码设置的store-by-value、统计/管理开关都加进去:
<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:infinispan:config:9.4 http://www.infinispan.org/schemas/infinispan-config-9.4.xsd" xmlns="urn:infinispan:config:9.4"> <cache-container> <local-cache name="foo"> <!-- Infinispan特定属性 --> <locking acquire-timeout="15000"/> <!-- JCache标准属性 --> <store-by-value/> <!-- 对应store-by-value=true --> <statistics enabled="false"/> <management enabled="false"/> </local-cache> </cache-container> </infinispan>
第二步:修改produce方法,直接获取缓存
不需要再调用createCache,直接从CacheManager获取已配置好的缓存:
@Produces @FooCache public Cache<Long, DiscountOrAddition> getDiscoCache(CacheManager mgr) { // 直接获取XML中定义的"foo"缓存 return mgr.getCache("foo"); }
这个方案的优势是代码完全基于JCache标准API,没有绑定到Infinispan——如果以后换其他JCache提供者,只需要替换对应的配置文件就行,代码不用改。
方案二:通过代码同时配置JCache和Infinispan属性
如果你更倾向于用代码管理所有配置,Infinispan的JCache实现允许你通过它的配置构建器,同时设置标准JCache属性和Infinispan特定属性,再创建缓存。不过这个方案会引入Infinispan的API依赖,稍微损失一点提供者无关性,但胜在配置集中在代码里。
代码示例:
@Produces @FooCache public Cache<Long, DiscountOrAddition> createDiscoCache(CacheManager mgr) { // 创建Infinispan配置构建器 InfinispanConfigurationBuilder ispnBuilder = new InfinispanConfigurationBuilder(); // 设置Infinispan特定属性 ispnBuilder.locking().acquireTimeout(15000); // 设置JCache标准属性 ispnBuilder.jcache() .storeByValue(true) .statistics(false) .management(false); // 构建JCache兼容的配置 Configuration<Long, DiscountOrAddition> config = ispnBuilder.build(); // 尝试创建缓存,若已存在则会抛出异常,所以可以先判断缓存是否存在 try { return mgr.createCache("foo", config); } catch (CacheExistsException e) { return mgr.getCache("foo"); } }
为什么原来的方案会失败?
这是JSR-107规范的硬性要求:当调用createCache()时,如果同名缓存已经存在(比如你的XML在CacheManager初始化时就创建了foo),必须抛出CacheExistsException。所以你不能用createCache去覆盖已存在的缓存配置。
内容的提问来源于stack exchange,提问作者geca

