PDA

View Full Version : CacheAdvice does not take into account the parameters passed to the method



PVG
08-31-2006, 11:25 AM
Hi,

When using the MemoryCache advice in the unittests I discovered the caching indeed works.

The problem however is that the GetCacheKey method in the CacheAdvice class only takes in account the full name of the method, and not the parameters that are passed in.

So what happened is that the result of my first method invocation was being cached. All subsequent calls to the method return exactly the cached result.

The method however took parameters. And the cached result as such is wrong since the result is linked to the parameters being passed in.

Can I simply use the GetParameters on the MethodInfo class and concatenate the values into the cachekey that is returned? I will implement this and try to submit it to any of the spring team members. Then you guys can see if there is anohter solution or that my workaround/solution is ok.

Is there another solution? Maybe this bugfix is part of the refactoring I could read upon in this forum. This refactoring however takes quite some time appearantly.

KR

Patrick

Bruno Baia
08-31-2006, 03:03 PM
Hi Patrick,

thanks for reporting this, i created an issue in JIRA (http://opensource.atlassian.com/projects/spring/browse/SPRNET-360).
I also received an private email from you, i'll take a look.



This refactoring however takes quite some time appearantly.
The refactoring was related to dynamic proxies and has been commited :
see fisheye report (http://fisheye1.cenqua.com/changelog/springnet/?cs=MAIN:bbaia:20060810184552) for more information.


-Bruno

ananthar
10-27-2006, 03:33 PM
Hello Bruno,

I want to incorporate client-side cache and server-side cache in my application . Is there any way I can use Spring.NET to get my caching framework up?
I saw some references of Spring.Air application on the net, but I am having tough time figuring this out.

Is there any documentation or a working sample for the same?
Do let me know.

Regards,
Anantha

Bruno Baia
10-27-2006, 07:05 PM
Hi Anantha,

Cache management is good candidate for AOP, take a look to this part of the reference documentation :
The Spring.NET AOP Cookbook - Cache (http://www.springframework.net/doc/reference/html/aop-quickstart.html#aop-quickstart-cookbook-caching)

We currenlty have an Cache Aspect implemented in Spring.Web using the ASP.NET Cache (AspNetCacheAdvice), but you can created your own one based on EntLibs or a simple hashtable.

Hope this helps,
Bruno

PS: I'm currenlty fixing the issue described by this thread.

ananthar
10-30-2006, 09:30 AM
Hi Bruno,

I got this working. One question though - instead of intercepting each and every method call - Do we have a way to intercept the occurences of a String . I had done this using AoP in Java , does this feature exist using Spring.NET?

This way, I can avoid the hit to every other method invocation in the class which hosts the method in question - where we have got the data cached.

Regards,
Anantha

ananthar
10-30-2006, 09:49 AM
Hi,

Please ignore my previous post. I figured out - that's precisely the reason why we have to use [Cache] on top of the method declaration.

Regards,
Anantha

Aleks Seovic
10-30-2006, 04:57 PM
CacheAdvice as it currently exists is not a production quality code, but more of a proof-of-concept thing that needs to be implemented a bit differently.

1. Instead of using inheritance to implement different caching strategies (ie. AspNetCache, EntLib Caching Block, or even, once .NET client for it is released later this year (http://www.infoq.com/news/coherence32), Tangosol Coherence), we need to define ICacheStore interface and inject it into the CacheAdvice. That way you would always use the same, non-abstract, CacheAdvice class, but you could plug in different ICacheStore implementations into it.

2. As you noted, current cache advice implementation doesn't take parameters into account at all. While that was ok for the demo it was built for, it is definitely not ok for a production use, which is why I said it is more of a POC. However, simply buidling a key based on the values of all parameters is somewhat naive, because sometimes there might be parameters that you don't care about.

What should be done instead is something similar to the ASP.NET cache directive, whioch allows you to specify VaryBy clause and the names of parameters that should be used to generate the key. This should be configured on the CacheAttribute level and the CacheAdvice should simply read those values and generate cache key based on them. Cache key itself will then become a composite value, consisting not only of the class and method name (or better yet, MethodInfo instance), but also of additional elements, one for each parameter that should be used within a key.

Hope this clarifies current state of affairs. Bruno, if you have some bandwidth feel free to implement the changes described above.

Later,

Aleks

Bruno Baia
10-31-2006, 07:20 PM
Hi,



I got this working. One question though - instead of intercepting each and every method call - Do we have a way to intercept the occurences of a String . I had done this using AoP in Java , does this feature exist using Spring.NET?

This way, I can avoid the hit to every other method invocation in the class which hosts the method in question - where we have got the data cached.


You can do this in the same way that Java does, using Pointcuts.
As you noticed, using Attributes is one implementation, but Spring provides others convenience pointcut implementations (http://www.springframework.net/doc-latest/reference/html/aop.html#aop-convenience-impls) but you can also write a custom Pointcut (http://www.springframework.net/doc-latest/reference/html/aop.html#d0e6550) for your specifics needs.


Hope this helps,
Bruno

ananthar
11-20-2006, 01:19 PM
Hi,

Thank you for the reply.
And Apologies for this delayed response - I got the cache framework working in my application.

In fact I faced the same problem initially, which Patrick faced.
I tweaked the implementation of my inherited advice slightly to achieve this.

On the first invocation, I retrieved all the data from the server to my local cache.
I then converted it into a dataset. On subsequent hits, the data will be retrieved from the cached dataset depending on the input parameters.

Data either resides in memory or in a binary serialized file or in SQLite DB depending upon the aspect we configure - which in turn depends on the size of the data.This is taken care of in putObjectinCache().
I wrote 3 aspects inheriting the CacheAdvice : MemoryCacheAdvice, FileCacheAdvice and DBCacheAdvice.

On subsequent requests, getObjectFromCache() data is retrieved in the form of dataset from any one of the the three implementations as per the configuration.

But this is specific to the business needs of the application. In my application, the main objective was to display the search results of any query criteria to be pretty fast.

Hence the above implementation worked for me.

If it helps anyone, let me know - I can post the code onto the forum.

Regards,
Anantha