Tuesday, December 04, 2007

Tracing MyFaces with AspectJ, Tomcat and Maven 2

When I started to learn Spring, I faced with AOP. It's new and interesting for me. It's really not easy to understand a new concept and to do some refactoring of my own brain while the most of documentation and books are in English (not my native language). There is not (almost) problem with English itself, but understanding a new concept is hard.

AOP is powerfull. Really. Relocating cross-cutting concerns to aspects is nice idea. Since I can intercept the methods executions of my own classes, I became very interested in how to trace any third-party libraries. In fact it's pretty cool to be able to see internals of MyFaces, Hibernate or whatever in action to get a deeper understanding what is going on behind the scene...

I found a wiki page about tracing MyFaces with AspectJ. Many thanks to Cagatay Civici for this article, really helpful. It is a starting point for my experiments. I'm using aspect source code from this article.

My environment is the following : JDK 1.5, Maven 2, Tomcat 5, MyFaces, AspectJ 1.5.


Cagatay restrict his article to
statically compiled AspectJ. But as you'll see later, runtime weaving on JDK 1.5 is not so hard to implement.

The first issue I came across is how to compile AspectJ aspect with Maven 2. Bingo ! There is a Maven plugin. So, placing some Trace.aj at src\main\java will work.

<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<configuration>
<outxml>true</outxml>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
Please note, that outxml=true. It's important since it is flag to "Generate aop.xml file for load-time weaving with default name.(/META-INF/aop.xml)".

The final part of config is agent setup for Tomcat. According to docs it's should be started with one additional JVM argument - javaagent.

Now we have tracing aspect, can compile it with Maven and know how to start Tomcat with right option. As for me, I like Cargo plugin. It is useful for integration testing for example, but in this case it is just a very nice Maven 2 plugin to put all together. With this config we can automatically download tomcat 5 distribution, unpack it, run tomcat with our -javaagent option
and deploy war. A lot of work, huh ? :)

<plugin>
<groupId>org.codehaus.cargo</groupId>
<artifactId>cargo-maven2-plugin</artifactId>
<configuration>
<container>
<containerId>tomcat5x</containerId>
<zipUrlInstaller>
<url>
http://www.eu.apache.org/dist
/tomcat/tomcat-5/v5.5.25/bin/apache-tomcat-5.5.25.zip
</url>
<installDir>
${java.io.tmpdir}/donloadedByCargo
</installDir>
</zipUrlInstaller>
<output>
${project.build.directory}
/tomcat5x.logs/container.log
</output>
<append>false</append>
<log>
${project.build.directory}
/tomcat5x.logs/cargo.log
</log>
</container>
<configuration>
<type>standalone</type>
<home>
${project.build.directory}/tomcat5x
</home>
<properties>
<cargo.servlet.port>
8080
</cargo.servlet.port>
<cargo.jvmargs>
-javaagent:"${user.home}\.m2\repository
\aspectj\aspectjweaver\1.5.3\aspectjweaver-1.5.3.jar"
</cargo.jvmargs>
<cargo.logging>high</cargo.logging>
</properties>
<deployables>
<deployable>
<groupId>com.mycoolcompany.fun</groupId>
<artifactId>MyFacesAspectJ</artifactId>
<type>war</type>
<properties>
<context>MyFacesAspectJ</context>
</properties>
</deployable>
</deployables>
</configuration>
</configuration>
</plugin>
As you can see, cargo.jvmargs element contains a path to aspectjweaver-1.5.3.jar library, in my case it is in my local repository already. After all to see it in action just type "mvn clean package cargo:start" and you are ready to go !

Trace will be available in the file "C:\trace.out" as defined in aspect source code. Exploring it's contents is another story, I guess.