Search code examples
javajakarta-eeinfinispanjboss-eap-6jsr107

Does javax.cache.annotation.CacheResult in infinispan need parameters in the method


Good day, I’m at the moment puzzled a bit by javax.cache.annotation.CacheResult implementation in the JBoss Enterprise Application Platform 6.1 and 6.3 of infinispan.

I have been googling and going through stackoverflow but I have not really found a defined answer, to the question that has been keeping me busy. So here is I go. Does the @CacheResult annotation need parameters in the method its annotated to. It used the Parameters to actually create the key for the store. Yet it does not really document what happens if you don’t have that. This could happen for a web application that wants to for example want to return a list of countries that is stored in the database and the list does not change that often.

Code example:

/**
 * Fetches a list of Country's from the Database system trough the SOAP adapter.
 *
 * @return a lit of country's from the Database system.
 */
@CacheResult(cacheName = "referenceService/CountryListCache")
// The attributes sorted is used by the caching mechanism, as combined key for the (to be) cached CountryListCache object.
public List<Country> getCountryList() throws ReferenceServiceException_Exception {
    LOG.debug("Cache is not used doing a full call to the service.");
    ReferenceTableIdSO getter = //Create a getter that does the external query;

    List<AlfaCodeDBObjectSO> transform = //calls the external system to get the data.
    //Transform the external data to somtine we want to return.
    List<Country> result = new ArrayList<Country>();
    for (AlfaCodeDBObjectSO trans : transform) {
        Country country = new Country(trans.getCode(), trans.getExplanation());
        result.add(country);
    }

    return result;
}

Config of EAP6.1.1

    <subsystem xmlns="urn:jboss:domain:infinispan:1.4">
        <cache-container name="rest-cache" default-cache="default" start="EAGER"> 
            <local-cache name="default">  
                <transaction mode="NONE"/>
                <eviction strategy="LRU" max-entries="1000"/>
                <expiration max-idle="3600000"/>
            </local-cache>
            <local-cache name="referenceService/CountryListCache">  
                <locking isolation="REPEATABLE_READ" acquire-timeout="15000"/>
                <transaction mode="NONE" locking="PESSIMISTIC"/>
                <eviction strategy="LRU" max-entries="1024"/>
                <expiration lifespan="86400000"/>
            </local-cache>
        </cache-container>
    </subsystem>

As you see in my example I would want to reduce the code call. And I set up the configuration to once a day refresh just to be sure. But I am actually not sure if the list is cached etc. Because its so poorly documented about if the method has no parameter.


Solution

  • According to the specification for JSR-107, if cacheName is not specified, @CacheResult will

    • Look for the cacheName property on the @CacheDefaults annotation on the class. This annotation, as you can infer from the name, sets defaults for cache-related annotations in the class. If this annotation is not set, then

    • Autogenerate a cacheName with the template package.name.ClassName.methodName(package.ParameterType,package.ParameterType)

    EDIT: I misread your question earlier. Regarding the key generation for a method that has no parameters, while the spec doesn't directly address it, one can infer that it's not supported from the following standpoints

    • Infinispan's implementation of the DefaultCacheKey(the wrapper class for the key in the cache) shows that a no-arg method will result in a deepHashCode of 0, for every invocation of the method. As a result, your cache will only ever contain one value, with a key of 0

    • The getAnnotations() method in the JSR has the following comment:

      @return An immutable Set of all Annotations on this method parameter,never null.

      This indicates (to me anyway) that there's no expectation that a cached method won't have a parameter.


    You might want to re-evaluate your design: I can't think of a reason why a no-arg method invocation should be cached. There are two use-cases I can think of for a no-arg method

    • Each invocation of the method returns a unique value for every invocation, in which case, you don't want to add caching to that level of the component,but to the parent method as there's no value in caching a unique value that will not be used after the first invocation

    • Each invocation of the method returns the same value, in which case, it's probably cleaner to invoke the method once (maybe at startup) and stash the return value, to be used for the duration of the application