Compile-time architecture enforcement revisited: AspectJ, Maven and Eclipse

It has been a while since we first heard about compile-time checks with AspectJ at the Java Server Symposium in 2007. Since then we have been using and experimenting with this feature of AOP and AspectJ, and more recently we have used this technology to implement architecture enforcment rules for some of our clients.

In this more technical post we revisit the concepts, how to create Aspects, and more importantly, how we integrate the aspect libraries with Maven and Eclipse via AspectJTools, creating an easy to maintain and usable environment.

We apply an agile approach in most of our projects, so what we describe here allow us to automate and integrate the architecture enforcement rules into our continuous integration environment using maven, meaning that we can fail a build that does not meet our architecture rules.

Depending on project’s nature, the enforcement rules may vary but they normally fall into some or all of these categories:

  • Rules to enforce application architecture and layering
  • Rules to enforce good practices like:
    • Usage of utility libraries against direct data manipulations
    • Exception handling
    • Proper logging against dumps to console
  • Avoid usage of already know problematic libraries

The ideal way to put all of this to work is to organise the defined rules in different libraries, so we can reuse them based on the type of project we are currently working on. Moreover, how can we setup maven projects/archetypes and Eclipse to use the configured environment automatically?

Preparing the rules libraries:

  1. Creation of maven project and codification of the rules in AspectJ aspects.
  2. Compile and archive the rules libraries.

Setup of the development environment:

  1. Configuring maven projects or archetypes that make use of the rules libraries.
  2. Automatically configure AspectJ Tools for Eclipse.

Let’s start on how we can create AspectJ aspects libraries to code the enforcing rules.

Preparing the rules libraries:

  • Create a maven project using a standard archetype:
$mvn archetype:create –DgroupId=com.tsl.common –DartifactId=lib-aoprules-enforce

We need to add the following the dependencies for AspectJ libraries and the aspectj-maven-plugin to the generated pom.xml in order to enable the compilation of AspectJ aspects. Te final pom.xml is given below:

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                                   http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.tsl.common</groupId>
	<artifactId>lib-aoprules-enforce</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>lib-aoprules-enforce</name>
	<url>http://maven.apache.org</url>
	<dependencies>
	   <dependency>
		<groupId>org.aspectj</groupId>
		<artifactId>aspectjrt</artifactId>
		<version>1.5.4</version>
	   </dependency>
	</dependencies>
	<build>
	   <plugins>
	      <plugin>
		   <groupId>org.apache.maven.plugins</groupId>
		   <artifactId>maven-eclipse-plugin</artifactId>
		   <version>2.6-SNAPSHOT</version>
	      </plugin>
	      <plugin>
		  <groupId>org.codehaus.mojo</groupId>
		  <artifactId>aspectj-maven-plugin</artifactId>
		  <executions>
			<execution>
				<goals>
					<goal>compile</goal>
				</goals>
			</execution>
		  </executions>
	      </plugin>
	  </plugins>
	</build>
	<pluginRepositories>
           <pluginRepository>
  		<id>apache.snapshots</id>
		<name>Apache Snapshot Repository</name>
		<url>
			http://people.apache.org/maven-snapshot-repository
		</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
		<releases>
			<enabled>false</enabled>
		</releases>
          </pluginRepository>
       </pluginRepositories>
</project>

Additionally, we have added another specific entry for the maven-eclipse-plugin. Why? Well, the current version of maven-eclipse-plugin (2.5.1) does not generate any configuration parameters to configure AspectJTools for Eclipse, i.e. project nature in “.project” file and AspectJ classpath in “.classpath” file.

A few days ago, the enhancement was added to the 2.6 snapshot version and works perfectly.

This allows us to use the maven-eclipse-plugin goal eclipse:eclipse to generate all necessary aspectj tools classpath variables and project natures.
You can download the snapshot from the apache repository and include it into your maven repo (see the plugin-repository definition in pom.xml).

So, let´s execute mvn eclipse:eclipse in the project directory and import the project into Eclipse (I´m asumming the M2_REPO classpath variable is already configured in your Eclipse environment and the AspectJTools pluging for Eclipse has been installed). Note how the AspectJ nature is already enabled. Later, when we want to make use of the libraries, we will see that the enhancement has another feature to make life easier.

Now, we can create a new aspect called “EnforceLogging.aj” in Eclipse. This aspect codifies a rule that will detect and generate a compilation warning of all calls that print to console outside TestCase classes, considering that our unit test framework is Junit:

package com.tsl.enforcement.aspects;
 
import junit.framework.*;
 
public aspect EnforceLogging {
 
	pointcut scope():
		within(com.tsl..*) && !within(TestCase+);
 
	pointcut printing(): 
		get(* System.out) || get(* System.err) || call(* printStackTrace());
 
	declare warning
		: scope() && printing()
		: "Don't print to Console, use logger";
 
}

