I would like to enable caching on several services that extends the same AbstractService for findById(Long id) method.
So in my applicationContext i wrote :
<!-- cache definitions -->
<cache:advice id="cacheAdvice" cache-manager="cacheManager">
<cache:caching cache="refs">
<cache:cacheable method="findById" key="#root.targetClass + #id"/>
</cache:caching>
</cache:advice>
<aop:config>
<aop:advisor advice-ref="cacheAdvice" pointcut="execution(* x.y.*.service.reference.*.*(..))"/>
</aop:config>
The problem is i would like to generate a unique key for each service call on method findById because the ID can be the same ( and so have a class cast exception) :
java.lang.ClassCastException: x.y.model.RefSituation cannot be cast to x.y.model.RefCivility
Unit test :
public class AbstractReferenceServiceTest extends AbstractBiTest {
@Inject
@Named("refSituationServiceClient")
private RefSituationService refSituationService;
@Inject
@Named("refCivilityServiceClient")
private RefCivilityService refCivilityService;
@Test
public void findById() {
RefSituation situation = refSituationService.findById(1L);
situation = refSituationService.findById(2L);
situation = refSituationService.findById(1L);
RefCivility refCivility = refCivilityService.findById(1L);
refCivility = refCivilityService.findById(2L);
refCivility = refCivilityService.findById(1L);
}
}
Both services extends an AbstractReferenceService :
public interface RefSituationService extends AbstractReferenceService<RefSituation> {}
public interface RefCivilityService extends AbstractReferenceService<RefCivility> {}
And AbstractReferenceService extends A crudService provided by a framework called RestHub (https://github.com/resthub/resthub-spring-stack/blob/master/resthub-common/src/main/java/org/resthub/common/service/CrudService.java)
But with the configuration above i have an error :
org.springframework.expression.spel.SpelEvaluationException: EL1030E:(pos 0): The operator 'ADD' is not supported between objects of type 'java.lang.Class' and 'null'
at org.springframework.expression.spel.ExpressionState.operate(ExpressionState.java:198)
at org.springframework.expression.spel.ast.OpPlus.getValueInternal(OpPlus.java:97)
at org.springframework.expression.spel.ast.SpelNodeImpl.getValue(SpelNodeImpl.java:93)
at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:89)
at org.springframework.cache.interceptor.ExpressionEvaluator.key(ExpressionEvaluator.java:80)
at org.springframework.cache.interceptor.CacheAspectSupport$CacheOperationContext.generateKey(CacheAspectSupport.java:464)
at org.springframework.cache.interceptor.CacheAspectSupport.inspectCacheables(CacheAspectSupport.java:291)
at org.springframework.cache.interceptor.CacheAspectSupport.execute(CacheAspectSupport.java:198)
at org.springframework.cache.interceptor.CacheInterceptor.invoke(CacheInterceptor.java:66)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at com.sun.proxy.$Proxy175.findById(Unknown Source)
Thanks in advance for your help.
The problem is #root.targetClass.name is always "CrudService", to resolve the problem you have to :
1- Implement your own CacheKeyGenerator :
ApplicationContext.xml :
Java :
Test :