AOP: Patching in the 21st Century

This article was originally published in VSJ, which is now part of Developer Fusion.
AOP is hot! AOP is cool! And after almost a decade of struggling to be noticed, Aspect Oriented Programming (or AOP for short) is finally approaching mainstream. Everyone else but you seems to be doing AOP. With so much action in both the academic and consulting worlds, AOP must be somehow relevant. It is time for us to put aside our conventional reservations, shed all our preconceptions and take a serious look at what aspiring young IT professionals will be doing to earn their bread for the next few decades.

In this article, an honest attempt will be made to answer the question – “What is AOP?”.

The answer may first surprise you, but it will ultimately inspire you. Using a single hands-on, “easy to understand and try” example, you will see for yourself how AOP actually works. Since the example scenario is a synopsis of modern software development, one that many of us encounter frequently, you will see how AOP may fit into your immediate and future plans.

Is AOP for you? You should be able to make an informed decision by the end of this article. But first, an AOP (if not AesOP) fable…

What IS AOP?

The foundation of AOP, much like the foundation of object-oriented programming when it first started out, is nothing radically new. It is something that software developers have been doing for decades – but never formalised.

Take yourself back to the day when you first started out in software development. Arriving at your new job, eager to apply structured top-down design (or formal object oriented analysis for younger readers) to the real world, you were disappointed to find very little enthusiasm for your new-found “expert” theories. Instead, the project seemed to be dealing with a very large body of existing legacy code, and the prevalent philosophy was “if it works, don’t touch it”. The all-star developer that you envisaged flying high and getting all the attention seems to be the one with the uncanny skill at dive-bombing into the multi-million lines of code and wrestling it into doing something new in an amazingly short period of time.

Yes, your competition – that annoying spaghetti code factory – is gaining favour with management! The most irritating part is that he/she doesn’t even seem to know or care about the difference between a DeMaco data flow diagram and a Yourdan structure chart.

That patch or that AOP artist is about to get yet another promotion while you linger another year in the trough of never-ending code churn.

Wait a minute, am I saying that AOP is code patching?! Sacrilege! Surely not?!

Read on, judge for yourself by following this familiar, yet hypothetical, situation.

An AOP Example: A common scenario in abstract

The hypothetical scenario takes place in the corporate headquarters of a large multi-national breakfast products company. The company decides to launch a national “Lucky Click” promotion, where the consumers of its product have a chance to win a handsome sum of money with every purchase.

They use a contract development firm to create a Lucky Click Java program. With every purchase of the breakfast product, the consumer receives a copy of the program. The Swing based Java program simply displays a “lucky” button to be clicked, shown in Figure 1.

Figure 1
Figure 1

When consumers click the button, they get a chance to win the prize. Typically, however, a “Please try again” dialog is displayed (Figure 2); and the consumer has to buy another box of the breakfast product.

Figure 2
Figure 2

The contract firm completes the code, which is audited by a reputable third party. The marketing department lines-up the TV, magazine, and newspaper advertising blitz, and the promotion is launched.

Success! Sales of the breakfast product are up several-fold.

But then, out of the blue, come rumours of potential class action lawsuits. For, you see, there appears to be no way of winning this Lucky Click prize – despite the hundreds of thousands of consumers clicking continuously on the little Java application.

Winning is not possible

You can try out the code for yourself, find it in the src directory of the code distribution in the VSJ code bin. It can be executed after a simple Java compile on the command line. You can use the jcompile.bat batch file to compile it, and run.bat to execute it.

After you get tired of seeing the “Sorry, try again soon” message, take a look at the code reproduced below (located in src/vsj/luckclick/LuckyClick.java in the code that can be downloaded from the VSJ code bin).

