java-quality

Java Quality - Quick Reference

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "java-quality" with this command: npx skills add claude-dev-suite/claude-dev-suite/claude-dev-suite-claude-dev-suite-java-quality

Java Quality - Quick Reference

When NOT to Use This Skill

  • SonarQube generic setup - Use sonarqube skill

  • Spring Boot testing - Use Spring Boot test skills

  • Security scanning - Use java-security skill

  • Coverage reporting - Use jacoco skill

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: spring-boot for framework-specific patterns.

Tool Overview

Tool Focus Speed Integration

Checkstyle Code style, formatting Fast Maven/Gradle

SpotBugs Bug patterns, bytecode Medium Maven/Gradle

PMD Code smells, complexity Fast Maven/Gradle

SonarJava All-in-one Slow SonarQube

Error Prone Compile-time bugs Fast Compiler plugin

Checkstyle Setup

Maven Configuration

<!-- pom.xml --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <version>3.3.1</version> <configuration> <configLocation>checkstyle.xml</configLocation> <consoleOutput>true</consoleOutput> <failsOnError>true</failsOnError> <violationSeverity>warning</violationSeverity> </configuration> <executions> <execution> <id>validate</id> <phase>validate</phase> <goals> <goal>check</goal> </goals> </execution> </executions> <dependencies> <dependency> <groupId>com.puppycrawl.tools</groupId> <artifactId>checkstyle</artifactId> <version>10.12.5</version> </dependency> </dependencies> </plugin>

checkstyle.xml (Google Style Based)

<?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"> <property name="severity" value="warning"/> <property name="fileExtensions" value="java"/>

&#x3C;module name="TreeWalker">
    &#x3C;!-- Naming -->
    &#x3C;module name="ConstantName"/>
    &#x3C;module name="LocalVariableName"/>
    &#x3C;module name="MemberName"/>
    &#x3C;module name="MethodName"/>
    &#x3C;module name="PackageName"/>
    &#x3C;module name="ParameterName"/>
    &#x3C;module name="TypeName"/>

    &#x3C;!-- Imports -->
    &#x3C;module name="IllegalImport"/>
    &#x3C;module name="RedundantImport"/>
    &#x3C;module name="UnusedImports"/>

    &#x3C;!-- Size -->
    &#x3C;module name="LineLength">
        &#x3C;property name="max" value="120"/>
    &#x3C;/module>
    &#x3C;module name="MethodLength">
        &#x3C;property name="max" value="50"/>
    &#x3C;/module>
    &#x3C;module name="ParameterNumber">
        &#x3C;property name="max" value="5"/>
    &#x3C;/module>

    &#x3C;!-- Complexity -->
    &#x3C;module name="CyclomaticComplexity">
        &#x3C;property name="max" value="10"/>
    &#x3C;/module>
    &#x3C;module name="NPathComplexity">
        &#x3C;property name="max" value="200"/>
    &#x3C;/module>

    &#x3C;!-- Best Practices -->
    &#x3C;module name="EmptyBlock"/>
    &#x3C;module name="EqualsHashCode"/>
    &#x3C;module name="HiddenField"/>
    &#x3C;module name="MissingSwitchDefault"/>
    &#x3C;module name="SimplifyBooleanExpression"/>
    &#x3C;module name="SimplifyBooleanReturn"/>
&#x3C;/module>

&#x3C;!-- File-level checks -->
&#x3C;module name="FileLength">
    &#x3C;property name="max" value="500"/>
&#x3C;/module>
&#x3C;module name="NewlineAtEndOfFile"/>

</module>

Commands

Run Checkstyle

./mvnw checkstyle:check

Generate report

./mvnw checkstyle:checkstyle

SpotBugs Setup

Maven Configuration

<!-- pom.xml --> <plugin> <groupId>com.github.spotbugs</groupId> <artifactId>spotbugs-maven-plugin</artifactId> <version>4.8.3.0</version> <configuration> <effort>Max</effort> <threshold>Medium</threshold> <failOnError>true</failOnError> <plugins> <plugin> <groupId>com.h3xstream.findsecbugs</groupId> <artifactId>findsecbugs-plugin</artifactId> <version>1.12.0</version> </plugin> </plugins> </configuration> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>

Exclude False Positives

<!-- spotbugs-exclude.xml --> <?xml version="1.0" encoding="UTF-8"?> <FindBugsFilter> <!-- Exclude generated code --> <Match> <Package name="~..generated.."/> </Match>

&#x3C;!-- Exclude specific patterns -->
&#x3C;Match>
    &#x3C;Bug pattern="EI_EXPOSE_REP"/>
    &#x3C;Class name="~.*Dto"/>
