http://www.developer.com/java/aspectj-benefits-for-java-development.html

Back to article

5 Reasons Java Developers Should Learn and Use AspectJ


April 27, 2011

Aspect-Oriented Programming (AOP) is a programming paradigm which focuses on modularizing system-level concerns (like logging, transaction management, security, performance monitoring, etc.) in the applications. In AOP language, these system-level concerns are called "crosscutting concerns" because they crosscut all the layers of the application.

AspectJ, a compatible extension to the Java programming language, is one implementation of AOP. AspectJ is very widely used in a lot of Java frameworks (like Spring), but still most developers do not know AspectJ. Developers often think that AspectJ is difficult to learn or it makes your code complex, and they decide not to learn this very powerful and useful technology. In this article, I will write down five reasons why I think Java developer should learn and use AspectJ.

AspectJ Is Easy to Learn

AspectJ is not difficult to learn. It has three core concepts: Join point, Pointcut, and Advice. Join points are the points in the execution of a program where you need to apply the cross cutting behavior. For example, execution of a method, call to a method or a field access are all valid join points. Pointcut allows developers to write expressions to select join points of interest and capture the join point context information. Advice allows a developer to execute some code at the join points selected by pointcut. AspectJ concepts are 3Ws--where (Join point), which (Pointcut), and what (Advice).

Let's use an example to make it clearer. Consider a scenario where you have to validate that argument to a method is not null. Without AOP you will do a null check in all the methods of interest and will throw an exception if the argument is null.

public class MyService {

public void process(ProcessRequest request){
if(request == null){
throw new IllegalArgumentException("Request can not be null");
}
// proceed forward
}
}

In the code shown above, we are validating that request should not be null before processing the request. If the request is null, we throw IllegalArgumentException. I can remove the validation logic from this class and move it a Validator class, but still I would have to make a call to validator class. You could have ten such classes where you are just doing null validation. So null validation is a crosscutting concern, which can be better implemented using AspectJ. The Join point is in the MyService class process method because it is the place where we would like to do validation (applying advice).

Now let's write an aspect that would declare a pointcut for selecting the process method and an advice that will do the validation before the join point is executed.

public aspect NullValidationAspect { // 1

pointcut validate(ProcessRequest request) : execution(public void MyService.process(ProcessRequest)) && args(request); //2

before(ProcessRequest request) : validate(request) { //3
if(request == null){
throw new IllegalArgumentException("Request can not be null");
}
}
}