package vsj.luckclick;
import javax.swing.JFrame;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
/* @author SL VSJ 2005 */
public class LuckyClick extends JFrame {
	public LuckyClick(String title) {
		super(title);
	}
	StatusDialog dlgToShow;
	WinDialog wdlg;
	SorryDialog sdlg;
	public void init() {
		JButton button = new JButton(
			“Click to win instantly!”);
		wdlg = new WinDialog(this);
		sdlg = new SorryDialog(this);
		button.addActionListener(new
			ActionListener() {
			public void
				actionPerformed(
				ActionEvent e) {
				dlgToShow = sdlg;
				double randNum =
					Math.random();
				if (randNum == 1.0d)
					dlgToShow = wdlg;
				dlgToShow.showMsg();
				System.exit(0);
			}
		});
		this.addWindowListener(
			new WindowAdapter() {
			public void windowClosing(
				WindowEvent e) {
				System.exit(0);
			}
		});
		JPanel pane = new JPanel();
		pane.setBorder(
	BorderFactory.createEmptyBorder(
			30, 30, 10, 30));
		pane.add(button);
		this.getContentPane().add(pane);
	}
	public static void main(
		String[] args) {
		LuckyClick lc = new
			LuckyClick(“Win today!”);
		lc.init();
		lc.pack();
		lc.setVisible(true);
	}
	abstract class StatusDialog extends
		JOptionPane {
		protected Component par = null;
		public StatusDialog(
			Component parent) {
			super();
			par = parent;
		}
		public abstract void showMsg();
	}
	class SorryDialog extends
		StatusDialog {
		public SorryDialog(
			Component par) {
			super(par);
		}
		public void showMsg() {
			showMessageDialog(par,
				“Sorry, try again soon.”,
				“Please try again”,
			JOptionPane.PLAIN_MESSAGE);
		}
	}
	class WinDialog extends
		StatusDialog {
		public WinDialog(Component par) {
			super(par);
		}
		public void showMsg() {
			showMessageDialog(par,
				“You’ve won! The secret
				code is AF837.
				Call 888-8888 now!”,
				“You win!!”,
			JOptionPane.PLAIN_MESSAGE);
		}
	}
}
You can see in the listing above, that there exists indeed a WinDialog class that can display the winning message. In the init() method of the LuckyClick class, an instance of the WinDialog is created and stored as the wdlg field, and an instance of the SorryDialog is stored as the sdlg field. The programming logic uses a pseudo-random number to decide which of the two dialogs to show when the button is clicked. The flaw is in this logic:
double randNum = Math.random();
if (randNum == 1.0d)
	dlgToShow = wdlg;
A quick check of the javadoc for Math.random() reveals that it returns a pseudorandom number “greater than or equal to 0.0 and less than 1.0”.

Ooops!

Making Sure We Win

The code has been audited and copies distributed, there is no going back. In the haste and excitement of the promotion launch, nobody had made 100% sure that the Lucky Click prize could actually be won. To all the corporate administrators, sales, product management and marketing departments, the ability to win the contest was an orthogonal concern. It was simply not on their agenda.

To remedy the situation before rumours become reality, a fire-fighting expert panel of software consultants is called in, you and your all-star (former-competitor, now-boss) project leader are in on the gig.

“So, Sebastian, our valiant project leader, tell me where to patch this baby!” you utter with a challenging undertone.

The guru parts his lips, and the wisdom starts to flow, “Without changing a single line of the audited code, we need to monitor program execution for assignment to the dlgToShow field. Anytime this field is assigned with a value, we need to make sure that the assigned value is the wdlg instance. This will ensure a 100% win. Once we achieve that, we can modify our code to control the desired probability. Watson! Can you recapitulate in AOP-speak?”

Watson, the newly hired young chap who has just attained AOP mastery via a five-day intensive boot camp, declares triumphantly “Yes, Sebastian Sir! We need to create an aspect containing a field-set pointcut for dlgToShow. This pointcut should be advised by code that sets dlgToShow to wdlg initially; we can replace this advice with code that calculates the proper probability later. I can complete this assignment in thirty minutes without any assistance from the rest of the team”.

“Brilliant, Watson, excellent! See you in thirty!”, says the delighted project leader as he leads the assembled company down to the fancy coffee shop in the lobby.

Applying AOP

