Implementing Object Caching with AOP

Discussions

News: Implementing Object Caching with AOP

  1. Implementing Object Caching with AOP (33 messages)

    Object Caching is a cross cutting concern that could be refactored into an Aspect, making caching occur transparently to application code. In this latest TSS article, Srini Penchikala implements AOP-based caching with AspectJ, JBossCache and OSCache.

    Read Implementing Object Caching with AOP

    Threaded Messages (33)

  2. powerful and dangerous.[ Go to top ]

    That has got to be a very dangerous use for aspects... one of the most dangerous. but powerful. use wisely.
  3. dangerous?[ Go to top ]

    why?
  4. But in the real world...[ Go to top ]

    I was just trying to emphasize the fact that you can use this kind of technology without using any AOP "implementation product" like AspectWerkz or AspectJ. It's possible to "think AOP" and apply it in pure Java, while waiting for the next (potential) step from our managers : pure AOP development :-)
  5. ... you can do pretty much the same with Dynamic proxies :)
  6. dynamic proxies[ Go to top ]

    ... you can do pretty much the same with Dynamic proxies :)

    Well, if you look at it that way, dynamic proxies + interfaces are just another means of doing AO[P].

    -Patrick

    --
    Patrick Linskey
    http://solarmetric.com
  7. Calculation caching[ Go to top ]

    Caching is one of the most common things we use AOP for. But not so much "object" caching as we use it for calculation caching. If an algorithm is expensive or happens often then we simply add an aspect to the method that caches depending on some context (user,parameters,object called, method called). The great thing about using an aspect for it is that you can easily change strategy and that flushing the cache as a side-effect of other objects being changed is very transparent. If the calculation cache was in the actual method that did the calculation then it would in most cases not be so simple to flush it when the input objects for the calculation are changed.
  8. why not use a strategy object?[ Go to top ]

    The great thing about using an aspect for it is that
    >you can easily change strategy and that flushing the
    >cache as a side-effect of other objects being changed
    >is very transparent.

    I'd rather use a caching strategy object that has a real interface and real implementations in real code that i can see in a real browser or file system. It gives the same effect in a more obvious way. I can't see the advantage of hiding this stuff behind such a low level interface like AOP that hides the detail outside of the code.
  9. why not use a strategy object?[ Go to top ]

    >The great thing about using an aspect for it is that >you can easily change strategy and that flushing the >cache as a side-effect of other objects being changed >is very transparent.I'd rather use a caching strategy object that has a real interface and real implementations in real code that i can see in a real browser or file system. It gives the same effect in a more obvious way. I can't see the advantage of hiding this stuff behind such a low level interface like AOP that hides the detail outside of the code.

    Since Rickard can't share what he has done in the way of AOP (I believe he can't, please correct me Rickard) - check out what ADJT has to offer in the way of visualizing this.

    AOP isn't about hiding code but rather about not cluttering code. You can have real interfaces and real code with AOP. It just is applied a wee bit differently. There are different ways of doing AOP from coding to wiring.
  10. why not use a strategy object?[ Go to top ]

    AOP isn't about hiding code but rather about not cluttering code.

    You can't clutter something with what it does, because that's what it is. If what it does is ugly then you can make it clean with good interfaces. Then you can see what it does by looking at the code.

    Layers of abstraction always say we are about being clean, but they mainly make things obscure because the function isn't obvious from the code.
  11. why not use a strategy object?[ Go to top ]

    > AOP isn't about hiding code but rather about not cluttering code.You can't clutter something with what it does, because that's what it is. If what it does is ugly then you can make it clean with good interfaces. Then you can see what it does by looking at the code. Layers of abstraction always say we are about being clean, but they mainly make things obscure because the function isn't obvious from the code.

    Not necessarily true. Our screens have to hide, show as read-only, or show as writable depending on business logic that is an combination of logic, user, and data. I have that security implemented not in the persistence tier, which is just dump presentation, but in a security module that is called using an around aspect. The purely security logic doesn't obscure what the standard business logic does.

    It has proven much easier to maintain.

    Also, things like caching, profiling, remoting, and basic logging isn't what a business method does, but does obsure the code. Now, those items are all added via AOP. I can turn them on or off via configuration file changes, and the pure business logic remains very clean.

    All the good interfaces in the world doesn't help if your business logic is loaded with such things.
  12. A way to look at the cluttering issue is to realize that the sample application in the article is implementing at least two separate concerns: business logic and performance. Strictly from the business logic concern's point-of-view, the performance issue is unimportant and shouldn't burden the business logic implementers. Any kind of caching-related implementation will tangle the business implementation with performance implementation (and other crosscutting implementations). This is undue burden on business concern implementers forcing them to be aware of caching issues.
     
    You could use the strategy pattern for caching, if you knew upfront that performance would be an issue and that caching (or at an abstract level, an object fetching strategy) would be improve performance. If not, using strategy would be an over-design. If you realize the need for strategy pattern later, you will be facing an under-designed system forcing you to change the implementation in many places to introduce caching. This over-design/under-design issue is what I call the architect's dilemma.

    AOP let's you overcome the architect's dilemma. You introduce new crosscutting concerns (such as caching) when and if you need it. Using AOP, if at any point during evolution you realize the need for caching, you can introduce it without any invasive changes. What's more, you could alter the paths and objects involved in caching strategy just by modifying the aspect. For example, you could enable caching only for certain objects and/or for processing in control-flow of certain operations.

    One final point, you could use the strategy design pattern with aspect and that would be a valid alternative to using two aspects. For example, the aspect will contain a member corresponding to caching strategy. Then you could initialize (through dependency injection, subaspects, etc.) that member to, say, either a JBossCacheFetcher or OSCacheFetcher object.

    -Ramnivas
    http://ramnivas.com/blog
  13. AOP let's you overcome the architect's dilemma. You introduce new crosscutting concerns (such as caching) when and if you need it. Using AOP, if at any point during evolution you realize the need for caching, you can introduce it without any invasive changes. What's more, you could alter the paths and objects involved in caching strategy just by modifying the aspect. For example, you could enable caching only for certain objects and/or for processing in control-flow of certain operations.

    I think it's a great idea, I just don't think it's that simple in practice .. but I _do_ want to encourage the work (anything that makes caching more prevalent ;-).

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Cluster your POJOs!
  14. AOP let's you overcome the architect's dilemma.
    > You introduce new crosscutting concerns
    >(such as caching) when and if you need it.

    What this ends up meaning still is that the application and the AOP have to agree on major services like transactions and locking or none of the code can work together. So it isn't really clean. We must all still agree how everything will work together.

    To take the argument to the extreme you should argue for not having name classes and named methods so functionality can be composed more easily. The architect may not like the classes or the methods either.
  15. why not use a strategy object?[ Go to top ]

    Interesting article, but I have a few issues with some of the AOP concepts discussed, which I summarized on my blog:

    http://beust.com/weblog/archives/000273.html

    Feel free to comment here so we can keep the discussion in one place.

    --
    Cedric
  16. why not use a strategy object?[ Go to top ]

    Interesting article, but I have a few issues with some of the AOP concepts discussed, which I summarized on my blog:http://beust.com/weblog/archives/000273.htmlFeel free to comment here so we can keep the discussion in one place.-- Cedric

    The turn off/turn on aspect I think he is refering to is not necessary all the caching, but the precision. With an AOP, I can enable caching on just these methods of an interface. I don't think you get that level of precision with just the caching configuration file. Plus, our code using a basic framework of Struts/Spring/Hibernate with aspects for security and caching(and soon profiling and basic method level logging) and you can use the same basic framework, but depending on how the configuration file is set turn different things on or off.
  17. why not use a strategy object?[ Go to top ]

    Interesting article, but I have a few issues with some of the AOP concepts discussed, which I summarized on my blog:http://beust.com/weblog/archives/000273.htmlFeel free to comment here so we can keep the discussion in one place.-- Cedric
    The turn off/turn on aspect I think he is refering to is not necessary all the caching, but the precision. With an AOP, I can enable caching on just these methods of an interface. I don't think you get that level of precision with just the caching configuration file. Plus, our code using a basic framework of Struts/Spring/Hibernate with aspects for security and caching(and soon profiling and basic method level logging) and you can use the same basic framework, but depending on how the configuration file is set turn different things on or off.
    That's partly true. You do get more fine-tuned control on what methods your pointcuts apply to, but you still need to modify your code (either the aspect or the annotation, as I showed in the annotation approach), so it's still not completely dynamic.

    Nevertheless, it's an improvement over phrasing this as conditional code inside your business logic.

    --
    Cedric
  18. why not use a strategy object?[ Go to top ]

    Interesting article, but I have a few issues with some of the AOP concepts discussed, which I summarized on my blog:http://beust.com/weblog/archives/000273.htmlFeel free to comment here so we can keep the discussion in one place.-- Cedric
    The turn off/turn on aspect I think he is refering to is not necessary all the caching, but the precision. With an AOP, I can enable caching on just these methods of an interface. I don't think you get that level of precision with just the caching configuration file. Plus, our code using a basic framework of Struts/Spring/Hibernate with aspects for security and caching(and soon profiling and basic method level logging) and you can use the same basic framework, but depending on how the configuration file is set turn different things on or off.
    That's partly true. You do get more fine-tuned control on what methods your pointcuts apply to, but you still need to modify your code (either the aspect or the annotation, as I showed in the annotation approach), so it's still not completely dynamic.Nevertheless, it's an improvement over phrasing this as conditional code inside your business logic.-- Cedric

    If I want to add caching to all find* methods, I don't have to modify the code, just the configuration file. Ditto for all find* methods, but findDavid. These would all be configuration file changes.
  19. why not use a strategy object?[ Go to top ]

    Interesting article, but I have a few issues with some of the AOP concepts discussed, which I summarized on my blog:http://beust.com/weblog/archives/000273.htmlFeel free to comment here so we can keep the discussion in one place.-- Cedric
    The turn off/turn on aspect I think he is refering to is not necessary all the caching, but the precision. With an AOP, I can enable caching on just these methods of an interface. I don't think you get that level of precision with just the caching configuration file. Plus, our code using a basic framework of Struts/Spring/Hibernate with aspects for security and caching(and soon profiling and basic method level logging) and you can use the same basic framework, but depending on how the configuration file is set turn different things on or off.
    That's partly true. You do get more fine-tuned control on what methods your pointcuts apply to, but you still need to modify your code (either the aspect or the annotation, as I showed in the annotation approach), so it's still not completely dynamic.Nevertheless, it's an improvement over phrasing this as conditional code inside your business logic.-- Cedric
    If I want to add caching to all find* methods, I don't have to modify the code, just the configuration file. Ditto for all find* methods, but findDavid. These would all be configuration file changes.

    One thing, I just realized that I'm talking about using Spring.
  20. why not use a strategy object?[ Go to top ]

    One thing, I just realized that I'm talking about using Spring.
    Ah ok. Then yes, you are correct, such a change would be completely at runtime. AspectJ will require a recompilation of the aspect, though.

    --
    Cedric
  21. why not use a strategy object?[ Go to top ]

    One thing, I just realized that I'm talking about using Spring.
    Ah ok. Then yes, you are correct, such a change would be completely at runtime. AspectJ will require a recompilation of the aspect, though.-- Cedric

    Yes. Sorry for the confusion.
  22. AOP = "container functionality"?[ Go to top ]

    My view of AOP has, since I heard of it for the first time, been that of a simple and powerful strategy (its concrete implementations being the tools) for separating technical "aspects" from the business logic. Using this description, the presence or absence of an aspect shouldn't change the functionality in terms of business logic. Caching, I agree, is a good example of this, and there are arguably more, correspondingly the functionality a traditional J2EE contatiner provides - security, transactionality, remoting, etc.

    Does this view correspond with yours or would there be a situation where it would be appropriate, or even benificial, to implement business logic as aspects? What would the implications of such a strategy be?

    Then again, this article was a concrete example of applying AOP for caching, and my post has no other intentions than to try to place it in a context.

    /Par
  23. AOP = "container functionality"?[ Go to top ]

    Does this view correspond with yours or would there be a situation where it would be appropriate, or even benificial, to implement business logic as aspects?
    Well, I suppose it depends on how far you want to go, generally. If you're a "top-dipping" kind of person then I suppose using annotations and pre-packaged container aspects works quite well.

    Since we're in the deep-sea diving business we decided from the start to use aspects(/introductions) as our object model (i.e. NOT only behaviour), and then it becomes logical to add behavioural aspects on top of that. Specifically, if we use a an introduction X that has aggregated objects as part of its state, then we almost always have an XLifecycle advice that handles the creation/cloning/removal of those aggregated objects on lifecycle events. This works amazingly well, and it gives us a rapid way of creating new functionality by reusing old introductions and accompanying aspects/UI.
  24. I agree[ Go to top ]

    I have had this same thought since the first time I came across AOP. To me AOP is what J2EE designers (especially EJB designers) were trying to accomplish, but they ended up doing it in a clumsy way.
  25. Wanghy-Cache uses this approach to implement object caching in Spring. First it's an abstraction layer to multiple cache implementations. Second it use AOP to cache and flush method result based on method signature and parameters hash key. We are using it in combination with Spring JDBC support with very good result.

    http://wanghy.sourceforge.net/cache/index.html
  26. There were three points given as an explanation as to why AOP should be used for caching:
    * caching code is often duplicated throughout a web application

    The code to access a cached value or "proceed" to the underlying implementation via a CacheLoader if the value is missing from the cache is typically something like:

    value = cache.get(key);
    * it's not easy to turn caching on or off dynamically when it's part of your business logic

    It should be a one-line change to a configuration file.
    * caching logic does not provide any business functionality, it's not related to the domain of a business application

    This is true, but (see above) a cache access and "caching logic" are two different things.

    I do think that caching is a pretty obvious place for using AOP, but there are many better reasons that we could give for it, such as:

    * The ability to add caching to arbitrary points in an already-built application, perhaps based on profile data

    * The ability to compare the results of adding that caching to various points (before v. after)

    Peace,

    Cameron Purdy
    Tangosol, Inc.
    Coherence: Cluster your POJOs!
  27. The code to access a cached value or "proceed" to the underlying implementation via a CacheLoader if the value is missing from the cache is typically something like:value = cache.get(key);
    My template for this is more along the lines of:
    value=cache.get(key);
    if (value==null)
    {
      value=...
      cache.put(key,value)
    }
    return value;

    Not quite sure how your code template accomplishes what you describe. Unless you put all the other stuff in the "cache.get()" call itself, which would then be the same as putting it in an aspect, except "cache.get(key)" isn't transparent.

    Or what am I missing?
  28. My template for this is more along the lines of:
    value=cache.get(key);
    if (value==null)
    {
      value=...
      cache.put(key,value)
    }
    return value;

    Not quite sure how your code template accomplishes what you describe. Unless you put all the other stuff in the "cache.get()" call itself, which would then be the same as putting it in an aspect, except "cache.get(key)" isn't transparent.

    Or what am I missing?

    Hm... How do you handle concurrent changes?
    What if between 'value=....' and 'cache.put(key, value)' the value was changed by another thread? Would end up putting a stale value into cache?

    I would assume that if loading of data happened inside of cache.get(key) method, it would be handled for you automatically, based on cache implementation of course.

    --Dmitriy.
  29. My template for this is more along the lines of:value=cache.get(key);if (value==null){  value=...  cache.put(key,value)}return value;Not quite sure how your code template accomplishes what you describe. Unless you put all the other stuff in the "cache.get()" call itself, which would then be the same as putting it in an aspect, except "cache.get(key)" isn't transparent.Or what am I missing?
    Hm... How do you handle concurrent changes?What if between 'value=....' and 'cache.put(key, value)' the value was changed by another thread? Would end up putting a stale value into cache?I would assume that if loading of data happened inside of cache.get(key) method, it would be handled for you automatically, based on cache implementation of course.--Dmitriy.
    "Safe" cache implementation wrapps key and adds it with thread local "TxID", lock table can be used to solve this problem too. Cache is a kind of memory database, it must implement cuncurrency control itself.
  30. Spring AOP Cache[ Go to top ]

    There is an AOP Cache implementation available from the Spring wiki which uses AOP in Spring.

    The implementation uses reflection to determine how the arguments of a method can be uniquely identified (eg. book.getId()) and uses these as the key in the cache. The expiration time for each cached method can be configured in the Spring configuration.

    Several cache implementations like EHCache, OSCache, SwarmCache and a MemoryCache which all inherit from a common CacheInterceptor are implemented. Other implementations should be easy to add.

    http://opensource.atlassian.com/confluence/spring/display/DISC/AOP+Cache
  31. Spring AOP Cache[ Go to top ]

    Hi Pieter,

    This looks very similar to wanghy-cache but wanghy seams to have more features: attibute based cache, flush on execute, etc.
  32. Great article in general. ;-)

    Just want to point out that for stateful data caching, cache aspect via AOP can be a great idea. But if we need caching mainly for entity data purpose, a good persistence layer (like Hibernate) also offers cache configuration option that can optimize performance as well. And the odds are that for complicated entity access you will need persistance framework anyway.

    -Ben Wang
  33. Implementing Object Caching with AOP[ Go to top ]

    Ben, good point.

    - Do not cache data what maybe already has been cached (hibernate, oracle.. others??...)

    - Be carefull with storing data in mem (caching) vs. cloning/clustering applications.

    - Be carefull with storing statefull data elsewhere then the session context. Many enterprise app servers do replicate session data at runtime (websphere, weblogic?, jboss?); some dont. But the data you store in another context like the page, request or application context will not get replicated across the different clones.

    - Measure the performance differences between DB storage and caching in mem. If the first option is not acceptable look for alternate solutions (caching).

    Kind regards,

    Murat Dönmez
    Zarif ICT Solutions
  34. Implementing it differently[ Go to top ]

    I think a better way of implementaiton would be

    1. Let the original method getInterestRates(String prodGroup) always read from the cache.

    2. Aspect will make sure that before the method getInterestRates(..)execution starts data is loaded to cache(if not already there). This way Aspect can handle DB reads and other complexities.

    Any thoughts?