Let's talk about the aspect shown above.

  1. Line 1 corresponds to an Aspect declaration. The aspect keyword specifies that the construct is an Aspect.
  2. Line 2 specifies a pointcut. The pointcut construct specifies the name of the pointcut (i.e. validate, a pointcut expression to select the validate method such as execution (public void MyService.process(ProcessRequest), and an args() construct to capture the method arguments). The pointcut expression language is very rich and selects a variety of join points like call to a method, call or execution of a constructor, object initialization, static initialization. Please refer to AspectJ documentation for more information.
  3. Line 3 refers to a before advice. A before advice runs before the join point execution. There are other types of advices also, such as after advice, which runs after the execution of join point code, around advice which surrounds the join point so you can do processing before and after the endpoint. In the advice, we will throw exception if the capture argument (i.e. ProcessRequest) is null.

I have given a very small and easy introduction to AspectJ here. If you can learn these concepts, then you can very easily use AspectJ in your projects. You can learn about other features of AspectJ like static crosscutting, advance pointcut expressions, etc. as you become comfortable working with AspectJ. I think once you start using basic features of AspectJ it will become very easy and natural to use advanced features. The purpose of this article is not to help you build applications using AspectJ, but to motivate you to learn AspectJ.

Another thing that makes learning AspectJ very easy is a great book--AspectJ in Action. This book teaches you how to think in aspects and shows how you can solve real life problems with AspectJ. It is a must buy if you want to learn AspectJ.

AspectJ Provides a Standard Mechanism to Handle a Crosscutting Concern

In the example shown above, we are doing a null validation and throwing an IllegalArgumentException when the request is null. This way we make sure that whenever an argument is null, we get the same uniform behavior. This leads to uniformity in your application code and prevents bugs from creeping into the application. It eliminates the chance of missing the validation and throwing another exception. The advantage of having a uniform way become more apparent when you are handling a crosscutting concern like Exception Handling. Having the exception handling code in the aspect makes your business logic cleaner and prevents developers from doing it differently or missing it.

AspectJ Offers Another Way to Look at Problems

Some time back, I wrote a piece of code which made a connection with a Web service and made a retry attempt if an exception was thrown.

public class MyService {

private WebService webService;

private final int NUMBER_OF_RETRIES = 5;

public List process(ProcessRequest request) {
int retryCount = 0;
return fetchResult(retryCount);
}

private List fetchResult(int retryCount) {
List result = null;
try {
result = webService.find();
} catch (WebServiceConnectionException e) {
System.out.println("Exception" + e);
if (++retryCount > NUMBER_OF_RETRIES) {
throw e;
}
System.out.println("Retrying…");
fetchResult(retryCount);
}
return result;
}

}

The pseudo code shown above makes a retry attempt if WebServiceConnectionException is thrown. It makes five retries, and after that it throws the exception. Retrying a network failure or Web service call is a very common problem, and most of the times it gets mixed with the business logic because developers do not find a way to separate the core business concern from the concern like a connection retry. Knowing AspectJ gives you another way to look at the problem and helps to avoid the code coupling between different concerns. As shown below we can write a simple Retry aspect, which can do the work for us, and we can use it at other places also.

public aspect RetryAspect {

private final int NUMBER_OF_RETRIES = 5;

pointcut retry() : call(public * *(..) throws com.developer.aspectj.part1.WebServiceConnectionException);

Object around() : retry() {
int retryCount = 0;
while (true) {
try {
return proceed();
} catch (WebServiceConnectionException e) {
System.out.println("Exception" + e);
if (++retryCount > NUMBER_OF_RETRIES) {
throw e;
}
System.out.println("Retrying…");
}
}
}

}

AspectJ Leads to Clean Code

If you have followed the article until now, you also have realized that AspectJ does not make code complex; rather, it simplifies your code and makes it cleaner. I think the code becomes more maintainable and easier to understand. AOP tries to reduce code scattering and code tangling. Code is tangled when its crosscutting concern code is intermixed with code that implements other concerns, and code is scattered when crosscutting code is spread out over multiple modules. Code scattering and tangling makes code difficult to maintain and evolve. Learning AOP will help you make your code more modular.

AspectJ Is Powerful, Mature, and Used in a Lot of Frameworks

AspectJ is not a new technology trend, as it has existed for more than 10 years. AspectJ is very mature, powerful and widely used in today's enterprise Java frameworks like Spring. Spring uses AspectJ to make it easy for the developers to use Transaction Management, or applying security (using Spring Security) in your application. Most Java developers use Spring or other frameworks that support AspectJ, but they do not know much about AspectJ. Knowing AspectJ will not only help in understanding how Spring framework uses AspectJ, but it can also help developers modularize the cross-cutting concerns specific to their application.

AspectJ is also used in a lot of other application frameworks (e.g. Spring Roo, Magma, and contract4j), monitoring tools (perf4j and glassbox), application servers (SpringSource dm server), and so on. If you know AspectJ, you can very easily understand the new frameworks which are using AspectJ and use them more effectively. For example, Spring Roo is a RAD tool that helps you build applications by generating code against the commands fired on the Roo shell. In Spring Roo, code generation artifacts are ITDs ("inter type declarations"), an AspectJ feature that provides static crosscutting. Static crosscutting means that it can change the structure of a class at compile time. It lets you add to your classes at compile time. So all the code is generated in ITDs, and at compile time that code is weaved into the target class. Hence, it helps in keeping generated artifacts away from the code that developer will change.

Shekhar Gulati -- Contributing Editor, Java -- is a Java consultant with over 5 years experience. He currently works with Xebia India, an Agile Software Development company. The opinions in this article and on his blog are his own and do not necessarily represent the opinions of his employer. His own blog is at and you can follow him on twitter here.

Sitemap | Contact Us