Let’s try to decipher what Watson said before our dinosaur pedigree is properly classified by the new recruits. The following table sums up our detective work:

Jargon, AOP Term Meaning
aspect A container of pointcut(s) and advice(s)
pointcut A way of specifying where and when to patch in code
advice Code to be executed – tied to a pointcut. This code also appears to have access to the context at which the pointcut occurs.

Examining Watson’s code, all our suspicions are confirmed. You can find the aspect code in winsrc/vsj/luckclick/Winning.aj in the code available from the VSJ code bin. It is reproduced here:

package vsj.luckclick;
public aspect Winning {
	pointcut makeWinnable(
		LuckyClick lc):
		set(LuckyClick.StatusDialog
			LuckyClick.dlgToShow)
			&& withincode(public void
			actionPerformed(*))
			&& target(lc);
	after(LuckyClick lc) :
		makeWinnable(lc) {
		if (lc.dlgToShow == lc.sdlg) {
			// if (Math.random() > 0.5d )
				lc.dlgToShow = lc.wdlg;
		}
	}
}
First, you will notice that the syntax is very similar to the Java programming language itself. This is a special attribute of the AOP framework that is used, in this case it is a popular framework called AspectJ. Let us analyse the code further.

Creating Aspects

Similar to a Java class, an aspect is declared using:
public aspect Winning {
... body of aspect ...
}
This aspect is also a physical part of the package, vsj.luckclick.

The body of the aspect can contain pointcuts and advices (and also other elements).

Selecting join points with Pointcut

So the basic premise is that you have some code that you would like to be executed (“patched in” in Jurassic lingo), sitting in an advice; but first you need to tell the runtime control when that code should be executed.

Well, in AOP, every possible time/location where your code can be triggered (advised) is called a join point. Every AOP framework has its own (unique) join point model. Typically, the potential set of join points is very large for any program, and a mechanism to select join points is required.

NOTE: A join point may also expose a context that can be accessed by the code in the advice.

With AspectJ, a pointcut is used to select join points. There is a large and rich set of built-in pointcuts, within AspectJ, that you can use (they are called primitive pointcuts). As you can imagine, you need something that is expressive enough to cater for all the situations under which you may want your advice to execute. For example, you may want execution when a certain method is called, or when a certain field is accessed, or when a certain type of object is created, and so on.

Back to the Winning aspect, and how it uses pointcut to select join points.

In the Winning aspect, there is only named pointcut defined:

pointcut makeWinnable(LuckyClick lc):
	set(LuckyClick.StatusDialog
	LuckyClick.dlgToShow)
	&& withincode(public void
	actionPerformed(*))
	&& target(lc);
The name of the pointcut is makeWinnable, it is actually a combination of three other primitive pointcuts. The three primitive pointcuts are combined using the boolean && operator, meaning that all of the specified pointcuts must match for makeWinnable.

The first pointcut is:

set(LuckyClick.StatusDialog
	LuckyClick.dlgToShow)
This pointcut selects the execution join points whenever the dlgToShow field is set to (assigned) some value. This will match any path of code execution where an assignment to the dlgToShow field of LuckyClick is performed during runtime. In the pointcut declaration, the field is specified as LuckyClick.dlgToShow, while the type of the field is specified LuckyClick.StatusDialog.

The second pointcut is:

withincode(public void
	actionPerformed(*))
Unlike the first, this pointcut is based on the lexical organisation (text) of the program, and not on any dynamic runtime behaviour. It will select all the join points within the code of actionPerformed() method.

Exposing context

The third pointcut is:
target(lc)
This pointcut is a state-based pointcut, and is used here to capture a context. Here the type of the identifier lc is not specified within the pointcut, but it is bound to a parameter on the left hand side of the pointcut declaration. The left side specifies the type of this lc parameter to be LuckyClick. When the field set pointcut (the first one) matches, the instance of LuckyClick will be matched by this pointcut and supplied to the advice via the lc parameter.

There are many other primitive pointcuts available in AspectJ, giving you infinite code-injection possibilities. You should explore the AspectJ documentation for more examples.

