Tag Archives: Static Analysis

We have found it useful to run our static analysis tools as part of our JUnit test suite, so that developers have a single task and IDE integration for code validation before a check-in, rather than having to run multiple tasks and tools. We first used that approach with CodeNarc, for analyzing our Groovy code. We also wanted the same integration for Java source code using PMD.

We use Groovy extensively for our automated tests, and we take advantage of Groovy’s integration with Ant using the Groovy AntBuilder class. That allows us to use the PMD Ant Task to execute PMD. Note that though the test class is in Groovy, the source code that we are analyzing is in Java.

1. Add PMD and Groovy-Ant Jars to the Classpath

First you need to add the PMD and Groovy-Ant jars to your project classpath. This is an excerpt from build.gradle for Gradle:

dependencies {
    // Support for PMD Ant Task 
    testCompile 'org.codehaus.groovy:groovy-ant:2.4.13'
    testCompile 'net.sourceforge.pmd:pmd-java:6.0.0'

2. Create a Groovy JUnit Test to Execute the PMD Ant Task

Here is the Groovy JUnit test class that executes PMD against our Java source code:

package sandbox

import java.util.logging.LogManager
import org.junit.Test

 * JUnit test to run PMD against the project Java source.
class RunPmdTest {

    private static final String RULESET_FILE = 'pmd-ruleset.xml'

    void runPmd() {
        // Disable internal PMD logging (Java Util Logging)

        def ant = new AntBuilder()

            failonerror:'true', failOnRuleViolation:'true') {

            sourceLanguage(name:'java', version:'1.8')


            formatter(type:'text', toConsole:'true')

            fileset(dir:'src/main/java') {

 Some things to note:

  • This test will fail if there are any PMD violations.
  • This example is based on a Gradle project. You may need to adjust the paths (e.g. “src/main/java” or “build/cache/pmd”), especially if you using this within a non-Gradle project.
  • In this example, the PMD results are only written to the console. You can add other formatters to write additional report types (HTML, XML, etc.). See the PMD Ant Task.
  • PMD logging is programmatically configured to streamline the PMD output.

3. Create the PMD Ruleset File

This is the “pmd-ruleset.xml” PMD ruleset file, located on the classpath:

<?xml version="1.0"?>
<ruleset name="Custom ruleset"
 <description>Custom PMD RuleSet</description>
 <rule ref="category/java/bestpractices.xml/AvoidPrintStackTrace" />
 <rule ref="category/java/bestpractices.xml/UnusedImports" />
 <rule ref="category/java/bestpractices.xml/UnusedLocalVariable" />
 <rule ref="category/java/bestpractices.xml/UnusedPrivateField" />
 <rule ref="category/java/bestpractices.xml/UnusedPrivateMethod" />

This is just a simple example ruleset. You will want to choose your own set of PMD rules. See the list of Java PMD rules.

(This article originally appeared in the June 2013 issue of GroovyMag)

This article provides examples of using CodeNarc’s “generic” rules to enforce your own custom best practices.

CodeNarc is a static analysis tool for Groovy source code, enabling monitoring and enforcement of many coding standards and best practices. It contains a set of rules, each of which can be individually enabled and configured.

In addition to the more obvious and straightforward rules for naming, size/complexity, unused code, etc., CodeNarc also contains a set of generic rules that require more specific configuration and customization in order to be useful (and enabled). In this article, we will look at six of these generic rules and how they can be used to enforce your organization’s coding and design standards and best practices.

          StatelessClass rule

The StatelessClass rule checks for non-final fields on a class. The intent of this rule is to check a configured set of classes that should remain “stateless” and reentrant. This rule ignores final fields (either instance or static), and all fields annotated with the @Inject annotation, as well as all classes annotated with the @Immutable transformation.

One example where this can be useful is DAO classes, if you define them as singletons (e.g., Spring beans). In that case, they need to be reentrant, and the only fields on the classes should be for configuration or injecting dependencies.

You can configure this rule to ignore certain fields either by name (ignoreFieldNames) or by type (ignoreFieldTypes). This can be used to ignore fields that hold references to (static) dependencies (such as DataSources) or static configuration.

See Listing 1 for an example StatelessClass rule configuration. Note that we override the rule name property (from its default “StatelessClass”), to give it a name more reflective of its customized purpose. That is usually a good idea for any of the CodeNarc generic rules. The rule is configured to ignore any fields named “dataSource” or fields with names ending in “Dao”. We also give it a custom description, which will be shown in the rule descriptions section of the HTML or XML reports.

StatelessClass {
    name = 'StatelessDao'
    priority = 2
    ignoreFieldNames = 'dataSource, *Dao'
    applyToClassNames = '*Dao'
    description = 'DAO classes should be stateless and reentrant. (Custom)'

Listing 1: StatelessClass rule configuration for DAOs

Note that this rule will not catch violations of true statelessness/reentrancy if you define a final field whose value is itself mutable, for example a final HashMap.

          IllegalPackageReference rule

The IllegalPackageReference rule checks for references to any of the packages configured in its packageNames property. This rule can be useful for governance and enforcement of architectural layering. Listing 2 contains an example IllegalPackageReference rule configuration that checks for references to any JDBC-specific packages (groovy.sql, java.sql or javax.sql) from non-DAO classes.

IllegalPackageReference {
    name = 'UseJdbcOnlyInDaoClasses'
    priority = 2
    packageNames = 'groovy.sql, java.sql, javax.sql'
    doNotApplyToClassNames = '*Dao*, com.example.dao.*'
    description = 'Reference to JDBC packages should be restricted to DAO classes. (Custom)'

Listing 2: IllegalPackageReference rule configuration

          IllegalClassReference rule

The IllegalClassReference rule checks for reference to any of the classes configured in its classNames property. Like the IllegalPackageReference rule, it can be used for governance and enforcement of architectural layering. Listing 3 contains an example IllegalClassReference rule configuration that checks for illegal DAO references from within model classes.

IllegalClassReference {
    name = 'DoNotReferenceDaoFromModelClasses'
    priority = 2
    classNames = '*Dao'
    applyToClassNames = 'com.example.model.*'
    description = 'Do not reference DAOs from model classes.'

Listing 3: IllegalClassReference rule configuration: Do not reference DAOs from model classes

The IllegalClassReference rule can also be used to flag references to obsolete or deprecated classes. Listing 4 contains an example rule configuration that checks for references to an old XmlUtil class that was used in our Java code to parse XML, but that is now obsolete because of the XML parsing provided by Groovy’s wonderful XmlSlurper (or XmlParser).

IllegalClassReference {
    name = 'DoNotUseXmlUtil'
    priority = 2
    classNames = 'com.example.xml.XmlUtil'
    applyToClassNames = '*'
    description = 'Do not use the XmlUtil class to parse XML. Use the Groovy XmlSlurper class instead. (Custom)'

Listing 4: IllegalClassReference rule configuration: Do not use obsolete class

          RequiredRegex rule

The RequiredRegex rule checks for a specified regular expression that must exist within the source code. Listing 5 contains an example rule configuration that verifies that each source file contains a javadoc comment containing @version … $Revision … @author … $Author … $Date. The (?s) prefix within the regular expression string enables dotall mode, which means that the expression . matches any character, including a line terminator, allowing the pattern to span multiple lines.

RequiredRegex {
    name = 'ClassJavadocTags'
    priority = 2
    regex = '(?s)\\/\\*\\*.*\\@version.*\\$Revision.*\\$.*\\@author.*\\$Author.*\\$.*\\$Date.*\\$'
    description = 'Class javadoc must include $Revision, $Author and $Date tags. (Custom)'

Listing 5: RequiredRegex rule configuration

          IllegalRegex rule

The IllegalRegex rule checks for a specified illegal regular expression within a source file. Listing 6 contains an example rule configuration that checks for empty @see tags within javadoc. We had an old class javadoc template in place for a few years that included an empty @see tag, so our codebase was littered with them. Perhaps you have similar junk scattered around your codebase? The (?m) prefix within the regular expression string enables multiline mode, which means that the $ expression matches the end of the line.

IllegalRegex {
    name = 'EmptySeeTag'
    priority = 2
    regex = /(?m)\@see\s*$/
    description = 'Class javadoc must not include empty @see tags. (Custom)'

Listing 6: IllegalRegex rule configuration

          RequiredString rule

The RequiredString rule checks for a specified text string that must exist within the source files. Listing 7 contains an example rule configuration that checks that each source file contains the Apache 2.0 License header. Note that, as configured, it only checks for a single line of the license. That should be good enough to ensure that you don’t forget to include the license within your source files. You can change the configuration to check for the exact, entire license, if you wish, but you must configure the whitespace exactly, and the copyright year must be correct and consistent across all source files.

RequiredStringRule {
    name = 'ApacheLicenseRequired'
    string = 'Licensed under the Apache License, Version 2.0 (the "License");'
    violationMessage = 'The Apache License 2.0 comment is missing from the source file'
    description = 'Checks that all source files contain the Apache License 2.0 comment'

Listing 7: RequiredString rule configuration

          Learn More