Skip to main content

Feature 8: Code Quality & Developer Experience

Purpose: This guide provides step-by-step instructions for implementing code quality enforcement and developer experience improvements.

Dependencies:

Related Documents:


Overview

What This Guide Covers

Code Quality & Developer Experience enforces code quality and improves developer workflow:

  • Checkstyle configuration (strict enforcement)
  • Checkstyle suppressions file (exclude generated sources)
  • Hibernate logging configuration
  • Detailed logging configuration

What's Included:

  • build.gradle configuration changes
  • checkstyle-suppressions.xml file
  • application.yml logging configuration
  • Code quality enforcement workflow

What's NOT Included:

  • ❌ OpenAPI Generator setup (separate guide)
  • ❌ Custom checkstyle rules (uses standard rules)
  • ❌ Custom logging appenders (uses default configuration)

Prerequisites

  • Springular boilerplate setup
  • Understanding of Gradle build configuration
  • Understanding of Checkstyle
  • Understanding of Spring Boot logging

Implementation Steps

Step 1: Configure Checkstyle Plugin

File: server/build.gradle

Purpose: Configure Checkstyle plugin with strict enforcement for code quality.

Key Points:

  • ✅ Strict enforcement (maxWarnings = 0)
  • ✅ Excludes generated sources
  • ✅ Configures checkstyle.xml location
  • ✅ Integrated with build process

Find plugins block and add (if not already present):

plugins {
// ... existing plugins ...

id 'checkstyle'
}

Add checkstyle configuration (after dependencies block or in appropriate section):

checkstyle {
toolVersion = '10.12.5'
configFile = file("$projectDir/config/checkstyle/checkstyle.xml")
maxWarnings = 0 // Strict enforcement - no warnings allowed
}

Configure sourceSets to exclude generated sources:

sourceSets {
main {
java {
srcDirs = ['src/main/java']
exclude '**/generated/**'
}
}
test {
java {
srcDirs = ['src/test/java']
exclude '**/generated/**'
}
}
}

// Exclude generated sources from checkstyle
tasks.named('checkstyleMain') {
exclude '**/generated/**'
}

tasks.named('checkstyleTest') {
exclude '**/generated/**'
}

Complete checkstyle configuration example:

checkstyle {
toolVersion = '10.12.5'
configFile = file("$projectDir/config/checkstyle/checkstyle.xml")
maxWarnings = 0 // Strict enforcement
}

sourceSets {
main {
java {
srcDirs = ['src/main/java']
exclude '**/generated/**'
}
}
}

tasks.named('checkstyleMain') {
exclude '**/generated/**'
source = sourceSets.main.java
}

Why maxWarnings = 0:

  • Prevents code style drift
  • Catches issues in CI/CD
  • Ensures consistent code quality
  • Better code review experience

Step 2: Create Checkstyle Suppressions File

File: server/config/checkstyle/checkstyle-suppressions.xml

Purpose: Suppress checkstyle warnings for generated code.

Key Points:

  • ✅ Excludes OpenAPI generated code
  • ✅ Excludes DDL generated code
  • ✅ Allows generated sources without checkstyle errors

Create file:

<?xml version="1.0"?>
<!DOCTYPE suppressions PUBLIC
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
"https://checkstyle.org/dtds/suppressions_1_2.dtd">

<suppressions>
<!-- Exclude all generated OpenAPI sources -->
<suppress checks=".*" files=".*/build/generated-sources/.*"/>
<suppress checks=".*" files=".*/generated-sources/.*"/>

<!-- Exclude specific generated packages (if any) -->
<!-- Example: AI-generated packages would go here if using OpenAPI Generator for AI -->
<!-- <suppress checks=".*" files=".*/com/saas/springular/common/ai/model/.*"/> -->
<!-- <suppress checks=".*" files=".*/com/saas/springular/common/ai/api/.*"/> -->