In summary, the makeWinnable pointcut will:

  • match all assignment operations to the dlgToShow field that are within the code of the actionPerformed() method
  • when the match occurs, the associated LuckyClick instance (at runtime) will be made available through the lc parameter of the pointcut
This gives us control whenever there is an assignment to the dlgToShow field.

Adding advice

An advice defines the code that is executed when the associated pointcut is matched. In this case, the advice is specified as:
after(LuckyClick lc) :
	makeWinnable(lc){
	if (lc.dlgToShow == lc.sdlg) {
		// if (Math.random() > 0.5d )
			lc.dlgToShow = lc.wdlg;
	}
}
On the left-hand side of an advice declaration, you can have before(), after(), after() returning, after() throwing, or around(). This specifies the execution of the advice with respect to the selected join point. For example, after() will execute the advice after the execution of the join point (see AspectJ documentation for more description).

On the right-hand side of the advice declaration is the pointcut that selects the join points for the advice. In this case, it is our old friend, makeWinnable. You can see here that the parameter, lc, is now passed to the advice. This provides the code in the advice with access to the runtime LuckyClick object instance.

The code in the advice checks and make sure that the dlgToShow field is always assigned with wdlg, enabling you to win 100% of the time. The code that is commented off can be uncommented and used to tune the eventual probability of winning.

Experiencing AOP

Time to experience AOP for yourself. There are several popular open-source AOP languages/frameworks available for Java developers. One of the best supported is AspectJ. Originally from Xerox’s Palo Alto Research Center (PARC), it is now part of the open-source Eclipse project.

Figure 3 shows the operational model of the AspectJ framework. When using AspectJ, you code your program to Java syntax. Aspects are defined using extended syntax provided by the AspectJ language extension, and placed into files with .aj extension.

Figure 3
Figure 3: The AspectJ framework

AspectJ comes with its own incremental Java compiler, ajc. It will compile both .java and .aj files. The resulting compiled bytecode will include the “weaved” aspects. Weaving refers to the bytecode manipulation that is necessary for pointcut matching and advice execution. During runtime, any compliant (JDK 1.4/JDK 5) Java VM can be used as long as the runtime library (aspectjrt.jar) is available in the JVM’s classpath.

Downloading and installing AspectJ

Download the latest copy of AspectJ. Click on the downloads link on the left sidebar. The latest stable version, at the time of writing, is 1.2.1. The distribution comes with an installer in a JAR file. You can start the installation by entering the following on the command line:
java -jar aspectj-1.2.1.jar
You will see the installer’s initial splash screen, as shown in Figure_4.

Figure 4
Figure 4

Follow the installer’s instructions to complete the installation. Remember to set your Java VM’s classpath to include the aspectjrt.jar (runtime support), and to add AspectJ’s bin directory to your PATH.

Compiling and testing the AspectJ application

AspectJ comes with its own incremental Java compiler, called apj. The following command line tells the apj compiler to read the list of files to compile from a file called luckyclick.lst:
apj @luckyclick.lst
You can use the above command, or run the compile.bat batch file to compile the LuckyClick.java file, and the Winning.aj file.

During the compilation, apj will “weave” the aspect’s code with the byte code of the LuckyClick class.

Finally, you can run the code using the run.bat batch file, or using the command line:

java vsj.luckclick.LuckyClick
At this time, if you click the button, it will always be showing the winning dialog! The Winning aspect is hard at work. This is shown in Figure_5.

Figure 5
Figure 5: The winning dialog

Now that you know what AOP is, and even have some idea of how to write AOP programs, it is an opportune time to ponder the value of AOP.

Why AOP?

The ability to win LuckyClick was an orthogonal concern to the marketing and sales department, as a result – it was not addressed in the initial code.

In AOP lingo, orthogonal concerns are called crosscutting concerns.

Crosscutting concerns

In software development, you are forced to deal with crosscutting concerns daily. Take logging, for example. When you write code that supports a system wide logging facility, you are forced intermix the code for logging throughout your business logic. In fact, logging is actually an orthogonal concern, and has little to do with the business logic that you are programming.

