FindBugs and PMD applied on Java EE 5

Customization required to produce zero-errors code according to FindBugs

  1. Changing XMLGregorianCalendar to Calendar: WSIMPORT uses JAXB to generate classes from the XSD Schemas documents and by default JAXB generates XMLGregorianCalendar from xsd:dateTime attributes definition. Since XMLGregorian calendar is not a Serializable type, FindBugs complains against that. We can workaround that applying a JAXB Customization in our XSD documents, as described in this link.

     <xsd:annotation>
    <xsd:appinfo>
    <jaxb:globalBindings>
    <jaxb:javaType name="java.util.Calendar"
    xmlType="xsd:dateTime"
    parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
    printMethod="javax.xml.bind.DatatypeConverter.printDate" />
    </jaxb:globalBindings>
    </xsd:appinfo>
    </xsd:annotation>

     

  2. @EJB remote interface requires Serializable classes: WSIMPORT generates non-serializable code from WSDL documents, but since I am using @Remote interfaces of EJB, the RMI messages requires their contents to be Serializable. The workaround of that was again another annotation in the XSD Schema:

 

    <xsd:annotation>
<xsd:appinfo>
<jaxb:globalBindings>
<xjc:serializable uid="-6026937020915831338" />
<jaxb:javaType name="java.util.Calendar"
xmlType="xsd:dateTime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDate"
printMethod="javax.xml.bind.DatatypeConverter.printDate" />
</jaxb:globalBindings>
</xsd:appinfo>
</xsd:annotation>

 

And that's it, after this minor changes the FindBugs stopped to bother me about bugs and I got my 100% clean code following FindBugs, including the generated code. FindBugs checks the byte code of your classes, it uses a more sophisticated strategy on checking how your code works instead of how it is written as .java document. A clean FindBugs code indicates the generated byte code is sound - a good feeling for developers and better sleeping nights for project managers.

Customization required to produce zero-errors code according to PMD

PMD was a bit more complicated to satisfy since it is based on java code analysis instead of the byte code. A bit more pedantic that FindBugs, PMD is based on heuristics about the code statistics. If a code is lengthy, PMD assumes it is buggy, and if there are too many public methods, PMD also assumes it is buggy. That attempt to identify problems analyzing code metrics is controversial but PMD was one of the first quality tool I learned to use few years ago, so I decided to customize its rules set in order to continue on using it in my J2EE 5 code. You can find the resultant rule set configuration file here. Be aware that Cejug-Classifieds is a work under progress and the contents of that file are only our beliefs about our own code quality.

small_beagleboys.png
Caption: Beagle Boys prefer brute force against bugs.

After the PMD customization I got a zero-errors report but since PMD covers five different levels of problems, I noticed the report of some High Warnings on the code. I am still fighting against them, specially the following ones:



  1. BeanMembersShouldSerialize: that one is hard, since I have a secondary issue related to that warning. One of the GUIs consuming our services uses FLEX, and it seems FLEX uses reflection to set values in the Java beans. The problem is, JAXB doesn't generate setters methods to attributes that contains maxOccurs='unbounded' (Collections). It causes problems of FLEX consuming SOAP 1.1 service exposed by JAXWS, and we are still looking for a solution for that. Actually, the PMD warning points to another direction, but it keeps a helpful mark to the FLEX problem in our service code.

  2. AvoidFieldNameMatchingTypeName: one of the elements of my XSD has a ref to itself, because it models Categories and Sub-Categories. Since I am using reference instead of creating a new attribute, the name of the field is compiled as the same name of the class. I agree with PMD that it is weird, so I will look for a solution asap. Until finding the solution, the warning will remain active.

  3. AbstractClassWithoutAbstractMethod: since we are using a JPA persistence façade, we use an AbstractEntity class to share entities fields. That class hasn't any method, since it is used only as superclass to the entities and therefore doesn't make any sense to force this class to be concrete nor to have methods.

  4. UncommentedEmptyConstructor: I finally opted to remove this rule since JAXB generates empty constructor for all elements on the meta-data. Not a big deal in my opinion, empty constructors are useless in most part of cases but they never cause problems at all, so the rule seems too pedantic to remain active.

  5. UnnecessaryParentheses: the same as the previous example, unnecessary parenthesis causes no damage to the code since they will be removed by the compiler. It only happens on generated classes and shouldn't be part of a serious code analysis.

Conclusion: I strongly recommend you to use PMD and FindBugs on your J2EE 5 code

Generated code and specially Generics requires an extra effort to pass through the code analysis since it is not pure classical Java code. Specially PMD claims more attention since it is based on heuristics instead of byte code analysis and it is older than FindBugs. Many of the suppositions ruled by PMD were created before the generics support on Java, and some of them simply doesn't apply anymore. Despite that, we realized in our experiments that both tools can be used together with good results and no conflict at all. If you aren't using PMD and FindBugs on your project, try them today - you will be surprised on how fast you can enhance the quality of your code. Actually I bet you will also get addicted to their quality metrics, specially FindBugs.

Acknowledge: the experiments and the effort to achieve the current quality results were shared with Rodrigo Lopes, one of the main commiters of Cejug-Classifieds.

Article Type: 
How-to
0
Average: 5 (1 vote)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)