Maximize Page
Tech & DevOps HubEspace Tech & DevOps: Explorez le monde du Dev, du Cloud et des outils DevOps à travers nos articles et discussions Explore the world of development, the cloud and DevOps tools

Sécuriser la qualité du code avec Spotless, Checkstyle & SpotBugs

Date de l'article:04-10-2025
CI/CD Spring Boot
Intégration de trois outils complémentaires: Spotless pour le formatage automatique, Checkstyle pour le lint et SpotBugs pour l'analyse statique. Nous verrons les stratégies d'intégration et les cas particuliers comme Lombok

Cet article explore l'intégration de Spotless, Checkstyle et SpotBugs dans un projet Java/Spring Boot afin d'améliorer durablement la qualité du code, depuis leur configuration Maven jusqu'à l'analyse des rapports et la gestion des erreurs, tout en adaptant les règles aux besoins du projet


Outils et usages
Outil Type Pour Qui Rôles Seuils CI (recommandés)
Spotless Formatage Dev & CI Normalisation automatique du code Échec si non-formaté
Checkstyle Lint Dev & CI Respect des conventions de nommage, structure, Javadoc 0 violations
SpotBugs Analyse statique Dev & CI Détection des bugs logiques grave (boucle infinie, null) 0 HIGH
SonarQube / SonarCloud Analyse complète Dev, CI, Management Qualité et sécurité globale du code, dette technique, sécurité Quality Gate ≥ 80%

L'association de ces outils permet de construire une véritable barrière qualité, active à la fois en local et dans le pipeline CI

  • Spotless corrige automatiquement le formatage
  • Checkstyle impose les conventions de code
  • SpotBugs détecte les erreurs logiques potentielles
  • SonarCloud apporte une vision globale et consolidée
Spotless évite la majorité des violations Checkstyle
Tous les outils peuvent être exécutés en local avant commit
       Dans la CI, tout échec bloque le build

   Ensemble, ils interviennent avant même les tests unitaires
  Chaîne logique: Spotless (corrige) → Checkstyle (impose le style) → SpotBugs (détecte les bugs) → Les tests (valident le comportement) → Sonar


Ordre d'exécution
En local / Pull Requests
  • On défini un seuil de couverture (JaCoco) pour la Quality Gates, faible au début
  • Les développeurs exécutent, en Local: Spotless → Checkstyle → SpotBugs
    • Les Test Unitaires sont lançés, ils donnent la couverture du code
    • On peux consulter les rapports depuis le rapport généré (folder target/site/JaCoCo)
  • Les développeurs envoyes le code via des PR checks:
    • Après avoir été testé et validé en local, le code est envoyé dans le repository et analysé avant d'être accepté au merge
Dans la CI
Les DevOps intègrent les outils dans les pipelines CI, c'est l'aspect le plus critique:
  • Le pipeline passe la suite logique: Formatage (Spotless) → Analyse de style (Checkstyle) → Analyse statique (SpotBugs) → Tests unitaires
    • Le pipeline échoue automatiquement si: le code mal formaté, qu'il détectes des bugs ou trouve une ou des violations critiques
  • L'analyse SonarCloud:
    • Èchoue automatiquement si la couverture est insuffisante
  • S'il est vert, SonarQube Cloud * apporte un "reporting global"
    • *: SonarQube tire son analyse des rapport JaCoCo
    • Avec le Plan Free: Seul la branche (main) finale est analysée (et les PR envoyés depuis main). Le rapport est public et peut être vu: sonarcloud.io
  • Packaging

Intégration des plugins

L'intégration dans Maven permet d'uniformiser le comportement entre les postes développeurs et le CI

Spotless
<properties> //...
  <spotless.plugin.version>2.43.0
  </properties> 
  //...

<!-- Spotless -->
<plugin>
  <groupId>com.diffplug.spotless</groupId>
  <artifactId>spotless-maven-plugin</artifactId>
  <version>${spotless.plugin.version}</version>
  <configuration>
    <java>
      <googleJavaFormat/>
    </java>
  </configuration>
</plugin>

Spotless Assure un formatage homogène
Il répare automatiquement le code via la commande "spotless:apply"

→  Le résultat attendu est un BUILD SUCCESS
Checkstyle (config sans personalisation)
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>3.3.1</version>
  <configuration>
    <configLocation>google_checks.xml</configLocation>
    <consoleOutput>true</consoleOutput>
    <failsOnError>true</failsOnError>
    <linkXRef>false</linkXRef>
  </configuration>
  <executions>
    <execution>
      <phase>verify</phase>
         <goals>
           <goal>check</goal>
           </goals>
     </execution>
  </executions>
</plugin>
pour la config personnalisée, voir la partie + bas: "Ajout de fichier custom et de suppression"

