Friday Sep 19, 2008

Running Findbugs with Ant Tasks for Maven

We have been using Findbugs for quite a while now to help us find and squash bugs before they can do any harm. It is an excellent tool. Findbugs is directly integrated into our Ant build scripts and is run with every build. Findbugs provides an Ant task that makes it easy to integrate into Ant.

For the integration you have to install Findbugs of course or provide the libraries with the rest of the Metro workspace. We did not want to require a manual installation for every developer because that seemed just inconvenient. And we did not want to check the libraries into our workspace because that workspace and the downloadable distributables are already bigger than we would like them to be. Hence we chose an approach that I have not seen documented in its entirety anywhere else.

The solution is primarily provided by the eminently useful Ant Tasks for Maven. They allow you to execute a couple of Maven related tasks from an Ant build script. And one of the useful things you can do with them is download Findbugs from a Maven repository within your Ant build script. Integrating the tasks is straight-forward:

<target name="maven-init">
    <typedef resource="org/apache/maven/artifact/ant/antlib.xml">
        <classpath>
            <pathelement location="lib/maven-artifact-ant-2.0.4-dep.jar" />
        </classpath>
    </typedef>
    <remoteRepository id="maven.repository" url="http://www.ibiblio.org/maven2/"/>
</target>

The above makes sure Ant knows about the new Maven tasks and declares a repository from which we will be dowloading Findbugs. This target is designed to be reused by other targets, not just the one that is downloading Findbugs. But back to integrating Findbugs into our Ant script. This here does the interesting part of the work:

<target name="findbugs-base" depends="maven-init">
    <dependencies pathId="findbugs.classpath"
                  useScope="runtime">
        <remoteRepository refid="maven.repository"/>
        <dependency groupId="net.sourceforge.findbugs"
                    artifactId="findbugs"
                    version="1.3.2"/>
    </dependencies>
    <typedef name="findbugs" classname="edu.umd.cs.findbugs.anttask.FindBugsTask">
        <classpath refid="findbugs.classpath"/>
    </typedef>
    <pathconvert property="findbugs.classpath">
        <path refid="findbugs.classpath"/>
    </pathconvert>
</target>

The dependencies task is one of the Maven tasks we integrated in the previous step. It does all the work of downloading a recent version of Findbugs from the Maven repository that we declared earlier. After the download we can go ahead and declare the findbugs Ant task. The dependencies task helped with that by setting the findbugs.classpath path to the classpath of the Findbugs library and all of its dependencies that were just downloaded. Finally, since we have some tasks later that need a property with this path, we convert the path to a property with pathconvert. Now we can go ahead and actually use Findbugs:

<target name="findbugs-html" depends="findbugs-base"
    <findbugs output="html" 
              outputFile="${build.dir}/findbugs.html"
              stylesheet="fancy.xsl"
              classpath="${findbugs.classpath}"
              jvmargs="-Xmx256m"
              pluginlist="${user.home}/.m2/repository/net/sourceforge/findbugs/coreplugin/1.3.2/coreplugin-1.3.2.jar"
              excludefilter="findbugs-exclude.xml">
        <class location="${build.classes.dir}"/>
        <auxClasspath>
            <path path="${run.classpath}"/>
        </auxClasspath>
        <sourcePath path="${src.dir}"/>
    </findbugs>
</target>

The above simply invokes the findbugs task that we had downloaded in the previous step. You can see that we are using the findbugs.classpath property in the classpath attribute. That is why we had to convert the path into a property. According to the Findbugs documentation, the findbugs task requires that you set a home attribute that points to the Findbugs installation directory. In this case however we don't have a Findbugs installation directory. Maven downloaded the libraries in a very different layout to the local disk. Fortunately, we can use that in conjunction with an undocumented feature of the findbugs task. The trick lies in declaring the classpath and pluginlist attributes. classpath simply needs to point to the Findbugs libraries that we downloaded earlier. pluginlist should point to the coreplugin library that comes with Findbugs. You can of course point to additional plugins in that attribute. The coreplugin was downloaded by Maven together with the rest of Findbugs. We can easily guess the location because Maven uses a fixed directory and structure in your home directory where it stores downloaded libraries.

Tags: , ,

About

ritzmann

Search

Categories
Archives
« April 2014
MonTueWedThuFriSatSun
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Today