&#x3C;/Match>

</FindBugsFilter>

Commands

Run SpotBugs

./mvnw spotbugs:check

Generate report

./mvnw spotbugs:spotbugs

GUI viewer

./mvnw spotbugs:gui

Common SpotBugs Warnings

Bug ID Description Fix

NP_NULL_ON_SOME_PATH Possible null dereference Add null check or use Optional

EI_EXPOSE_REP Returns mutable object Return defensive copy

MS_SHOULD_BE_FINAL Static field should be final Add final modifier

SQL_INJECTION SQL injection risk Use parameterized queries

DM_DEFAULT_ENCODING Uses default encoding Specify charset explicitly

PMD Setup

Maven Configuration

<!-- pom.xml --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-pmd-plugin</artifactId> <version>3.21.2</version> <configuration> <rulesets> <ruleset>pmd-rules.xml</ruleset> </rulesets> <failOnViolation>true</failOnViolation> <printFailingErrors>true</printFailingErrors> </configuration> <executions> <execution> <goals> <goal>check</goal> </goals> </execution> </executions> </plugin>

pmd-rules.xml

<?xml version="1.0"?> <ruleset name="Custom Rules"> <description>Custom PMD ruleset</description>

&#x3C;!-- Best Practices -->
&#x3C;rule ref="category/java/bestpractices.xml">
    &#x3C;exclude name="JUnitTestContainsTooManyAsserts"/>
&#x3C;/rule>

&#x3C;!-- Code Style -->
&#x3C;rule ref="category/java/codestyle.xml">
    &#x3C;exclude name="AtLeastOneConstructor"/>
    &#x3C;exclude name="OnlyOneReturn"/>
&#x3C;/rule>

&#x3C;!-- Design -->
&#x3C;rule ref="category/java/design.xml">
    &#x3C;exclude name="LawOfDemeter"/>
&#x3C;/rule>

&#x3C;!-- Error Prone -->
&#x3C;rule ref="category/java/errorprone.xml"/>

&#x3C;!-- Performance -->
&#x3C;rule ref="category/java/performance.xml"/>

&#x3C;!-- Custom thresholds -->
&#x3C;rule ref="category/java/design.xml/CyclomaticComplexity">
    &#x3C;properties>
        &#x3C;property name="methodReportLevel" value="10"/>
    &#x3C;/properties>
&#x3C;/rule>

&#x3C;rule ref="category/java/design.xml/CognitiveComplexity">
    &#x3C;properties>
        &#x3C;property name="reportLevel" value="15"/>
    &#x3C;/properties>
&#x3C;/rule>

</ruleset>

Commands

Run PMD

./mvnw pmd:check

Generate report

./mvnw pmd:pmd

Copy-paste detection

./mvnw pmd:cpd

Error Prone Setup

Maven Configuration

<!-- pom.xml --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.12.1</version> <configuration> <compilerArgs> <arg>-XDcompilePolicy=simple</arg> <arg>-Xplugin:ErrorProne</arg> </compilerArgs> <annotationProcessorPaths> <path> <groupId>com.google.errorprone</groupId> <artifactId>error_prone_core</artifactId> <version>2.24.1</version> </path> </annotationProcessorPaths> </configuration> </plugin>

Combined Quality Profile

All-in-One Maven Profile

<!-- pom.xml --> <profiles> <profile> <id>quality</id> <build> <plugins> <!-- Checkstyle --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-checkstyle-plugin</artifactId> <executions> <execution> <goals><goal>check</goal></goals> </execution> </executions> </plugin>

            &#x3C;!-- SpotBugs -->
            &#x3C;plugin>
                &#x3C;groupId>com.github.spotbugs&#x3C;/groupId>
                &#x3C;artifactId>spotbugs-maven-plugin&#x3C;/artifactId>
                &#x3C;executions>
                    &#x3C;execution>
                        &#x3C;goals>&#x3C;goal>check&#x3C;/goal>&#x3C;/goals>
                    &#x3C;/execution>
                &#x3C;/executions>
            &#x3C;/plugin>

            &#x3C;!-- PMD -->
            &#x3C;plugin>
                &#x3C;groupId>org.apache.maven.plugins&#x3C;/groupId>
                &#x3C;artifactId>maven-pmd-plugin&#x3C;/artifactId>
                &#x3C;executions>
                    &#x3C;execution>
                        &#x3C;goals>&#x3C;goal>check&#x3C;/goal>&#x3C;/goals>
                    &#x3C;/execution>
                &#x3C;/executions>
            &#x3C;/plugin>
        &#x3C;/plugins>
    &#x3C;/build>