Spotbug
<plugin>
  <groupId>com.github.spotbugs</groupId>
  <artifactId>spotbugs-maven-plugin</artifactId>
  <version>4.8.6</version>
  <configuration>
    <failOnError>true</failOnError>
  </configuration>
</plugin>

SpotBugs effectue une analyse statique avancée.
      Il Bloque le build si une anomalie (critique) est détectée

Checkstyle, en utilisation d'une configuration standard (Google ou Sun) effectue les vérification des conventions, contrôle de structure et détecte les mauvaises pratiques.
Il est exécuté dans la phase "verify"

Commandes associées
  • Formatage automatique: ./mvnw spotless:apply
  • Build complet: ./mvnw clean verify
  • ou, en commandes ciblées:
    ./mvnw checkstyle:check
    ./mvnw spotbugs:check

Commande d'exécution initiale

Lors de la première exécution, il est fréquent d'obtenir un échec:

$ ./mvnw checkstyle:check
//download and install pour une première utilisation
[INFO] -----------------------< com.example:flashcards >---------------
[INFO] 
[INFO] --- checkstyle:3.6.0:check (default-cli) @ flashcards ---

[INFO] There are 16 errors reported by Checkstyle 9.3 with sun_checks.xml 
                                                                  ruleset
[INFO] -----------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] -----------------------------------------------------------------
Les erreurs reportées signifient que le code ne respecte pas encore les conventions définies (ici "sun_check" qui défini des règles assez strictes par défaut)

Le rapport - Résultats types et gestion des erreurs

Quand Checkstyle bloque un build :
- Chaque non-conformité remonte avec ses détails:
  Ligne trop longue, paramètres non final, imports globaux, etc

Un rapport détaillé est alors généré dans: /target/checkstyle.xml


Stratégies d'intégration possibles
Option 1 - Mode Strict (recommandé)
  • Le build échoue dès la moindre violation
  • Garantit du “enterprise grade”: Progression par correction successive.
Idéal pour:
  • Les projets récents
  • Les équipes disciplinées
  • La réduction de la dette technique

Option 2 - Mode Tolérant (transition)
  • Les erreurs sont affichées mais non bloquantes
  • Permet une adoption progressive en équipe
Ajoutez "failOnViolation" pour afficher les erreurs sans bloquer le pipeline:
<configuration>
      //..
     <failOnViolation>false</failOnViolation>
</configuration>
ou, en ligne de commande :
./mvnw checkstyle:check -Dcheckstyle.failOnViolation=false
Il affichera toujours les erreurs, mais le build ne sera plus “FAILURE”
Option 3 - Styles personnalisé (inspiré de Google ou d'un style d'équipe)

Permet de désactiver les règles trop strictes pour avoir un style plus souple

  • Télécharger le fichier officiel Google Style: Google
  • L'ajouter dans le projet: (ex : config/checkstyle/google_checks.xml)
  • Le référencer dans pom.xml avec:
      <configLocation>
            config/checkstyle/google_checks.xml
        </configLocation>

Recommandé pour les projets long terme


Option 4 - Désactivation temporaire

Utilisé uniquement en phase de migration ou de refactoring massif

→ Commentez les lignes du mode strict et utilisez le mode tolérant:
# - name: Run Checkstyle
#   run: ./mvnw checkstyle:check

- name: Run Checkstyle (non-blocking)
  run: ./mvnw checkstyle:check 
       -Dcheckstyle.failOnViolation=false
Ma décision concernant mon projet Flashcards:

Étant le développeur et le devOps, j'ai choisi le mode strict, ainsi je n'accumule pas de dette technique
En entreprise, en tant que devOps, j'aurais activé le mode tolérant, le temps que le développeur corrige toutes les erreurs relevés


Cas courants et correctifs
Absence de Javadoc
Cause: → méthodes publiques non documentées
Bonne pratique:
  • documenter classes et API publiques
  • décrire paramètres et retours
  • première phrase claire et complète
Trailing spaces
Cause:
→ Espaces en fin de ligne
Correction:
→ Automatiser via l'IDE

Spotless corrige généralement ce problème
Imports génériques (import.*)
Problèmes:
  • lisibilité réduite
  • ambiguïtés
  • incohérences CI
Bonne pratique:
  • imports explicites
  • tri alphabétique
  • regroupement cohérent
Problèmes d'indentation
Erreurs fréquentes:
  • tabs vs espaces
  • niveaux incohérents
Recommandation:
  • 4 espaces par niveau
  • aucune tabulation

Cas particulier: Lombok + Checkstyle
Problème:
Lombok génère du code à la compilation (getters, setters, builders, etc.)
Mais, Checkstyle analyse uniquement le code source, pas le code généré!
Résultat: Faux positifs fréquents, erreurs Javadoc inexistantes, méthodes "manquantes"