<!-- Exclude specific checkstyle rules for generated code (optional, checks=".*" above covers all) -->
<!-- These are redundant if checks=".*" is used, but included for clarity -->
<suppress checks="Indentation" files=".*/generated-sources/.*"/>
<suppress checks="CustomImportOrder" files=".*/generated-sources/.*"/>
<suppress checks="AvoidStarImport" files=".*/generated-sources/.*"/>
<suppress checks="UnusedImports" files=".*/generated-sources/.*"/>
<suppress checks="SummaryJavadoc" files=".*/generated-sources/.*"/>
<suppress checks="AnnotationLocationMostCases" files=".*/generated-sources/.*"/>
<suppress checks="OperatorWrap" files=".*/generated-sources/.*"/>
<suppress checks="LineLength" files=".*/generated-sources/.*"/>
<suppress checks="EmptyLineSeparator" files=".*/generated-sources/.*"/>
</suppressions>

Why Suppressions File:

  • Generated code doesn't need to follow checkstyle rules
  • Prevents checkstyle from failing on generated code
  • Keeps checkstyle focused on source code
  • Works with OpenAPI Generator (separate guide)

Step 3: Update build.gradle to Use Suppressions

File: server/build.gradle

Purpose: Configure Checkstyle to use the suppressions file.

Update checkstyle configuration:

checkstyle {
toolVersion = '10.12.5'
configFile = file("$projectDir/config/checkstyle/checkstyle.xml")
maxWarnings = 0
}

// Configure suppressions file
checkstyleMain {
configProperties = [
'suppressionFile': file("$projectDir/config/checkstyle/checkstyle-suppressions.xml")
]
}

Complete checkstyle configuration:

checkstyle {
toolVersion = '10.12.5'
configFile = file("$projectDir/config/checkstyle/checkstyle.xml")
maxWarnings = 0
}

checkstyleMain {
configProperties = [
'suppressionFile': file("$projectDir/config/checkstyle/checkstyle-suppressions.xml")
]
exclude '**/generated/**'
}

Step 4: Configure Hibernate Logging

File: server/src/main/resources/application.yml

Purpose: Configure Hibernate SQL logging for better debugging experience.

Key Points:

  • ✅ Logs SQL statements
  • ✅ Formats SQL for readability
  • ✅ Includes SQL comments for tracing
  • ✅ Developer experience improvement

Find spring.jpa.properties section and add:

spring:
jpa:
properties:
# Log SQL for debugging
hibernate:
show_sql: true
format_sql: true
use_sql_comments: true

Complete JPA configuration example:

spring:
jpa:
hibernate:
ddl-auto: validate
properties:
# Log SQL for debugging
hibernate:
show_sql: true # Show SQL statements in logs
format_sql: true # Format SQL for readability
use_sql_comments: true # Include SQL comments for tracing

Configuration Explanation:

  • show_sql: true - Logs SQL statements to console
  • format_sql: true - Formats SQL with indentation (readable)
  • use_sql_comments: true - Includes Hibernate-generated comments in SQL

Benefits:

  • Better debugging experience
  • SQL query visibility
  • Formatted SQL for readability
  • SQL comments for tracing

Note: For production, consider disabling SQL logging or using appropriate log levels.


Step 5: Configure Detailed Logging

File: server/src/main/resources/application.yml

Purpose: Configure detailed logging levels for better debugging and visibility.

Key Points:

  • ✅ Enhanced OAuth2 debugging
  • ✅ Hibernate SQL and parameter binding visibility
  • ✅ Schema tool visibility
  • ✅ Better debugging capabilities

Find logging section and add/update:

logging:
level:
org:
security:
oauth2: DEBUG
hibernate:
SQL: DEBUG
tool.schema: DEBUG
type.descriptor.sql.BasicBinder: TRACE
type.descriptor.sql: TRACE
type: TRACE

Complete logging configuration example:

logging:
level:
root: INFO
com.saas.springular: DEBUG
org:
security:
oauth2: DEBUG # OAuth2 debugging
hibernate:
SQL: DEBUG # SQL statement logging
tool.schema: DEBUG # Schema tool visibility
type.descriptor.sql.BasicBinder: TRACE # Parameter binding visibility
type.descriptor.sql: TRACE # SQL type descriptor visibility
type: TRACE # Type resolution visibility

