Home > Uncategorized > My epic battle with findbugs-maven-plugin and how I utterly lost

My epic battle with findbugs-maven-plugin and how I utterly lost

August 23rd, 2011

It started quite innoucently. I was looking at this thread in Jenkins dev list and thought it’d be a good idea to get some critical findbugs errors to fail a build. My goal was simple, I want to run some high-priority findbugs checkers during the build, and if they report any error, I want the build to fail. I wanted this to be in a profile, so that I don’t need to wait for FindBugs to finish if I just want to build.

Should be simple enough, you’d think. Nope.

I’ve spent the entire afternoon getting this going. There were several issues in the plugin and relevant places that blocked my progress. In the hope that other people won’t suffer the same loss, here are those:

  • Maven 2.x and Maven 3.x site plugins are totally incompatible, breaking the setup that used to work. AFAIK there’s still no reasonable approach to enable your project to build both with Maven 2 and Maven 3, when it comes to site stuff, and that pretty much includes all the code analysis plugins. Maven 3 breaks backward compatibility with the site configuration of Maven 2, so the POM setup that used to work will no longer work with Maven 3. (So if someone tells you that Maven 3 is compatible with Maven2, don’t let them fool you.) It silently ignores all you have in and does nothing. So you’ll have to move the reporting configuration into a new location. This used to make it impossible to share the site configuration between Maven2 and Maven3, but I was told that the latest Maven site plugin version 3.0 no longer has this problem.

  • Findbugs plugin documentation seems to offer two mojos to generate reports — findbugs:check and findbugs:findbugs. But the check mojo actually isn’t capable of generating any reports. Two dozen or so configuration options to tweak the report generation you see in the doc are totally bogus. They are unused and ignored. (correction 8/24: what I missed is that the check plugin designates findbugs:findbugs as a pre-requisite.)

  • Some people tell you that you can invoke mvn findbugs:findbugs directly to generate report, but this is rather problematic if you actually try it. Firstly, it will generate XML but not HTML, so it’s useless for human beings. It does tell you how many bugs it found, but it doesn’t tell anything that actually points you to where the offending code is. One is supposed to be able to work around that by running the findbugs:gui mojo, but AFAICT this mojo is utterly broken. Secondly, if you invoke findbugs:findbugs mojo directly, it doesn’t pick up the same configuration that it uses during the site generation (one picks up build/plugins/plugin, the other looks at reporting/plugins/plugin). Again, AFAIK there’s no way to have those two modes of invocation use the same configuration.

  • You need to make sure that Maven at least compiled your source code before running site. The FindBugs mojo will happily skip itself if there’s no class files to work on, and unless you are smart enough to figure out what the mysterious “canGenerate=false” line means, you’ll waste your time trying to figure out why the mojo isn’t working, like I did.

  • Remember my use case of making the build fail in case of serious FindBugs issues? Documentation might make you believe that findbugs:check mojo is able to do this, but there are two large pit-falls. One is what I’ve already described, namely that this doesn’t actually run FindBugs, and instead it expects that you’ve already run it. The other is that if it doesn’t find any trace of FindBugs running, it happily skips itself. The consequence is that mvn clean install will always complete successfully, even if your code has FindBugs violations. I still haven’t figured out how to make this whole thing work. As I mentioned, findbugs report generation itself requires that the source code be compiled, so I guess you’d have to invoke Maven like mvn clean compile site install or something. This is just ridiculous.

  • In FindBugs, you can specify what rules you want to enforce and what rules you want to ignore. You describe this in a filter file. In a multi-module project, it tends to be more convenient to have just one filter file that all your modules use, rather than having many similar filter definitions. But this seemingly typical use case just doesn’t work with the Maven FindBugs plugin, because the path you specify in the filter file configuration is always interpreted relative to the current Maven module, and there seems to be no way to have it point to the base directory of the project (the ${project.basedir} macro also expands to the current module’s base directory, which is useless.) The documentation does talk about this and gives you a work around. As a Maven plugin developer myself, I understand where they are coming from, but as a Git user, the assumption that requires such a cumbersome workaround (of being able to check out and build modules individually, like you can in Subversion) is unnecessary, yet I still have to pay all the price. This doesn’t make sense.