Si Checkstyle n'est pas encore configuré, il utilisera la configuration par défaut

Solution
  1. Créer un fichier "checkstyle.xml" personnalisé
  2. Ajouter un fichier "checkstyle-suppressions.xml"
Ignorer certaines règles sur: les DTO, entités, tests

Cela permet de garder Checkstyle strict sans pénaliser le code généré

1. Créer le fichier "config/checkstyle/checkstyle.xml"
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
        "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
        "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
    <!-- Vérifie la longueur des lignes -->
    <module name="LineLength">
        <property name="max" value="120"/>
        <property name="ignorePattern" value="^package.*|^import.*|a href|href|http|https"/>
    </module>

    <!-- Vérifie les tabulations -->
    <module name="FileTabCharacter">
        <property name="eachLine" value="true"/>
    </module>

    <!-- Analyse syntaxique du code Java -->
    <module name="TreeWalker">
        <module name="UnusedImports"/>
        <module name="AvoidStarImport"/>
        <module name="Indentation"/>
        <module name="NeedBraces"/>
        <module name="MethodLength">
          <property name="max" value="100"/>
        </module>
        <module name="ParameterName"/>
        <module name="LocalVariableName"/>
        <module name="MemberName"/>
    </module>
</module>
2. Créer le fichier "checkstyle-suppressions.xml"
<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
    "-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
    "https://checkstyle.org/dtds/suppressions_1_2.dtd">

<suppressions>
  <!-- Ignore Lombok-generated code -->
  <suppress files=".*[/\\]model[/\\].*" checks="MissingJavadocMethod"/>
  <suppress files=".*[/\\]entity[/\\].*" checks="MissingJavadocMethod"/>
  <suppress files=".*[/\\]dto[/\\].*" checks="MissingJavadocMethod"/>

  <!-- Ignore test files -->
  <suppress files=".*Test\.java" checks="JavadocMethod"/>
</suppressions>
3. Ajouter les chemins de fichiers au plugin
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-checkstyle-plugin</artifactId>
  <version>3.3.1</version>
  <configuration>
    <configLocation>config/checkstyle/checkstyle.xml</configLocation>
    <suppressionsLocation>checkstyle-suppressions.xml</suppressionsLocation>    
    <consoleOutput>true</consoleOutput>
    <failsOnError>true</failsOnError>
  </configuration>
  <executions>
    <execution>
      <phase>verify</phase>
         <goals>
           <goal>check</goal>
           </goals>
     </execution>
  </executions>
</plugin>

Avantage: On garde Checkstyle strict sur le reste du code. Et, on évite les faux positifs sur le code Lombok ou boilerplate Spring Boot


SpotBugs: Lecture des résultats
Lancer la commande:
$ ./mvnw -e SpotBugs:check  
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO] -----------------------< com.example:flashcards >----------------
[INFO] Building flashcards 0.0.1-SNAPSHOT
[INFO]   from pom.xml
[INFO] -----------------------------[ jar ]------------------------------
[INFO] >>> spotbugs:4.8.6.2:check (default-cli) > :spotbugs @ flashcards >>>
[INFO] --- spotbugs:4.8.6.2:spotbugs (spotbugs) @ flashcards ---
[INFO] Fork Value is true
[INFO] Done SpotBugs Analysis....
[INFO] <<< spotbugs:4.8.6.2:check (default-cli) < :spotbugs @ flashcards <<<
[INFO]
[INFO] --- spotbugs:4.8.6.2:check (default-cli) @ flashcards ---
[INFO] BugInstance size is 0
[INFO] Error size is 0
[INFO] No errors/warnings found
[INFO] -----------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] -----------------------------------------------------------------

Un build vert indique:
Aucune anomalie critique - Aucun bug potentiel détecté Bilan après intégration:
→ Code conforme aux standards Java
→ Formatage homogène
→ Aucune anomalie critique détectée

pipeline CI sécurisé dès l'étape qualité


Recommandations
→ Intègrer Checkstyle et SpotBugs très tôt dans le cycle de vie du projet
→ Rendre Checkstyle obligatoire au fil du temps;
     Commencer en mode tolérant, lors des phases de mise en place
→ Documenter, automatiser, faites évoluer les règles avec l'équipe
Cette approche garantit la qualité du code, gain de temps lors des revues, l'intégration continue fiabilisée, et une base saine pour le scaling du projet

L'article suivant couvrira JaCoco, SonarCloud, et la Quality Gates, en local et dans un pipeline multi-branches


Laissez-moi un commentaire

En postant un commentaire anonyme, vous adhérez automatiquement aux conditions d'utilisation du site.