Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Code Analysis With Gradle Plugins

DZone's Guide to

Code Analysis With Gradle Plugins

Code Analysis is usually done as the last step (if done at all) in most projects. It is usually hard to configure and integrate it with the existing code. This article aims to outline the steps (and the ease of it) to integrate PMD and FindBugs with Gradle, and integrate these with an existing Sonar build tool.

· DevOps Zone
Free Resource

“Automated Testing: The Glue That Holds DevOps Together” to learn about the key role automated testing plays in a DevOps workflow, brought to you in partnership with Sauce Labs.

Code Analysis is usually done as the last step (if done at all) in most projects. It is usually hard to configure and integrate it with the existing code.

This article aims to outline the steps (and the ease of it) to integrate PMD and FindBugs with Gradle, and integrate these with an existing Sonar build tool.

PMD, CheckStyle, and FindBugs

The first thing we need to add is the plugins in our build.gradle file:

apply plugin: 'checkstyle'
apply plugin: 'pmd'
apply plugin: 'findbugs'

These plugins enable PMD, CheckStyle, and FindBugs in our code. 

By default, these tasks execute on both the Test and Main source code. For us to exclude FindBugs, and PMD from running on the test code, we include the following commands:

findbugs{
    findbugsTest.enabled=false
}
pmd {
    pmdTest.enabled=false
}

Next, we execute this from Gradle:

./gradlew clean findBugsMain pmdMain

This cleans out the project and then executes FindBugs and PMD on the source code.

The output is as below:

:clean
:compileJava
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:processResources
:classes
:findbugsMain FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':findbugsMain'.
> FindBugs rule violations were found. See the report at: file:///myprojects/build/reports/findbugs/main.xml

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 24.597 secs

The build failed even without executing the PMD, since there are FindBugs violations. The output of the FindBugs and PMD are in XML. 

The report can be found at <proj_home>/build/reports directory

In order to have a human readable HTML output and continue the build on failure, we make the following changes to the build.gradle file:

findbugs{
    ignoreFailures=true
    findbugsTest.enabled=false

}

tasks.withType(FindBugs) {
    reports {
        xml.enabled = false
        html.enabled = true
    }
}
tasks.withType(Pmd){
    reports{
        xml.enabled=true
        html.enabled=true
    }
}
pmd {
   ignoreFailures = true
    pmdTest.enabled=false
}

The task.withType is used to configure each of the tasks. In this, you are enabling the HTML and XML reports for PMD and HTML for FindBugs.

Note: At the time of writing, FindBugs only support one enabled output

./gradlew clean findBugsMain pmdMain
:clean
:compileJava
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
:processResources
:classes
:findbugsMain
FindBugs rule violations were found. See the report at: file:///myprojects/build/reports/findbugs/main.html
:pmdMain
Removed misconfigured rule: LoosePackageCoupling  cause: No packages or classes specified
Removed misconfigured rule: LoosePackageCoupling  cause: No packages or classes specified
174 PMD rule violations were found. See the report at: file:///myprojects/build/reports/pmd/main.html

BUILD SUCCESSFUL

Total time: 6.013 secs

For PMD, you can configure the rulesets using the ruleSet option. Following are some of the commonly used rulesets.

pmd {
   ignoreFailures = true
    pmdTest.enabled=false
    ruleSets = [
            'java-basic',
            'java-braces',
            'java-clone',
            'java-codesize',
            'java-comments',
            'java-controversial',
            'java-coupling',
            'java-design',
            'java-empty',
            'java-finalizers',
            'java-imports',
            'java-optimizations',
            'java-strictexception',
            'java-strings',
            'java-typeresolution',
            'java-unnecessary',
            'java-unusedcode'
    ]
}

A sample output would be as below:

Image title

Image title

Sonar Integration

PMD, Checkstyle, and Sonar are all useful tools. However, from an organization prespective, we need to track the changes to the project's code quality and technical debt over a period of time. We need to be able to measure against other similar teams.

In order to do this, Sonar is used. This article assumes that you have a working Sonar setup.

Altassian provides the Sonar plugin for this. In order to use this, we add the necessary plugin.

buildscript {
    repositories {
        mavenCentral()
        maven { url "http://mvnrepo.nordstrom.net/nexus/content/groups/public" }
        maven { url "http://repo.maven.apache.org/maven2" }
    }
    dependencies {
        classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:1.2"
    }

}

Once the build script is setup, we configure the sonarqube:

apply plugin: "org.sonarqube"

