« Adopting AOP, and AspectJ 5 talks | Main | Nick Lesiecki : Experiences using AspectJ at VMS »
March 16, 2005
AOP with Metadata: principles and practices (Ramnivas Laddad)
Why do we need AOP and metadata? Today we have signature based pointcuts. These exploit inherent information associated with the signature. This works well in many cases. However, metadata based pointcuts also enable us to leverage metadata at matched join points. Useful for transaction management, security etc.
Ramnivas is showing transaction management implemented without aspects at all - inlined class to JTA. Now he is showing how aspects can remove all of the tx logic from the business class. The first implementation uses around advice to "transactedOps()". The around advice has the familiar try-catch-finally block. But how do you write the pointcut? One solution is to enumerate all of the matching signatures - but how do we know what they will be?
Current solution:- create an abstract aspect and make the transactedOps pointcut abstract - now you can define it in (eg.) a Banking specific aspect. It would look like:
public pointcut transactedOps() : execution(* Bank.credit(..)) || ...;
With annotations we can write:
pointcut transactedOps() : @annotation(Transactional);
(AMC note ... I would have added && execution(* *(..)) to the above to limit matching to method execution join points.)
And now you annotate each method that needs tx support with the @Transactional annotation.
If you need to add security (say) you just add another annotation: @Authorized. Ramnivas is making a nice analogy: annotations are playing the role of additional method "signatures" in alternate dimensions (the @Transactional annotation is the method signature in the transaction dimension, the @Authorized annotation is the method signature in the security dimension and so on. Recall that annotations can have values etc. Rather than calling them "dimensions" I might call them "domains" - so a method has a signature in the business domain, the transaction domain etc..
When you think of it like this, the Account class looks as follows in the transaction domain (dimension):
public class Account { @Transactional * credit(..) @Transactional * debit(..) .. }
Onto best practices...
Metadata is an easy way to capture crosscutting concerns - just sprinkle some annotations around. It limits the collaboration between aspects and classes to just annotations. Downside is that collaboration from classes is needed. It's clearly nonsense to use annotations on every method for say logging :).
Guideline: don't use annotations when you can do without them. Eg. you want to capture all RMI operations. You can write a simple, stable pointcut: execution(* Remote+.*(..) throws RemoteException) - no need for an annotation here. Likewise you can write a stable pointcut for all thread-safe calls to the Swing library - you don't need annotations for this either.
Not sure if Ramnivas is going to mention this, but there are also expressibility limitations with annotations - you can't say for example "all calls to x within y" since you can't annotate calls (you can say "all calls to a method with an annotation X made within y" - but that's a slightly different thing). There are other examples too...
A second guideline from Ramnivas: employ aspect inheritance to defer pointcut specification to a sub-aspect. Now write one pointcut per "subsystem" this will be much easier than trying to write a single global pointcut that works across the whole system.
A third guideline - make use of existing annotation types - eg. EJB
A fourth guideline - if you create annotation types, use names that describe a property of the annotated element, not an instruction to some processor. Eg. @ReadOnly, not @ReadLock, use @Idempotent, not @RetryOnFailure, and so on.
A final guideline - wisdom comes with experience: start with something and refactor as you go along.
Ramnivas is now discussing whether metadata-fortified AOP harms "obliviousness". His argument is that it does not if the guidelines are followed.
The final flourish in Ramnivas' talk. You could have an aspect that matches on annotated methods... if you don't want to annotate them individually, you can use an inner aspect (participant pattern) to declare them...
Posted by adrian at March 16, 2005 10:19 PM [permalink]
Comments
Hi There,
Is there a way to take a neat printout of this blog ?
thank you,
BR,
~A
Posted by: Anjan Bacchu at March 22, 2005 03:15 AM
The easiest way would be to use one of the many RSS readers to view the entries, and then print direct from there. That way you'll get the articles themselves but without all the surrounding gumf from the website. I might look into changing the template to add a "printable version" link against entries as its a reasonable requirement - but that will have no wait until I'm next hacking the site scripts....
Posted by: Adrian Colyer at March 22, 2005 02:30 PM
Post a comment
Thanks for signing in, . Now you can comment. (sign out)
(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)