How to use AspectJ to check your code in combination with maven2?
A couple a weeks ago me and some colleagues took a two day course in AOP. The course was given by the excellent teacher Adrian Colyer. In this short blog I want to show you a very nice (not well known) feature of AspectJ and how you can integrate AspectJ in your build using the maven2 plugin.
When you want to play around with AspectJ the first thing you should do is install the AspectJ eclipse plugin. With this plugin you can enable AspectJ support for your project.
Often the use of aspects, beside the obvious usages like security, transactions, and tracing, is frowned upon: too complex, too difficult and where is the world going to. Conservatists! I was one of those people, but in the course Adrian showed us some good real-world usecases where aspects can improve your code. I'll show you one example (and I hope Adrian won't mind me using some of his code).
I don't like code like this:
//do Something
System.out.println("Something happened");
Everyone will agree that it is far better to use a logging framework to inform people that something happened.
//do Something
if (log.isDebugEnabled()) {
log.debug("Something happened");
}
But when doing audits/working on projects I almost always encounter the 'System.out' anti-pattern. With AspectJ it is very easy to write an aspect that checks during the build if the code tries to write messages to the console.
/**
* @author Adrian Colyer
*/
public aspect DontWriteToTheConsole {
pointcut sysOutOrErrAccess() : get(* System.out) || get(* System.err);
declare error
: sysOutOrErrAccess()
: "Don't write to the console";
}
The above pointcut expression detects all attempts to access the public property 'out' of the 'System' class and generates a compile error (it would probably be better to declare a warning in this specific case, but this is just an example). When you want to check all of your code simply put the aspect in your codebase and add the following dependency to your maven2 pom.xml:
<dependency>
<groupId>aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.5.2a</version>
</dependency>
The next thing you want to do is add the aspectj-maven-plugin to the build section of your pom.xml:
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>compile</goal><!-- use this goal to weave all your main classes -->
<goal>test-compile</goal><!-- use this goal to weave all your test classes -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
Now when your build your project
$ mvn clean install
the build breaks when you write "Hello World" to the console:
[INFO] ------------------------------------------------------------------------
[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Compiler errors :
error at System.out.println("Hello World!");
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
E:\workspace\play-time\src\main\java\org\harsta\HelloWorld.java:9:0::0 Don't write to the console
see also: E:\workspace\play-time\src\main\java\org\harsta\DontWriteToTheConsole.aj:18::0
The example is simple, but there are a lot more ways to check if your code is 'clean'. You could even write a maven2 profile that enables the weaving process only under some circumstances (like the presence of an environment variable).
If you want to read more about AspectJ in combination with Spring 2.0 this article is a good starting point.
Filed under Java | 1 Comment »
Nice! I would be interested in seeing an example of reusing aspects from external libraries. I suspect it will not be all that hard, and that would really (!) be the ideal way of enforcing some common guidelines across the organization.