sonarqube{
    check
    properties {
        // Sonar Specific properties
        property 'sonar.projectName', 'Project Services' // This is the display project name
        property 'sonar.host.url','http://sonar:8080/' // This is the Sonar Server
        property 'sonar.projectKey', 'com.wordpress.mrvivekr:project' // The Key using which the project details are tracked

       // JDBC Properties
        property 'sonar.jdbc.url','jdbc:jtds:sqlserver://ABCD:1433/SonarDB;domain=MYCOMP;SelectMethod=Cursor'

        property 'sonar.jdbc.username','userName'
        property 'sonar.jdbc.password','Secr#%'

      //Which Sonar Profile to use - this is optional
        property 'sonar.profile','JavaProfile'
    }
}

Note: sonar.profile is the pre-configured sonar profile (and rules) that is set up by your company. This is not mandatory and is optional. My JDBC connection uses a SQLServer to connect to

./gradlew sonarqube
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:compileTestJava
:processTestResources
:testClasses
:test
....... ommitted .....
11:27:36.713 INFO  - Java Main Files AST scan done: 812 ms
11:27:36.714 INFO  - 13/13 source files have been analyzed
11:27:36.715 INFO  - Java bytecode scan...
11:27:36.762 INFO  - Java bytecode scan done: 47 ms
11:27:36.762 INFO  - Java Test Files AST scan...
11:27:36.762 INFO  - 5 source files to be analyzed
11:27:36.885 INFO  - Java Test Files AST scan done: 123 ms
11:27:36.885 INFO  - 5/5 source files have been analyzed
11:27:36.888 INFO  - Package design analysis...
11:27:39.868 INFO  - Package design analysis done: 2980 ms
11:27:39.884 INFO  - Sensor JavaSquidSensor (done) | time=4307ms
11:27:39.884 INFO  - Sensor Lines Sensor
11:27:39.888 INFO  - Sensor Lines Sensor (done) | time=4ms
11:27:39.888 INFO  - Sensor QProfileSensor
11:27:39.891 INFO  - Sensor QProfileSensor (done) | time=3ms
11:27:39.891 INFO  - Sensor InitialOpenIssuesSensor
11:27:45.592 INFO  - Sensor InitialOpenIssuesSensor (done) | time=5701ms
11:27:45.592 INFO  - Sensor ProjectLinksSensor
11:27:45.730 INFO  - Sensor ProjectLinksSensor (done) | time=138ms
11:27:45.730 INFO  - Sensor VersionEventsSensor
11:27:47.690 INFO  - Sensor VersionEventsSensor (done) | time=1960ms
11:27:47.690 INFO  - Sensor org.sonar.plugins.findbugs.FindbugsSensor@7894f007
11:27:47.694 INFO  - Execute Findbugs 3.0.1...
11:27:48.557 INFO  - Found findbugs plugin: /myprojects/build/sonar/findbugs/fb-contrib.jar
11:27:48.596 INFO  - Found findbugs plugin: /myprojects/build/sonar/findbugs/findsecbugs-plugin.jar
11:27:48.612 INFO  - Findbugs output report: /myprojects/build/sonar/findbugs-result.xml
The following classes needed for analysis were missing:
  javax.crypto.spec.SecretKeySpec
11:27:50.846 INFO  - Execute Findbugs 3.0.1 done: 3153 ms
11:29:31.499 INFO  - Sensor org.sonar.plugins.findbugs.FindbugsSensor@7894f007 (done) | time=103809ms
11:29:31.499 INFO  - Sensor SurefireSensor
11:29:31.500 INFO  - parsing /myprojects/build/test-results
11:29:31.558 INFO  - Sensor SurefireSensor (done) | time=59ms
11:29:31.558 INFO  - Sensor JaCoCoOverallSensor
11:29:31.565 WARN  - You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.
11:29:31.565 INFO  - Analysing /myprojects/build/jacoco/test.exec
11:29:31.601 WARN  - You are not using the latest JaCoCo binary format version, please consider upgrading to latest JaCoCo version.
......... Ommitted .............
11:30:38.654 INFO  - ANALYSIS SUCCESSFUL, you can browse http://sonar:8080/dashboard/index/com.wordpress.mrvivekr:project
11:30:38.654 INFO  - Note that you will be able to access the updated dashboard once the server has processed the submitted analysis report.
11:30:38.655 INFO  - Executing post-job class org.sonar.plugins.buildbreaker.AlertBreaker
11:30:38.657 INFO  - Executing post-job class org.sonar.plugins.buildbreaker.ForbiddenConfigurationBreaker

BUILD SUCCESSFUL

Total time: 5 mins 16.499 secs

You should see a similar output:

Image title

Happy Code Analysis!

Learn about the importance of automated testing as part of a healthy DevOps practice, brought to you in partnership with Sauce Labs.

Topics:
gradle ,pmd ,findbugs ,gradle:goodness ,code analysis ,sonar

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}