Weaving Maven

Fri, 26/09/2008 - 18:23

We're trying to clean up our services at present, and as such are keen on investigating the @Configurable annotation for Spring 2.5. For those who aren't in the know, this uses aspects to allow Spring to configure new instances of an annotated class, allowing dependencies to magically appear in your new object, no factories required.

Black magic? Perhaps. Time will tell. But first we had to get it set up anyway.

In theory, this is simple. You have two choices: runtime or compile-time weaving. Compile-time means changing your build scripts. Runtime means either using a compliant classloader (WLS, for instance) or changing your JVM parameters (nasty for deployment). Given our lack of desire for deployment pain compile-time seemed the obvious choice.

As always, there was a Maven plug-in. As always, it didn't work. At least not with Spring 2.5.4. It turns out that Spring 2.5.4 broke compatibility with AspectJ 1.5.4. Worse, Spring's POMs were broken and it still depended on this incompatible version. So, task one: upgrade to Spring 2.5.5.

Secondly, the Maven plug-in still broke. So, check it out, change the version number and the AspectJ version, compile & upload to our internal repository. Task two: hack the Maven plug-in. I have a growing suspicion that this is a standard part of the Maven workflow.

Now, the easy bit - configure your POM. Except the examples need a bit of tweaking, not least because Java 5 is now old hat. Try the following:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.6.0</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>2.5.5</version>
</dependency>

And:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.0-st</version>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <source>1.5</source>
        <target>1.5</target>

        <showWeaveInfo>true</showWeaveInfo>
        <verbose>true</verbose>
        <proceedOnError>false</proceedOnError>

        <weaveDependencies>
            <weaveDependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </weaveDependency>
        </weaveDependencies>

        <aspectLibrarys>
            <aspectLibrary>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aspects</artifactId>
            </aspectLibrary>
        </aspectLibrarys>
    </configuration>
</plugin>

Change the plug-in version number as required, of course.

Finally, step four: pimp your application. You'll need the following in your Spring configuration:

<context:spring-configured/>

Right, after all that you can start the @Configurable love. Create your bean:

package com.signtechno.example;

@Configurable
public class DummyBean {
    private int value;

    public void setValue(final int value) {
        this.value = value;
    }

    public int getValue() {
        return value;
    }
}

Create a Spring prototype:

<bean class=“com.signtechno.example.Dummy” scope=“prototype”>
    <property name=“value” value=“17”/>
</bean>

Create your logic:

final DummyBean dummyBean = new DummyBean();

And voila, dummyBean.getValue() == 17. Wasn't that easy?

in fact, if you

Submitted by Anonymous (not verified) on Tue, 30/09/2008 - 14:35.
in fact, if you pop @Configurable(autowire=Autowire.BY_NAME) instead of the simple @Configurable annotation, it will automatically get the bean you're after and so you don't need the spring prototype! even easier.