點燈坊

學而時習之,不亦悅乎

如何使用 SonarQube 檢查 Java 專案 ?

Sam Xiao's Avatar 2019-05-19

SonarQube 已經內建 SonarJava,可以直接對 Java 進行檢查,本文將以 Java + Gradle 為例,並在 Eclipse 中使用 SonarLint 對 Java 專案進行檢查。

Version

macOS High Sierra 10.13.4
SonarQube 7.1
SonarQube Scanner 3.1.0.1141
Eclipse Oxygen.3a (4.7 3a)
Java SE 1.8.0_171

GitHub

java000

  1. 本文將 Java 專案放在 https://github.com/oomusou/javasonarqube

Gradle

Installation

$ brew install gradle

Gradle 類似 JavaScript 世界的 Webpack,負責整個專案的編譯管理,使用 Homebrew 安裝。

Project Initialization

$ gradle init --type java-application

下載範例後,進入專案目錄,使用 Gradle 對專案初始化。

java001

Build Project

$ ./gradlew build

使用 Gradle 第一次 build 專案。

java002

Eclipse

Install Plugin

java003

Help -> Eclipse Marketplace…

java004

請安裝以下兩個套件:

  1. Buildship Gradle Integration 2.0:在 Eclipse 使用 Gradle 建置專案
  2. SonarLint 3.5:讓 Eclipse 能即時執行 SonarQube 檢查

Import Project

java005

File -> Import

java006

  1. 選擇 Gradle -> Existing Gradle Project
  2. Next 繼續

java007

  1. 選擇專案目錄
  2. Next 繼續

java008

  1. Finish 結束

Add SonarQube Plugin

build.gradle

/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Java project to get you started.
 * For more details take a look at the Java Quickstart chapter in the Gradle
 * user guide available at https://docs.gradle.org/4.7/userguide/tutorial_java_projects.html
 */

plugins {
    // Apply the java plugin to add support for Java
    id 'java'

    // Gradle plugin to help analyzing projects with SonarQube
    id 'org.sonarqube' version '2.6.2'

    // Apply the application plugin to add support for building an application
    id 'application'
}

// Define the main class for the application
mainClassName = 'App'

dependencies {
    // This dependency is found on compile classpath of this component and consumers.
    compile 'com.google.guava:guava:23.0'

    // Use JUnit test framework
    testCompile 'junit:junit:4.12'
}

// In this section you declare where to find the dependencies of your project
repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

13 行

// Gradle plugin to help analyzing projects with SonarQube
id 'org.sonarqube' version '2.6.2'

在 Gradle 新增 SonarQube plugin,將來可透過 Gradle 執行 SonarQube。

java009

  1. 開啟 build.gradle 檔案
  2. 新增 SonarQube plugin

Build Project

java010

  1. 右側 Gradle Tasks
  2. build 展開,執行 build
  3. 在 Console 出現 BUILD SUCCESSFUL 表示建置成功

目前為止,Gradle 在 Eclipse 已經正常執行,接下來要設定 SonarQube

SonarQube

Installation

$ brew install sonarqube

使用 Homebrew 安裝 SonarQube。

Start SonarQube

$ sonar console

使用 sonar console 自行啟動 SonarQube。

java011

Test SonarQube

java012

  1. 輸入 localhost:9000,若看到 SonarQube 首頁,則表示安裝成功
  2. 右上角 Log in 可登入管理設定 SonarQube,預設為 admin/admin

SonarQube Scanner

SonarQube 雖然已經包含 SonarJava,但必須靠 SonarQube Scanner 才能執行,預設 SonarQube 並沒有包含 Scanner,必須自行安裝。

Installation

$ brew install sonar-scanner

Configuration

sonar-scanner.properties

#Configure here general information about the environment, such as SonarQube server connection details for example
#No information about specific project should appear here

#----- Default SonarQube server
sonar.host.url=http://localhost:9000

#----- Default source code encoding
#sonar.sourceEncoding=UTF-8

將第 5 行的 # 拿掉,設定 SonarQube server 的 URL 位址。

java013

  1. 將目錄移到 /usr/local/Cellar/sonar-scanner/3.1.0.1141/libexec/conf
  2. 開啟 sonar-scanner.properties
  3. 使用 vim 開啟 sonar-scanner.properties

java014

  1. 設定 SonarQube server

Test Scanner

$ gradle sonarqube

使用 Gradle 執行 SonarQube 檢查。

java015

Result

java016

進入 SonarQube 網頁,就可看到 JavaSonarQube 專案已經出現 SonarQube。

目前為止,SonarQube 已經可以正常透過 Gradle 執行,實務上可以透過 Jenkins 執行 Gradle,就可自動執行 SonarQube,但這種方式較被動,若發現有任何 issue,還要開 ticket 要求修改,一來一回可能好幾天,若能在開發階段就即時 SonarQube 檢查,就能「及早發現,及早治療」。

SonarLint

java017

在 Code Smell 部分,SonarQube 已經檢查出:

  • Move this file to a named package
  • Remove this method and declare a constant for this variable
  • Replace this use of System.out or System.err by a logger

若能在 Eclipse 也能顯示這些警告訊息,那就太好了。

Connet to SonarQube Server

java018

  1. 選擇專案按滑鼠右鍵
  2. 選擇 SonarLint
  3. 選擇 Bind to a SonarQube project…

java019

  1. Connect to a SonarQube server…

java020

  1. 選擇 sonarqube
  2. Next 繼續

java021

  1. 輸入 SonarQube server 網址
  2. Next 繼續

java022

  1. 選擇 Username + Password
  2. Next 繼續

java023

  1. 輸入 SonarQube 帳號與密碼
  2. Next 繼續

java024

  1. 輸入 connection 名稱
  2. Next 繼續

java025

  1. Finish 完成設定

java026

  1. 是否要 Eclipse 提供 Password hint,選 NoYes 都可以

java027

  1. Finish 完成連接 SonarQube server 動作

java028

  1. 顯示 SonarQube 連線正常

Analyze by SonarLint

java029

  1. 選擇專案按滑鼠右鍵
  2. 選擇 SonarLint
  3. 選擇 Analyze

java030

  1. 下方顯示了與 SonarQube 網頁完全相同的警告,因此 developer 在開發階段,就可以完全獲得 SonarQube 的支援

java031

  1. 在 editor 也會即時警告
  2. 將滑鼠放在警告之上,也會顯示與 SonarQube 相同的警告訊息

java032

  1. 點選 SonarLint Rule Description,會顯示更詳細解釋,甚至還有範例說明

Conclusion

  • 有了 SonarLint,developer 就能更即時獲得 SonarQube 建議,養成 clean code 好習慣

Sample Code

完整範例可以在我的 GitHub 上找到

Appendix

JAVA_HOME

~/.bash_profile

export JAVA_HOME=$(/usr/libexec/java_home)

這裡在執行 Gradle 時遇到一個雷,由於 Gradle 與 Eclipse 都會依賴系統變數 $JAVA_HOME,必須在 bash_profile 設定 $JAVA_HOME 才會讓 Gradle 與 Eclipse 順利抓到,而不能只設定在 .zshrc ,所以不要覺得在 iTerm 2 能 echo $JAVA_HOME 就沒事,畢竟 Gradle 與 Eclipse 不是吃 .zshrc,而是吃 .bash_profile