&#x3C;/profile>

</profiles>

Run all quality checks

./mvnw verify -Pquality

Common Code Smells & Fixes

  1. God Class

// BAD - Class does too much public class OrderService { public Order createOrder() { ... } public void sendEmail() { ... } public void generatePdf() { ... } public void calculateTax() { ... } public void updateInventory() { ... } }

// GOOD - Single responsibility public class OrderService { private final EmailService emailService; private final PdfGenerator pdfGenerator; private final TaxCalculator taxCalculator; private final InventoryService inventoryService;

public Order createOrder(OrderRequest request) {
    Order order = buildOrder(request);
    order.setTax(taxCalculator.calculate(order));
    inventoryService.reserve(order.getItems());
    return orderRepository.save(order);
}

}

  1. Long Parameter List

// BAD public void createUser(String name, String email, String phone, String address, String city, String country, String zipCode) { }

// GOOD - Use builder or DTO public void createUser(CreateUserRequest request) { }

@Builder public record CreateUserRequest( String name, String email, String phone, Address address ) {}

  1. Feature Envy

// BAD - Method uses another object's data excessively public double calculateTotal(Order order) { double total = 0; for (OrderItem item : order.getItems()) { total += item.getPrice() * item.getQuantity(); if (item.getDiscount() > 0) { total -= item.getPrice() * item.getQuantity() * item.getDiscount(); } } return total; }

// GOOD - Move logic to Order public class Order { public double calculateTotal() { return items.stream() .mapToDouble(OrderItem::getSubtotal) .sum(); } }

public class OrderItem { public double getSubtotal() { double base = price * quantity; return discount > 0 ? base * (1 - discount) : base; } }

  1. Primitive Obsession

// BAD public void sendEmail(String email) { if (!email.matches("^[A-Za-z0-9+_.-]+@(.+)$")) { throw new IllegalArgumentException("Invalid email"); } }

// GOOD - Value object public record Email(String value) { public Email { if (!value.matches("^[A-Za-z0-9+_.-]+@(.+)$")) { throw new IllegalArgumentException("Invalid email: " + value); } } }

public void sendEmail(Email email) { ... }

  1. Deep Nesting

// BAD public void process(Order order) { if (order != null) { if (order.isValid()) { for (OrderItem item : order.getItems()) { if (item.isAvailable()) { if (item.getQuantity() > 0) { // process } } } } } }

// GOOD - Guard clauses public void process(Order order) { if (order == null || !order.isValid()) { return; }

order.getItems().stream()
    .filter(OrderItem::isAvailable)
    .filter(item -> item.getQuantity() > 0)
    .forEach(this::processItem);

}

Quality Metrics Targets

Metric Target Tool

Cyclomatic Complexity < 10 Checkstyle, PMD

Cognitive Complexity < 15 PMD, SonarQube

Method Length < 50 lines Checkstyle

Class Length < 500 lines Checkstyle

Parameters < 5 Checkstyle

Nesting Depth < 4 PMD

CI/CD Integration

GitHub Actions

name: Quality on: [push, pull_request]

jobs: quality: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4

  - name: Set up JDK
    uses: actions/setup-java@v4
    with:
      java-version: '21'
      distribution: 'temurin'
      cache: maven

  - name: Run quality checks
    run: ./mvnw verify -Pquality

  - name: Upload reports
    uses: actions/upload-artifact@v4
    if: always()
    with:
      name: quality-reports
      path: |
        target/checkstyle-result.xml
        target/spotbugsXml.xml
        target/pmd.xml

Anti-Patterns

Anti-Pattern Why It's Bad Correct Approach

Suppressing all warnings Hides real issues Fix or justify individually

No static analysis in CI Quality degrades over time Add to build pipeline

Only running Checkstyle Misses bugs and smells Combine with SpotBugs + PMD

High complexity thresholds Allows unmaintainable code Keep < 10 cyclomatic

Excluding entire packages Ignores quality in areas Be specific with exclusions

Quick Troubleshooting

Issue Likely Cause Solution

Checkstyle fails on generated code No exclusion pattern Add <exclude> for generated dirs

SpotBugs false positive on DTO EI_EXPOSE_REP on records Exclude pattern for DTOs

PMD too slow Analyzing all files Configure incremental analysis

Error Prone conflicts Version mismatch Align with JDK version

Quality gate fails in CI Different config locally Commit config files

Related Skills

  • SonarQube

  • JaCoCo

  • Clean Code

  • Java Security

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

cron-scheduling

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

token-optimization

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

react-19

No summary provided by upstream source.

Repository SourceNeeds Review