Tuesday, April 10, 2007

AOP-Aspect-oriented Programming

Why we need AOP

AOP lets the developer better separate tasks that should not be inextricably tangled in code like logging, Assigning login user id to Oracle Client Identifier, Exception handling etc.

What is AOP

Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure.

You can think of aspects as doing something around, before or after calls to groups of methods in your program.

Where can we use AOP

A great example is J2EE applications where you have to deal with all sorts of functionality that is really orthogonal to the business logic of your application (persistence, authorization, load balancing, transactions) but typically ends up mixed in to your code.

So you can avoid such code mixed up in your business logic code and the orthogonal feature like Logging can be used as aspect and it can be reused at different place (pointcuts) in your code.

Example

With out going too deep into any of the AOP terminology, let take a real time example and see how we can apply AOP using spring framework.

I was doing sample project to understand the JSF, spring and hibernate framework and I was using Oracle personal Express edition 10g.

Well, I slowly started the sample project and I had one of the requirement of auditing.

When ever user create a new row or updates row in database I have to track the date time and user id for that action.

I have database columns called create_dt_time, create_user_id, update_dt_time, update_user_id for this purpose.

Approach or options

One way to do this would be write code every where, where ever you have insert or update statement get the logged on user id and send to the insert or update sql statement as parameter and current date time as parameter.

Or if you are using Hibernate framework for your persistence, you can use the hibernate interceptor to write common logic to get the logged on user id and inject that to your domain object and Hibernate will help you to save or update that domain object.

Or the other way can be using AOP concept, which declarative and can be applied to all or some of the methods.

There can be many ways to solve/implement the above problem domain and right now I am not pointing the advantages or disadvantages of different approaches.

Right now our goal is to learn the AOP using spring framework.

Let's see how to implement this using spring AOP.

Aspect - Think of this as the general feature you want to apply globally to your application, in this example is our Auditing.

Advice - A chunk of code that is invoked during program execution, and is a piece of the logic for implementing your aspect. This is the first important piece of a Spring AOP aspect implementation, compare advice implementations to the decorator pattern.



Joinpoint - A place in the code where an advice should be executed. Spring's AOP only supports method invocation. So by default this is on method invocation.

Pointcut - A pointcut is a set of many joinpoints where an advice should be executed. Spring allows only method invocation, so a pointcut is just a set of methods that, when called, should have advices invoked around them.

This is defined in the configuration file (Example from applicationContext-hibernate.xml file)

Targets/Target Objects - The objects you want to apply an aspect, in this example to all bean names ending with Dao. In my sample project I have Dao which will do all the database related operations.

So the advice will be called on all Dao methods invocation and user login ID will be set to Oracle client identifier by our Adviser.

And we have written triggers in Oracle for insert and update operations, which will get the Client Identifier from Oracle and set to respective columns (create_dt_time, create_user_id, update_dt_time, update_user_id).



Example of my update trigger.



Conclusion

Our requirement for Auditing in this example was not business requirement and I have identified it as orthogonal feature.

After implementing this code, my business logic code is not mixed up with Auditing requirement code. There is clear separation of business and other requirements.

In this approach, my domain object do not have auditing columns, so my application there is no reference to auditing columns at all after implementing, a new developer can concentrate more on implementing business logic rather than writing or mixing up auditing code with business logic code.

Once we have written this simple code, even if new tables are added to my application, my code will not change and developer need not write code to implement the auditing feature.

This code is totally reusable and It is so less maintenance.

I'm looking forward to your feedback, questions, and comments.