Pregunta

I need your expertise :)

I'm working on a application where method calls on a service need to be authenticated. That means I want each method call to be cached with a key containing the username (to avoid for an unauthorized user to retrieve information cached by an authorized one).

With a personnalized KeyGenerator, all works fine.

Example of my key : username:USERNAME.appVersion:VERSION.METHOD.PARAM1.etc

But at some location, I got methods that retrieve a national content : this one will be the same for each user. And I want to avoid a cache key for each user asking for this content.

Example : appVersion:VERSION.METHOD.PARAM1.etc

So when I'm positioning my @Cacheable annotations, is there any way to set a new parameter in it ? The Key Generator will be able to catch it and know if he had to prefix the cache key name with user information or not.

Thanks for your help :)

Take care

¿Fue útil?

Solución

I don't really understand what you're saying by "set a new parameter in it". That parameter should come from somewhere right?

KeyGenerator gives you access to the Method, the actual instance and the method arguments. You may want to have a specific KeyGenerator for this particular cache operation which is something that will be available as from Spring 4.1 but in the mean time you can implement a composite that invokes the right KeyGenerator instance based on the method or, for instance, an annotation you have created to flag it.

Otros consejos

Thank you snicoll, that was crystal clear and you really helped me a lot :)

Waiting for Spring 4.1, my team and I decided to use a custom @SharedCache annotation.

Here is some code samples to help if someone is in the same situation.

  • Given an existing custom GenericKeyGenerator (he's building a custom cache key for each cached method invocation)

  • We have a new custom AuthenticatedGenericKeyGenerator : he's inherited from GenericKeyGenerator and simply prefixing the cache key with user information

The application is now using AuthenticatedGenericKeyGenerator by default :

<cache:annotation-driven key-generator="keyGenerator"/>

<bean id="keyGenerator" class="your.package.AuthenticatedGenericKeyGenerator" />

AuthenticatedGenericKeyGenerator.java in details :

public class AuthenticatedGenericKeyGenerator extends GenericKeyGenerator {

    public AuthenticatedGenericKeyGenerator() {

        super(...);
    }

    @Override
    public Object generate(final Object target, final Method method, final Object... params) {

        String cacheKey = super.generate(target, method, params).toString();

        if(!method.isAnnotationPresent(SharedCache.class)) {

            cacheKey =  "user:" + some user information + "." + cacheKey;
        }

        return cacheKey;
    }

}

Our custom @SharedCache annotation :

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface SharedCache {

}

Now we just have to annotate @Cacheable methods with an extra @SharedCache if we want the cache key to be shared and not be unique (with an user id for example).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top