Friday 27 July 2012

Weaving aspects with AspectJ in Maven

First of all welcome at my PL memos, blog. I haven't been blogging for a while and this blog is a simplistic way, to note down something that matters/mattered to me.

Today I tried to build an open source project (and while not important, the project is an SOS service deployed into tomcat), with the AspectJ maven plugin, in order to weave some aspects. I needed to hook certain functionality into an open source project while avoiding cut-pasting code upon each svn update of any upcoming new revision (not even resolving conflicts via the svn tooling). I wanted a clean solution, developed and maintained independently. However there were some minor difficulties through the process, specially for developers without strong know how with the maven build tool, like me.

The SOS service, came as a single maven aggregation project with various modules. I couldn't declare the aspectj compiler plugin there. If you do that you are going to get a "Not executing aspectJ compiler as the project is not a Java classpath-capable package" warning. My attempts to find adequate information around the web, resulted in solutions referring to the version number of source/target. While looking in mailing lists, every reference of this error (like this so), was paired with a "bad version number found in ..." warning. Unfortunately I was getting only the "Not executing aspectJ compiler.." warning, so I couldn't find what was going on, until I checked the if-expression from within the aspectj plugin. This helped me to understand that this had something to do with an entity called ArtifactHandler. Only then I found out the solution. Define the aspect j plugin only to children poms. The next step, after a lot of experimentation concluded in adding the following section at the pom.xml that interested me:


Now you must only see --- aspectj-maven-plugin:1.4:compile (default) @ <project name> --- followed by no warnings or errors. The next step is to drag and drop already developed aspects and place them at the default directory for the aspectj plugin to look into: src/main/aspect. For my proof of concept I coded a simple join point to intercept a specific call (not important but it is a certain listener).

What you expect to see at this point under the --- ... --- message is an info log entry like that:
[INFO] --- aspectj-maven-plugin:1.4:compile (default) @ 52n-sos-core ---
[INFO] Join point 'method-execution(org.n52.sos.resp.ISosResponse org.n52.sos.InsertObservationListener.receiveRequest(org.n52.sos.request.AbstractSosRequest))' in Type 'org.n52.sos.InsertObservationListener' (InsertObservationListener.java:103) advised by around advice from 'InterceptInsertCalls' (InterceptInsertCalls.aj:8) [with runtime test]
Any error messages, any unmatched advices are going to be reported in the maven build output. Finally, assuming that you target a web-app, a war file is packaged and ready to be deployed. This simple case enabled me to weave sample code that appends an incremented string in the log file tomcat7-stdout.2012-07-26.log, when someone posted observations messages to the service.
What we achieved? We patched an open source project, avoiding to mess with the code and isolated the additional functionality into an independent development life-cycle.