Another example of a crosscutting concern is the support for user authentication. Before AOP, you were forced to litter the calls to authentication methods within all software modules that requires authentication. The authentication calls themselves have nothing to do with the application logic within the modules.

There are many other generic examples of crosscutting concerns, including transaction management, monitoring, synchronisation, load balancing, persistence management, etc.

In any problem domain that you may be writing software for, you should be able to readily identify crosscutting concerns that result in intermixed code that is difficult to code and maintain.

Separation of concerns

AOP provide a modular foundation for you to separate crosscutting concerns.

It allows you to write code by focusing on the application logic, and not worry about the integration of multiple crosscutting concerns. The crosscutting concerns can be applied to the application logic subsequently, via AOP.

This separation of concerns is clearly beneficial. The most obvious benefit is the improved clarity and maintainability of the core application logic, unencumbered by orthogonal concerns.

A concrete example reveals another more subtle benefit. An authentication crosscutting concern is applied to a property management system. The company with the system is migrating from a simple *nix password system to a full-blown directory service. No change is required to the code of the property management system, since it contains zero linkage to any authentication library. Even for the authentication aspects, they require only minor changes in adapting to a new but similar implementation.

Towards a world of adaptive software systems

Similar to the early days of object-oriented design/programming, AOP is still in its infancy. The full potential that the technology brings to the table has not yet been fully explored, let alone realised. The road leads towards more adaptive and robust software systems, where the need for total-reconstruction is minimised and maintenance is simplified.

AOP may one day enable you to unobtrusively alter the ultimate behaviour of a software system, while preserving the robustness and correctness of the core logic.

You may remember in the early days, Pascal and C developers’ constant gripe: “I’ve coded and re-coded the bubble-sort algorithm for the millionth time”. Object-oriented programming and code reuse came along, and nowadays almost nobody codes raw sort algorithms anymore. Today’s popular complaint is “I’ve coded and recoded variations of (Enterprise Java) Beans to debit one account and credit another for the millionth time”. AOP has the potential of eliminating this need in the near future.

In the IT world of tomorrow, the day may arrive when system dependent coding can become a crosscutting concern. Instead of looking to outsource the porting of your ten million line codebase when moving from a legacy system to the latest and greatest platform – you may be able to modify a few aspects and have your massive codebase running on the new system in record time.

Imagine further down the road, applying AOP principles to an algorithm development language, where datatype is made a crosscutting concern. Using this language, you can design all sorts of algorithms, test and prove their correctness in isolation. When you need to use these algorithms for physical tasks, just apply the appropriate aspects.

The possibilities are limitless, and we’ve only barely scratched the surface.

Conclusions

Applying the separation of concerns principle, AOP enable developers to create application code that is unencumbered by orthogonal concerns. Crosscutting concerns are modularly encapsulated in aspects that can be applied later; modified and maintained separate from the core application logic.

There is a very thin line separating the dreamers and the realists in the continual evolution of software system design, and the development of AOP throughout the last decade has pushed that line over yet another notch.


Sing Li is a consultant, trainer and freelance writer specialising in Java, Windows NT and distributed object technologies. His most recent publication is Early Adopter JXTA: Peer-to-Peer Computing with Java from Wrox Press.

AspectJ’s Inter-type declarations

In addition to pointcuts and advices, an aspect declaration in AspectJ can also contain inter-type declarations. Inter-type declarations enable you to add members to existing types (i.e. classes). This allows the addition of fields, methods, and constructor to existing type. See AspectJ documentation for more details.

AOP Tools and Frameworks

Other popular AOP frameworks include:

You might also like...

Comments

About the author

Sing Li United States

Sing Li has been writing software, and writing about software for twenty plus years. His specialities include scalable distributed computing systems and peer-to-peer technologies. He now spends ...

Interested in writing for us? Find out more.

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Theory is when you know something, but it doesn't work. Practice is when something works, but you don't know why. Programmers combine theory and practice: Nothing works and they don't know why.”