Configuration Explanation:

  • oauth2: DEBUG - Enhanced OAuth2 debugging (authentication flows)
  • SQL: DEBUG - Logs SQL statements (works with hibernate.show_sql)
  • tool.schema: DEBUG - Schema generation/validation visibility
  • type.descriptor.sql.BasicBinder: TRACE - Shows parameter values in SQL
  • type.descriptor.sql: TRACE - SQL type descriptor visibility
  • type: TRACE - Type resolution visibility

Benefits:

  • Enhanced debugging capabilities
  • Better visibility into Hibernate operations
  • SQL parameter binding visibility
  • Schema tool visibility

Note: TRACE level is verbose - use for debugging, not production.


Verification

Step 1: Verify Checkstyle Configuration

Run checkstyle:

./gradlew checkstyleMain

Expected Result:

  • Checkstyle runs successfully
  • Reports any code style violations
  • Fails build if violations found (maxWarnings = 0)

Fix Any Violations:

  • Review checkstyle report
  • Fix code style violations
  • Re-run checkstyle until clean

Step 2: Verify Suppressions File Works

After implementing OpenAPI Generator (from separate guide):

  1. Generate OpenAPI code
  2. Run checkstyle:
    ./gradlew checkstyleMain
  3. Expected: No checkstyle errors from generated code

Verify Suppressions:

  • Generated code should be excluded
  • Source code should still be checked
  • Checkstyle should pass with clean source code

Step 3: Verify Hibernate Logging

Start application and perform database operation:

./gradlew bootRun

Expected in logs:

Hibernate: 
select
user0_.id as id1_0_,
user0_.email as email2_0_,
...
from
users user0_
where
user0_.email=?

Verify:

  • SQL statements are logged
  • SQL is formatted (indented)
  • SQL includes comments

Step 4: Verify Detailed Logging

Check logs for:

  • OAuth2 DEBUG messages (authentication flows)
  • Hibernate SQL DEBUG messages
  • Parameter binding TRACE messages (if enabled)
  • Schema tool DEBUG messages

Verify Log Levels:

  • OAuth2 messages appear at DEBUG level
  • SQL statements appear at DEBUG level
  • Parameter values appear at TRACE level

Testing

Unit Tests

No unit tests required (configuration changes).

Integration Tests

Verify checkstyle integration:

  • CI/CD runs checkstyle
  • Build fails on checkstyle violations
  • Generated code excluded from checkstyle

Verify logging:

  • Existing tests continue to pass
  • Logging doesn't break tests
  • Log levels work correctly

Troubleshooting

Checkstyle Fails on Generated Code

Issue: Checkstyle fails on generated OpenAPI code.

Solution:

  1. Verify suppressions file exists
  2. Check suppressions file path in build.gradle
  3. Verify suppressions file syntax
  4. Check generated code paths match suppressions patterns

Checkstyle maxWarnings = 0 Too Strict

Issue: Too many checkstyle violations to fix immediately.

Solution:

  1. Fix violations incrementally
  2. Consider temporary suppressions for existing code
  3. Add suppressions file entries for legacy code patterns
  4. Gradually improve code quality

Excessive Logging

Issue: Too much logging output (especially TRACE level).

Solution:

  1. Adjust log levels for production
  2. Use DEBUG for development, INFO/WARN for production
  3. Configure log levels per environment
  4. Use structured logging if needed

CI/CD Integration

GitHub Actions Example

Add checkstyle to CI/CD:

- name: Run Checkstyle
run: ./gradlew checkstyleMain

Benefits:

  • Enforces code quality in CI/CD
  • Prevents code style violations in PRs
  • Consistent code quality across team

Next Steps

After completing this guide:

  1. Code Generation Infrastructure - OpenAPI Generator foundational setup (suppressions file ready)
  2. Test Infrastructure - Test profile configuration

Summary

This implementation provides:

  • Code Quality: Checkstyle strict enforcement
  • Generated Code Exclusion: Suppressions file for generated sources
  • Enhanced Debugging: Hibernate SQL logging
  • Detailed Logging: Better visibility into application operations
  • Developer Experience: Improved workflow and debugging tools

All changes improve developer experience and code quality, making development faster and more reliable.