Announcement Announcement Module
Collapse
No announcement yet.
How to construct a key for cache in @Cacheable annotation Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to construct a key for cache in @Cacheable annotation

    Hi there,

    Another question about spring cache abstraction @Cacheable annotation:
    Code:
    public PersonService {
       ...
       public string getType() {
          return "PersonService";
       }
       
        @Cacheable(value = "defaultCache")
        public Person findPerson(int id)  {
                return getSession().getPerson(id);
        }
    
    }
    Can I construct the cache key to be getType() + id using SpEL in the @cacheable annotation?
    Thanks,

    David

  • #2
    This is without testing it, but I think you should be able to do somthing like this
    Code:
    @Cacheable(value = "defaultCache", key="#root.target.getType() + #id")
    See the "28.3.1.2 Custom Key Generation Declaration" and "28.3.1.4 Available caching SpEL evaluation context" in the Spring reference manual [1].

    [1] http://static.springsource.org/sprin...tml/cache.html

    Best regards
    Pontus Ullgren

    Comment


    • #3
      Thanks,

      Code:
      key="#root.target.getType()"
      worked. One observation though, if I need to call the method from the returned object by getType(), say,
      Code:
      key="#root.target.getType().getName()"
      , I'll get an error:

      org.springframework.expression.spel.SpelEvaluation Exception: EL1004Epos 23): Method call: Method getName() cannot be found on com.example.Person type
      at org.springframework.expression.spel.ast.MethodRefe rence.findAccessorForMethod(MethodReference.java:1 82)
      at org.springframework.expression.spel.ast.MethodRefe rence.getValueInternal(MethodReference.java:106)
      at org.springframework.expression.spel.ast.CompoundEx pression.getValueInternal(CompoundExpression.java: 57)
      at org.springframework.expression.spel.ast.OpPlus.get ValueInternal(OpPlus.java:62)
      at org.springframework.expression.spel.ast.OpPlus.get ValueInternal(OpPlus.java:62)
      at org.springframework.expression.spel.ast.SpelNodeIm pl.getValue(SpelNodeImpl.java:93)
      at org.springframework.expression.spel.standard.SpelE xpression.getValue(SpelExpression.java:88)
      at org.springframework.cache.interceptor.ExpressionEv aluator.key(ExpressionEvaluator.java:80)
      at org.springframework.cache.interceptor.CacheAspectS upport$CacheOperationContext.generateKey(CacheAspe ctSupport.java:464)
      at org.springframework.cache.interceptor.CacheAspectS upport.inspectCacheables(CacheAspectSupport.java:2 91)
      at org.springframework.cache.interceptor.CacheAspectS upport.execute(CacheAspectSupport.java:198)
      at org.springframework.cache.interceptor.CacheInterce ptor.invoke(CacheInterceptor.java:66)
      at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :172)
      at org.springframework.aop.framework.Cglib2AopProxy$D ynamicAdvisedInterceptor.intercept(Cglib2AopProxy. java:622)
      at com.activx.om.util.dao.TorqueDAO$$EnhancerByCGLIB$ $190b8d3a.find(<generated>)
      at com.activx.om.util.dao.TorqueDAOTest.testFind(Torq ueDAOTest.java:76)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknow n Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Un known Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.junit.runners.model.FrameworkMethod$1.runRefle ctiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallabl e.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExpl osively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.InvokeMethod .evaluate(InvokeMethod.java:20)
      at org.junit.internal.runners.statements.RunBefores.e valuate(RunBefores.java:28)
      at org.junit.runners.ParentRunner.runLeaf(ParentRunne r.java:263)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild( BlockJUnit4ClassRunner.java:69)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild( BlockJUnit4ClassRunner.java:48)
      at org.junit.runners.ParentRunner$3.run(ParentRunner. java:231)
      at org.junit.runners.ParentRunner$1.schedule(ParentRu nner.java:60)
      at org.junit.runners.ParentRunner.runChildren(ParentR unner.java:229)
      at org.junit.runners.ParentRunner.access$000(ParentRu nner.java:50)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRu nner.java:222)
      at org.junit.internal.runners.statements.RunBefores.e valuate(RunBefores.java:28)
      at org.junit.runners.ParentRunner.run(ParentRunner.ja va:292)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestR eference.run(JUnit4TestReference.java:50)
      at org.eclipse.jdt.internal.junit.runner.TestExecutio n.run(TestExecution.java:38)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:467)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.runTests(RemoteTestRunner.java:683)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.run(RemoteTestRunner.java:390)
      at org.eclipse.jdt.internal.junit.runner.RemoteTestRu nner.main(RemoteTestRunner.java:197)

      Comment


      • #4
        From the posted stack trace it seems you have changed your code since your original post.

        You need to make sure that the object returned from getType() has a getName() method.

        BR
        Pontus

        Comment


        • #5
          The returned object (Class) does have a getName method, if I have another method like:
          Code:
          public String getTypeName() {
             return getType().getName();
          }
          it'll work, but I guess Spring can't call the returned object's method from the proxy it generated. It's trying to access the returned object in the cached method, rather than accessing the method in the class.
          But it's no biggie, I can get it to work, just something I observed as a heads-up for others.
          Thanks,

          David

          Originally posted by ullgren View Post
          From the posted stack trace it seems you have changed your code since your original post.

          You need to make sure that the
          object returned from getType() has a getName() method.

          BR
          Pontus

          Comment

          Working...
          X