I’m sorry to say this, but this is a disaster. Integrating FindBugs in Ant project, generating HTML report, and failing a build in case of significant error is fairly straight-forward, and takes maybe 10 or 20 lines at max. But here in Maven, it takes more lines in your POM, not to mention one whole Maven module just for the filter file, plus all these pitfalls. And it still doesn’t attain my original goal of making critical FindBugs issues fail the build.

Experiences like this made me really want to switch to Gradle, but alas, it’s no longer my call alone to make changes like that. So for the time being, I think I’m going back to my good trusted Maven antrun extended plugin. At least it works. And Stephen, this is why Ant fragment is actually more maintainable than the magical combination of Maven hacks.

Uncategorized ,

  1. Thomas Dudziak
    August 23rd, 2011 at 22:49 | #1

    Did you try the maven 3 profile trick from https://cwiki.apache.org/MAVEN/maven-3x-and-site-plugin.html (bottom of the page) ? Basically it should be possible to define two profiles, one for maven 2 and one for maven 3, with the respective site generation setup. I tried the maven 3 profile thing myself for some project of mine and it works fine (but I haven’t tried a maven 2-only profile yet).

  2. August 23rd, 2011 at 23:46 | #2

    I’ve certainly ran into my fair share of maven issues since maven 1, but I can’t imagine what my existing project would look like without it.
    For the most part I have seen maven 3 be backwards compatible. I haven’t had to test maven site yet so sounds like that makes a difference.
    I will say I also use a combination of ant via the antrun plugin, but I actually prefer the gmaven plugin: http://docs.codehaus.org/display/GMAVEN/Home.

  3. August 24th, 2011 at 00:16 | #3

    AFAIK maven site plugin 3.0 (recently released) is now compatible for both maven 2.x and 3.x

  4. kreyssel
    August 24th, 2011 at 00:38 | #4

    I think you mix problems in your post.

    You say that bugs/missing features in the findbugs-maven-plugin make you not able to implement a feature like you want to do. IMHO, this is not a maven problem, this is a problem with the plugin itself!

    And your point with more codelines between ant and maven is not fair. In this case it is true, but in the most cases it doesnt. Do you think that the today jenkins build (incl plugins) can be simpler and manageable done with ant?

  5. Stephen Connolly
    August 24th, 2011 at 00:53 | #5

    Don’t worry I’ll bash it into shape again and rip out antrun-extended as soon as I get a chance. ;-)

  6. amertum
    August 24th, 2011 at 00:53 | #6

    Agree with the problem of compatibility between maven site plugin for maven2 and maven3. But running the findbugs plugin only to check code with maven multimodule is quite easy and works well (at least for me ;-))

    /findbugs-exclude.xml
    /pom.xml
    /module1/
    /module2/

    sub-modules pom should inherit from /pom.xml

    in /pom.xml

    org.codehaus.mojo
    findbugs-maven-plugin

    ${findbugs-failOnError}

    Max
    Default

    true
    true
    true

    ${basedir}/../findbugs-exclude.xml

    pre-integration-test

    check

    I do the same thind with PMD.

  7. amertum
    August 24th, 2011 at 00:55 | #7

    Oups code formatting goes away, try again.


    <plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>findbugs-maven-plugin</artifactId>
    <configuration>
    <failOnError>${findbugs-failOnError}</failOnError>

    <effort>Max</effort><!-- Min, Default, Max -->
    <threshold>Default</threshold><!-- High, Default, Low, Ignore -->

    <xmlOutput>true</xmlOutput>
    <findbugsXmlOutput>true</findbugsXmlOutput>
    <findbugsXmlWithMessages>true</findbugsXmlWithMessages>

    <excludeFilterFile>${basedir}/../findbugs-exclude.xml</excludeFilterFile>
    </configuration>
    <executions>
    <execution>
    <phase>pre-integration-test</phase>
    <goals>
    <goal>check</goal>
    </goals>
    </execution>
    </executions>
    </plugin>

  8. Maarten
    August 24th, 2011 at 02:03 | #8

    I, for one, would wholeheartedly support a switch by Jenkins to Gradle. I seems to me that Maven is, and always has been, much more trouble than it’s worth.

  9. Steven Dick
    August 24th, 2011 at 04:53 | #9

    If I’m free to pick a build system from Maven, ANT and Gradle, then it’s Gradle. Dependency management with a sane way of doing build customization. Down with XML-as-a-build-language.

  10. August 24th, 2011 at 07:59 | #10

    @Thomas Dudziak
    Yes, I’ve seen that, and you are right that this presumably would be useful as an escape hatch.

    It was just that adding 30+ more lines of hack into POM (on top of all that I’ve already added) was more than I was willing to do, especially because site wasn’t what I was interested to begin with. I just want to run FindBugs and get errors.

  11. August 24th, 2011 at 08:02 | #11

    @James Lorenzen
    I agree that I can’t imagine what my projects would have looked like without it — after all I kept using them. But sometimes it really pushes me over the edge.

    And yes, I like GMaven plugin a lot, too, and I use it.

  12. August 24th, 2011 at 08:07 | #12

    @kreyssel
    This post was written in anger, so it may have come out as confusing, but I don’t think I said this is a Maven problem. I think much of the issue stems from the implementation approach of the Maven static code analyss plugins, because the findbugs plugin appears to try hard to keep the behaviour in line with other similar plugins.

  13. August 24th, 2011 at 08:10 | #13

    @amertum
    As I wrote in MPFINDBUGS-118, your code actually does not run findbugs. It just picks up the result of the previous execution. Similarly, “${basedir}/../foobar.xml” only works when your modules are flat.

  14. August 24th, 2011 at 08:13 | #14

    @Olivier Lamy
    OK, thanks for the info. That I didn’t know. I’ll make a correction accordingly.

  15. Chris Hilton
    August 24th, 2011 at 08:41 | #15

    Use Sonar and its build breaker plugin?

  16. benson margulies
    August 24th, 2011 at 09:01 | #16

    maven-site-plugin 3.0 definitely fixes the compatibility story, which was just as bad as you report for the previous releases of the site plugin.

  17. August 24th, 2011 at 09:12 | #17

    As always, writing a post like this turns out to best way to discover all my mistakes. In MPFINDBUGS-118, Garvin LeClaire pointed out that findbugs:check specifies findbugs:findbugs as a pre-requisite. So I made that correction in the post as well.

  18. Bill Shannon
    August 24th, 2011 at 12:26 | #18

    Hi Kohsuke! I ran into some of these problems using FindBugs with GlassFish.
    In particular, for your last bullet point, I ended up creating a separate module
    to contain the resource file with the global FindBugs filter rules for all of
    GlassFish. The FindBugs plugin configuration includes this module as a dependency.
    In addition, each module is allowed to have a filter file of its own, stored in the
    module directory, and configured with a property set to the pathname using
    “${project.basedir}/exclude.xml”. See the GlassFish pom files for examples.

    This was *much* more complicated than I expected, but I’m learning to expect that
    of Maven…

    For findbugs:check, I’ve never been able to make it work correctly for GlassFish.
    If I remember right, Garvin believes it’s due to a Maven bug. I’m waiting to see
    if Maven 3.0 fixes it. For some reason findbugs:check runs with a different set
    of dependencies or different classpath than findbugs:findbugs.

    findbugs:gui works fine for me if I run it in a leaf module, but there’s no way to
    run it in at the top level and get an aggregated view of all the errors. For that
    we depend on the Hudson FindBugs plugin. I also wrote a simple program to turn
    the findbugsXml.xml into plain text in the format of typical compiler error
    messages. But it sure would be nice if the FindBugs plugin could do that.

    Sonar was a non-starter due to its lack of support for the FindBugs filter file.

  19. August 25th, 2011 at 14:44 | #19

    @Bill Shannon
    I feel honored to hear from you! Thanks for the details. I wonder if your simple program to parse FindBugs XML into plain text could be merged into the findbugs plugin. It’s one of the frequently requested features there.

  20. Ravi Teja
    September 1st, 2011 at 23:19 | #20

    Hi, I ran into similar problem , but got a solution for it.
    The findbugs provides you a xsl ${findbugs.home}/src/xsl/default.xsl. Using this xsl and maven xslt plugin, you can convert the generated xsl to the html.
    Thanks,
    Ravi Teja

  21. September 2nd, 2011 at 02:17 | #21

    KK – what do you think of Chris Hilton’s suggestion to use Sonar and the build-breaker? I see that this didn’t work for Bill Shannon, but is there scope to add “support for the FindBugs filter file”? Or some other work-around? It sounds like you just need a Sonar profile for your critical errors, but I could be wrong.

    I’m no expert, but I’ve dabbled in breaking the build on Findbugs/Checkstyle results in various scenarios (both Ant and Maven-based) over the past 2 years or so, and the more I use Maven & Jenkins & Sonar & Build-breaker, the more I think that separating the responsibilities between project building and code quality measurement/reporting is The Right Thing To Do.

    It’s not the perfect combination yet, but perhaps if the Jenkins community were more involved in the Sonar project, perhaps improving integration between the two, rather than having code quality efforts more “thinly spread” between Sonar and Jenkins Plugins, then we’d get better quicker.

    Sonar has a whole bunch of features that are really useful, especially when it comes to hooking rules and profiles into the dev’s workspaces, and it would be nuts to attempt to duplicate them (and I’m speaking as someone who was foolhardy enough to try, in some insane Ant-based build I used to oversee).

    I’m not trying to be critical, just push forward the case for the “Jenkins&Sonar” dream team!

  22. Peter
    December 20th, 2012 at 03:11 | #22

    It is sad but after more then year situation is unchanged,. I wanted to exclude Android R.java class through exclude filter and couldn’t understand why is still reported. Moving plugin from reporting to build solved issue. Shame on these maven-findbugs-plugin commiters

  23. January 6th, 2014 at 11:48 | #23

    I know this is a late reply to your post but better late than never. I just figured out that you can add the attribute ${project.parent.basedir} and it solves the issue. Your IDE may not like it but the site builds totally fine.

  24. March 13th, 2014 at 10:24 | #24

    I hope I dont get flamed for saying that I am a Gradle user.
    I have been trying for now 4 days on and off to get findBugs to generate anything resembling (XML or otherwise) a report.

    It has been a serious uphill struggle, and if I could use a Java static analyzer that actually works within 10 minutes of configuring it, I would pay for it…any suggestions are welcome.

    So, its not Maven, or Gradle, it is findBugs.

  25. Jesse Glick
    January 6th, 2015 at 03:25 | #25

    I have no special suggestion for the custom rules issue, but I think everything else is handled easily enough by running the check goal in a profile enabled whenever skipTests is not. https://github.com/jenkinsci/workflow-plugin/commit/075b4c66dd1c4805408d4d02048c29915d50f30e#diff-26 shows how. Now if you are running a full build including tests (but not otherwise), FindBugs will run (after compilation), and if it encounters any errors, print them to the log and exit. There is no HTML reporting here, but if you just want to fail if there are *any* errors, this does not seem important anyway.

  1. No trackbacks yet.