ClassCastException 在使用某些缓存加载器配置的直读缓存的情况下

ClassCastException in case of configured read-through cache with some cache loader

最近我 运行 遇到了 Infinispan 8.2 的问题。1.Final。我在配置缓存加载器的失效模式下有一些通读缓存。该缓存的配置由两部分组成。第一部分是 XML 中的以下模板:

<?xml version="1.0" encoding="UTF-8"?>
<infinispan xmlns="urn:infinispan:config:8.2">
    <cache-container default-cache="default">
        <transport cluster="jcache-cluster"/>
        <invalidation-cache-configuration name="user" mode="SYNC" statistics="true"/>
    </cache-container>
</infinispan>

第二部分是使用 classes 和来自 JCache 的接口的编程配置 API:

new MutableConfiguration<String, User>()
    .setReadThrough(true).setStoreByValue(true)
    .setCacheLoaderFactory(FactoryBuilder.factoryOf(UserCacheLoader.class));

UserCacheLoader 非常简单。它只是在每次调用时创建一个 User 的新实例。

一切正常,直到我调用 javax.cache.Cache.removeAll() 方法。它会导致以下异常:

Caused by: java.lang.ClassCastException: org.infinispan.test.User cannot be cast to java.lang.String
at org.infinispan.test.UserCacheLoader.load(UserCacheLoader.java:40)
at org.infinispan.jcache.embedded.JCacheLoaderAdapter.loadKey(JCacheLoaderAdapter.java:65)
... 40 more

经过一些调查,我在 class org.infinispan.jcache.embedded.JCacheLoaderAdapter 中找到了以下代码:

@Override
public MarshalledEntry load(Object key) throws PersistenceException {
  V value = loadKey(key);

  if (value != null) {
     Duration expiry = Expiration.getExpiry(expiryPolicy, Expiration.Operation.CREATION);
     long now = ctx.getTimeService().wallClockTime(); // ms
     if (expiry == null || expiry.isEternal()) {
        return ctx.getMarshalledEntryFactory().newMarshalledEntry(value, value, null);
     } else {
        long exp = now + expiry.getTimeUnit().toMillis(expiry.getDurationAmount());
        JCacheInternalMetadata meta = new JCacheInternalMetadata(now, exp);
        return ctx.getMarshalledEntryFactory().newMarshalledEntry(value, value, meta);
     }
  }

  return null;
}

如您所见,使用 value 作为键和值调用 newMarshalledEntry

这是错误还是功能?有人遇到同样的问题吗?

P.S。似乎这个问题对于最新版本的 Infinispan 也是实际的。

这确实是一个 bug,现在已被 @brianheart 修复:)。它将包含在下一个版本中。