Wednesday, June 20, 2007

False positives with FindBugs on IoC code

I just configured FindBugs on a current spring and JPA enabled project, using the maven-findbugs MOJO from codehaus.

A first run detected some bugs, which was purely due to our code using spring container for dependency injection and JPA for mapping to the database. Something is happing at runtime, that FindBugs does not account for. Examples follow...

Field not initialized in constructor (UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR)
This is simply a dependency property on the class, that gets injected by a setter on the instance at runtime. What findbugs tells me is, that it cannot spot any initialization on the private variable in the constructor, before it is used in my class. The code is like this:
public class FooServiceImpl implements FooService {
private BarService barService;

public void setBarService(BarService barService) {
this.barService = barService;
}

public void someServiceMethod() {
// use of barService here...
}
}
Hmm, well. I want to filter that out. You can do that, with the following findbugs filter.
<findbugsfilter>
<match>
<package name="~com\.company\.system\.service.*"/>
<class name="~.*ServiceImpl"/>
<or>
<field name="~.*Dao"/>
<field name="~.*Service"/>
</or>
<bug pattern="UWF_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR"/>
</match>
</findbugsfilter>
Basically, it says: Filter out all classes named something that ends in ServiceImpl, which are placed below the com.company.system.service package, if the field in question is named something with Dao or Service at the end (like barService, in this example).

Private method is never called (UPM_UNCALLED_PRIVATE_METHOD)
This is in a JPA mapped class, where the setter for the "id" attribute is marked private, as it should not be called from application logic, but only from the JPA mapping layer through reflection. The code is like this:
public class Bleech {
private Long id;

private void setId(Long id) {
this.id = id;
}
}

So, findbugs cannot see this method is called, although it will be at runtime, when the JPA mapper kicks in. Again, I want to filter these bugs out, which can be done with this findbugs filter:
<findbugsfilter>
<match>
<package name="~com\.company\.system\.domain.*"/>
<method name="~set.*" returns="void" params="java.lang.Long"/>
<bug pattern="UPM_UNCALLED_PRIVATE_METHOD"/>
</match>
</findbugsfilter>

This filter matches classes in domain package with a "void setXxx(Long)" signature.

Configuring exclude filter on the maven-findbugs-plugin
I configured my filter settings above as exclude filters on the maven plugin like this in the pom:
<reporting>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>findbugs-maven-plugin</artifactId>
<version>1.1</version>
<configuration>
<effort>Max</effort>
<excludeFilterFile>${basedir}/src/main/resources/findbugs-exclude.xml</excludeFilterFile>
<onlyAnalyze>com.company.*</onlyAnalyze>
</configuration>
</plugin>
</reporting>

and saved the findbugs-exclude.xml in src/main/resources (a specific one for each module: domain and services).

Initially, I had some trouble getting the findbugs plugin to find my filter file. Running maven with "-X" revealed a DEBUG statement about where it tried to find by filter file (which accidently, was not were it actually was).

Will it help me or irritate me?
Not having used FindBugs for real before, I am wondering if it will actually make my code better than it was before, or if I will be tired of it before that happens.

I already filtered out a bug about serialVersionUID not being defined for a serializable class (SE_NO_SERIALVERSIONID). I hate that one! Once worked with Eclipse for a short time, which kept complaining about that too. Who cares? I do not send class bytecode over the wire to other systems or store serialized versions for later retrieval. In the actual code, it was a servlet of mine, which, simply by inheriting HttpServlet, became serializable.

Anyway, I (and the complete team), use IDEA, which is already pretty good at spotting a lot of these errors and warnings on the fly, helping me to correct them too.

Will findbugs give me anything new?

2 comments:

Anonymous said...

I tried to use findbugs too, and I was really surprised about "accessing undefined field" which are injected by IoC container. Therefore, I asked FindBugs if they planned to improve there spring support. You should try to search spring plugin to findbugs functionality, they answered.

Stevo Slavić said...

It's 2011, some of these issues are still open. Just started related discussion on findbugs mailing list.