As we are using Junit libraries in our aspects we need to add it as a dependency to the maven pom.

With this configuration, we can easily build now our first rules library and deploy it in our repository with mvn install.

Setup of development environment:

Let’s see how a new project will be created and how it will use those rules libraries.
As we use maven, the integration is pretty simple and will ensure that our continuous integration system will detect builds that break the configured rules.

In the past, we would have to manually configure the AspectJTools plugin in Eclipse to work with our project – which can be very annoying.

As mentioned previously, now with the 2.6 version of the maven-eclipse-plugin, we can integrate everything in a transparent way to the developer, so they can start coding in Eclipse without worrying about AspectJ details.

We normally have a maven archetype defined with the required configuration to enable aspectj and the libraries we want to be included, so the development team will create a new project with all the desired enforcement rules straight away.

For this example, a project pom.xml from which the archetype could be generated should include at least:

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
				http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.tsl.common</groupId>
	<artifactId>enforcement-test</artifactId>
	<packaging>jar</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>enforcement-test</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>com.tsl.common</groupId>
			<artifactId>lib-aoprules-enforce</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>1.5.4</version>
		</dependency>
	</dependencies>
	<build>
	   <plugins>
	      <plugin>
		<groupId>org.apache.maven.plugins</groupId>
		<artifactId>maven-eclipse-plugin</artifactId>
		<version>2.6-SNAPSHOT</version>
	      </plugin>
	      <plugin>
		<groupId>org.codehaus.mojo</groupId>
		<artifactId>aspectj-maven-plugin</artifactId>
		<configuration>
			<aspectLibraries>
				<aspectLibrary>
					<groupId>
						com.tsl.common
					</groupId>
					<artifactId>
						lib-aoprules-enforce
					</artifactId>
				</aspectLibrary>
			</aspectLibraries>
		</configuration>
 
 
		<executions>
			<execution>
				<goals>
					<goal>compile</goal>
				</goals>
			</execution>
		</executions>
	      </plugin>
          </plugins>
	</build>
	<pluginRepositories>
           <pluginRepository>
  		<id>apache.snapshots</id>
		<name>Apache Snapshot Repository</name>
		<url>
			http://people.apache.org/maven-snapshot-repository
		</url>
		<snapshots>
			<enabled>true</enabled>
		</snapshots>
		<releases>
			<enabled>false</enabled>
		</releases>
          </pluginRepository>
       </pluginRepositories>
</project>

The dependencies must include the aspects library or libraries together with the aspectj runtime library. In the other hand, the aspectj-maven-plugin configuration must include those libraries when weaving.

Now, if we execute mvn eclipse:eclipse and import the project in Eclipse we can create an example class that violates the defined rule, verifying that we get compile errors:

AspectJ compile-time checks in eclipse

Note that the AspectJ Libraries have been atuomatically configured for us in “Referenced Libraries”.

That´s it, with this setup we can define an easy to use and easy to maintain architecture/best practices enforcement for all our projects.

Consider that this is a simple example and depending on the environment you might want to setup different profiles to activate these compile-time checks at development time and avoid dragging the aspectjrt library into production builds. We normally use it for our development and integration builds, while disabling it for the production builds.

Some additional things to consider:

  • As Olivier mentions in his blog entry, there are some cases (e.g. two maven compile executions without changes in the source or configuration) where the aspectj compilation is not performed and therefore errors/warnings might be bypassed. There was an enhancement request but I haven’t seen it included in any release or snapshots. In the end, it is not a major problem, it does not affect the development environment with Eclipse, and we normally enforce a mvn clean in our continuous integration which gets around the problem.
  • The aspect libraries must be generated with the same compiler than later is used to weave the classes.

4 Comments on “Compile-time architecture enforcement revisited: AspectJ, Maven and Eclipse”

  1. #1 Sanjay Acharya
    on Apr 19th, 2009 at 5:04 am

    Very nice blog post. Thanks much for the excellent explanation.

  2. #2 sandrar
    on Sep 10th, 2009 at 2:52 pm

    Hi! I was surfing and found your blog post… nice! I love your blog. :) Cheers! Sandra. R.

  3. #3 Krish
    on Aug 4th, 2010 at 9:50 pm

    I was able to get it working with maven, but with ant it fails…not the expected output, doesn’t seem to do anything..I think i’ve messed up with aj5. Thanks for the post.

  4. #4 Jan
    on Mar 31st, 2011 at 1:48 pm

    i’m planning to create a similar process in our organisation, ie develop some aspects to enforce correct coding.

    Are there more examples available or maybe an opensource project which has some ready to use aspects allready?

    I would hate to reinvent the wheel..

Leave a Comment