EE8 JCache注释CacheResult不起作用 [英] EE8 JCache annotation CacheResult doesn't work

查看:208
本文介绍了EE8 JCache注释CacheResult不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用EhCache作为JCache实现(JSR 107)在JBoss EAP 7.2下开发Web应用程序

I'm developing a WEB APP under JBoss EAP 7.2 (EE8) using EhCache as JCache implementation (JSR 107)

我有以下代码:

@Inject
CacheManager cacheManager;

@CacheResult(cacheName = "roles")
public List<RoleDTO> get(@CacheKey String id) {
    return service.getRoles(id);
}

public List<RoleDTO> getRoles(final String userId) {

    final List<RoleDTO> output = get(userId);

    return output;
}

根据此文章我读到了,我希望我第二次访问get(userId)方法时应该使用缓存,而忽略输入方法,但并非如此。
我还查询注入的cacheManager,并且角色缓存始终为空。

According to this article I read, I'd expect the second time I access the get(userId) method should use cache and ignore entering the method, but is not so. I also queries injected cacheManager, and "roles" cache is always empty.

我在哪里错了?

编辑

我想EhCache 3.x在标准EE环境中不支持jcache批注,在网络上我可以仅看到ri o guice等其他CDI实现。
但是,通过包括以下实现之一,例如:

I guess EhCache 3.x doesn't support jcache annotations in a standard EE environment, on the web I can only see other CDI implementations like ri o guice. However, by including one of these implementations, for example:

    <dependency>
        <groupId>org.jsr107.ri</groupId>
        <artifactId>cache-annotations-ri-cdi</artifactId>
    </dependency>

似乎将新的缓存项放到新的缓存管理器中(请参见以下代码)

seems the new cache entry is put onto a new cachemanager (see the below code)

 Caching.getCachingProvider().getCacheManager

我已经没有注入和配置的CacheManager

instead of the injected and configured CacheManager I already have

EDIT EDIT

@CacheResult(cacheName = "roles", cacheResolverFactory = AppCacheResolverFactory.class, cacheKeyGenerator = CacheKeyGeneratorFactory.class)
    public List<RoleDTO> getRoles(@CacheKey final String userId) {

这是我的 CacheResolverFactory

public class AppCacheResolverFactory implements CacheResolverFactory {


    @Inject
    CacheManager cacheManager;

    @Override
    public CacheResolver getCacheResolver(CacheMethodDetails<? extends Annotation> cacheMethodDetails) {
        return new DefaultCacheResolver(cacheManager.getCache(cacheMethodDetails.getCacheName()));
    }

    @Override
    public CacheResolver getExceptionCacheResolver(CacheMethodDetails<CacheResult> cacheMethodDetails) {
        return null;
    }
}

现在我明白了:

java.lang.ClassCastException: Invalid key type, expected : java.lang.String but was : org.jsr107.ri.annotations.DefaultGeneratedCacheKey

EDIT EDIT EDIT

我创建了一个CacheKeyGeneratorFactory和一个包装字符串值的StringCacheKey:

I've created a CacheKeyGeneratorFactory and a StringCacheKey that wraps a String value:

CacheKeyGeneratorFactory

public class CacheKeyGeneratorFactory implements CacheKeyGenerator {
    @Override
    public GeneratedCacheKey generateCacheKey(CacheKeyInvocationContext<? extends Annotation> cacheKeyInvocationContext) {
        final CacheInvocationParameter[] allParameters = cacheKeyInvocationContext.getAllParameters();
        for (CacheInvocationParameter parameter : allParameters) {
            if (StringCacheKey.class.equals(parameter.getRawType())) {
                return (StringCacheKey)parameter.getValue();
            }
        }
        return null;
    }
}

StringCacheKey

public class StringCacheKey implements GeneratedCacheKey {

    private String value;

    public StringCacheKey(String param) {
        this.value = param;
    }

    @Override
    public int hashCode() {
        return this.value.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        return obj != null && obj.getClass() == this.getClass() && this.value.equals(((StringCacheKey)obj).getValue());
    }

    public String getValue() {
        return value;
    }
}

然后我使用以下命令更改了ehcache.xml配置:

Then I changed ehcache.xml configuration with this:

 <cache alias="roles">
    <key-type>mypackage.StringCacheKey</key-type>
    <value-type>java.util.List</value-type>

还有@CacheResult的方法

And the method with @CacheResult too

public List<RoleDTO> get(@CacheKey String id) 

现在可以了,但是我想知道我是否可以保存所有这些代码和使其生效的类:/

Now it goes, however I wonder I can save all this bunch of code and class to make it work :/

推荐答案

RI默认将密钥包装到 DefaultGeneratedCacheKey 。您需要更改EHCache配置,以允许键的 Object 类型。另外,您可以注册自己的密钥生成器并使用自己的密钥类型。当然,您也可以在EHCache配置中指定 org.jsr107.ri.annotations.DefaultGeneratedCacheKey ,然后绑定到特定的实现。

The RI wraps keys by default into DefaultGeneratedCacheKey. You need to change your EHCache configuration to allow Object types for the key. Alternatively you can register your own key generator and use your own key type. You can of course also specify org.jsr107.ri.annotations.DefaultGeneratedCacheKey in your EHCache configuration, however, then you bind to a specific implementation.

不幸的是,用于注释的JSR107 / JCache标准要求高速缓存键实现接口 GeneratedCacheKey 。这意味着,如果您有一个简单的缓存键(例如int或string),那么在存储到缓存中时,总是需要将它们包装起来。

Unfortunately, the JSR107/JCache standard for annotations requires that a cache key implements the interface GeneratedCacheKey. That means, if you have a simple cache key like int or string, these always need to get wrapped, when stored into the cache.

侧面说明:没有技术接口 GeneratedCacheKey 的需要,因为它没有定义任何新方法。这是标准中的已知问题。不幸的是,在标准最终定稿之前,注释部分没有得到足够的审查。

Side note: There is no technical need for the interface GeneratedCacheKey, since it does not define any new methods. This is a known problem in the standard. Unfortunately, there was no sufficient vetting of the annotations part before the standard got finalized.

这篇关于EE8 JCache注释CacheResult不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