I'm developing a WEB APP under JBoss EAP 7.2 (EE8) using EhCache as JCache implementation (JSR 107)
I have this code:
@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;
}
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.
Where am I wrong ?
EDIT
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
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) {
This is my CacheResolverFactory class
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;
}
}
Now I get this:
java.lang.ClassCastException: Invalid key type, expected : java.lang.String but was : org.jsr107.ri.annotations.DefaultGeneratedCacheKey
EDIT EDIT EDIT
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;
}
}
Then I changed ehcache.xml configuration with this:
<cache alias="roles">
<key-type>mypackage.StringCacheKey</key-type>
<value-type>java.util.List</value-type>
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 :/