Feature 8: Code Quality & Developer Experience
Purpose: This guide provides step-by-step instructions for implementing code quality enforcement and developer experience improvements.
Dependencies:
- Requires Code Generation Infrastructure to be completed first (for checkstyle suppressions file to exclude generated code)
Related Documents:
- Boilerplate Enhancements Solution Architecture - System design overview
- Boilerplate Enhancements Epic - Capability definition
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 consoleformat_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 visibilitytype.descriptor.sql.BasicBinder: TRACE- Shows parameter values in SQLtype.descriptor.sql: TRACE- SQL type descriptor visibilitytype: 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):
- Generate OpenAPI code
- Run checkstyle:
./gradlew checkstyleMain - 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:
- Verify suppressions file exists
- Check suppressions file path in build.gradle
- Verify suppressions file syntax
- Check generated code paths match suppressions patterns
Checkstyle maxWarnings = 0 Too Strict
Issue: Too many checkstyle violations to fix immediately.
Solution:
- Fix violations incrementally
- Consider temporary suppressions for existing code
- Add suppressions file entries for legacy code patterns
- Gradually improve code quality
Excessive Logging
Issue: Too much logging output (especially TRACE level).
Solution:
- Adjust log levels for production
- Use DEBUG for development, INFO/WARN for production
- Configure log levels per environment
- 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:
- ✅ Code Generation Infrastructure - OpenAPI Generator foundational setup (suppressions file ready)
- ✅ 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.