chore: modernize build tooling + fix MariaDB Lock Exception regression#54
Conversation
There was a problem hiding this comment.
Pull request overview
Changes: Maintenance (1)
This PR modernizes the build tooling by upgrading Gradle to 8.14.3, Spring Boot to 3.5.7, and updating several key dependencies including Lombok, Groovy, and Spock. It also updates the Java target to 17 and adds JUnit Platform support for tests.
Changes:
- Upgraded Gradle wrapper from 7.3.3 to 8.14.3
- Updated Spring Boot from 2.2.4 to 3.5.7 and Spring JDBC from 4.3.18 to 6.2.12
- Migrated Groovy from 2.5.13 (Codehaus) to 4.0.29 (Apache) and Spock from 1.3 to 2.4-M5
- Updated Java compatibility from 1.9 to 17 and added JUnit Platform launcher for test execution
- Added docker-compose executable auto-detection for macOS Homebrew and Linux installations
Reviewed changes
Copilot reviewed 9 out of 11 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| libraries.gradle | Updated dependency versions for Lombok, Spring Boot, Spring JDBC, Groovy, and Spock; added groovy-json, groovy-sql, and junit_platform_launcher dependencies |
| build.gradle | Updated Gradle version, Java target to 17, Spring Boot plugin to 3.5.7, dependency-management plugin to 1.1.7, added useJUnitPlatform() for tests, and docker-compose executable auto-detection |
| idempotence4j-test/build.gradle | Added groovy-json and groovy-sql dependencies for Groovy test support |
| idempotence4j-postgres/build.gradle | Added groovy-sql dependency for integration tests |
| idempotence4j-mariadb/build.gradle | Added groovy-sql dependency for integration tests and fixed indentation |
| idempotence4j-benchmarks/build.gradle | Changed bootJar classifier property from deprecated 'classifier' to 'archiveClassifier' |
| gradlew | Updated Gradle wrapper script to the version shipped with Gradle 8.14.3 with improved POSIX compliance and argument handling |
| gradle/wrapper/gradle-wrapper.properties | Updated Gradle distribution URL from 7.3.3 to 8.14.3 |
| gradle/wrapper/gradle-wrapper.jar | Updated Gradle wrapper JAR binary to match version 8.14.3 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Spring 6 changed the default SQL exception translator from SQLErrorCodeSQLExceptionTranslator to SQLExceptionSubclassTranslator. This caused MariaDB error 1205 (lock wait timeout) to be translated to UncategorizedSQLException instead of CannotAcquireLockException, breaking the lock acquisition logic in JdbcMariaDbLockProvider. The fix creates a new JdbcTemplate with the correct exception translator instead of mutating the passed instance. This avoids side effects on shared JdbcTemplate instances while preserving transaction safety - Spring's DataSourceTransactionManager binds connections at the DataSource level, so both the original and new JdbcTemplate participate in the same transaction and use the same database connection. Co-Authored-By: Claude <noreply@anthropic.com>
8048414 to
963825b
Compare
- SLF4J 1.7.26 → 2.0.17 (fixes Logback conflict) - Jackson 2.13.2 → 2.18.2 - Micrometer 1.3.5 → 1.14.5 - HikariCP 3.3.1 → 6.2.1 - Flyway 6.1.4 → 11.3.4 - PostgreSQL driver 42.2.16 → 42.7.5 - MariaDB driver 2.5.2 → 3.5.2 Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
f6d19ea to
81668f0
Compare
Flyway 10.x moved database-specific support to separate modules. MariaDB support requires the flyway-mysql artifact. Co-Authored-By: Claude <noreply@anthropic.com>
Flyway 10.x moved database-specific support to separate modules. PostgreSQL support requires the flyway-database-postgresql artifact. Also updated CI from Postgres 10.9 to 12 (matching docker-compose). Co-Authored-By: Claude <noreply@anthropic.com>
|
/request-review |
|
Unfortunately, the review request could not be sent to any teams:
|
Breaking changes warrant a major version bump: - Java 11 → 17 - Spring Boot 2 → 3 - Spring Framework 5 → 6 - Jakarta EE namespace migration Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
| // because Spring's DataSourceTransactionManager binds connections at the DataSource | ||
| // level, not the JdbcTemplate level - both templates will use the same connection | ||
| // within a transaction. | ||
| DataSource dataSource = jdbcTemplate.getDataSource(); |
There was a problem hiding this comment.
Think it'd be simpler to make the constructor take a DataSource directly instead of a JdbcTemplate instance, the auto configuration bean method already takes in a data source instance so should be easy enough.
Technically it'd be a breaking change, though given JdbcMariaDbLockProvider is being created by auto config, it feels unlikely to cause real issues for users.
There was a problem hiding this comment.
I like this suggestion, breaking change could be justified too - it's 2.0.0 + this bugfix requires careful implementation
|
Here are the release notes for the SQLExceptionSubclassTranslator change |
| classpath "io.spring.gradle:dependency-management-plugin:1.0.10.RELEASE" | ||
| classpath "org.springframework.boot:spring-boot-gradle-plugin:2.2.4.RELEASE" | ||
| classpath "io.spring.gradle:dependency-management-plugin:1.1.7" | ||
| classpath "org.springframework.boot:spring-boot-gradle-plugin:3.5.7" |
There was a problem hiding this comment.
Since we're upgrading all the things and making breaking changes, how much trouble would it be to test this against both Spring Boot 3.5.x and Spring Boot 4? There were quite a few changes (also changes in Spring Framework 7) that are worth testing against.
There was a problem hiding this comment.
Since this doesn't use any of wise provided infra it's a bit harder but not impossible
Move dependency management to allprojects block and let Spring Boot BOM manage spring-jdbc and junit-platform-launcher versions to ensure compatibility across Boot versions. Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
Replace Spring's SQLErrorCodeSQLExceptionTranslator with direct JDBC error code checking for lock conflict detection. This reduces coupling to Spring's internal exception mapping which changed in Spring 6. Breaking change: JdbcMariaDbLockProvider constructor now takes DataSource instead of JdbcTemplate. See docs/adr/0001-low-level-jdbc-for-lock-detection.md for details. Co-Authored-By: Claude <noreply@anthropic.com>
Remove deprecated spring.datasource.platform and initialization-mode properties in favor of spring.sql.init.mode. Co-Authored-By: Claude <noreply@anthropic.com>
Remove explicit classes list from @SpringBootTest to let Spring Boot auto-configure DataSource and other required beans properly. Co-Authored-By: Claude <noreply@anthropic.com>
- Add AutoConfiguration.imports file for Spring Boot 3+ style registration - Add spring-boot-starter-jdbc to test dependencies for DataSource auto-config - Update test application.yml to use spring.sql.init.mode instead of deprecated properties - Simplify test @SpringBootTest annotation Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Claude <noreply@anthropic.com>
|
The approval(s) from normanma-tw do(es)n't fullfill the approvers requirements because:
|
Rename matrix job to test-matrix and add a build job that depends on it. This ensures branch protection can target the single 'build' check that only passes when all matrix variants succeed. Also split publish into a separate job that runs only on master. Co-Authored-By: Claude <noreply@anthropic.com>
Context
Modernizes the build tooling and dependencies to current standards.
Changes
🔍 Deep Dive: MariaDB Lock Exception Fix
The Problem
After upgrading to Spring 6, the MariaDB integration test
should only allow single side-effect for a given actionstarted failing:The test verifies that concurrent requests for the same idempotent action properly detect lock conflicts and throw
ConflictingActionException.The Investigation 🕵️
Initial hypothesis was that MariaDB's
FOR UPDATE NOWAITsemantics were broken. We tested:All versions showed the same behavior. NOWAIT was being accepted syntactically but the lock provider wasn't detecting conflicts.
Root Cause Found! 🎯
Spring Framework 6 changed the default SQL exception translator.
SQLErrorCodeSQLExceptionTranslatorSQLExceptionSubclassTranslatorThis meant MariaDB error 1205 (lock wait timeout) was being translated to
UncategorizedSQLExceptioninstead ofCannotAcquireLockException:The
JdbcMariaDbLockProvidercatchesCannotAcquireLockExceptionto detect lock conflicts - with the wrong exception type, it was throwing instead of returningOptional.empty().The Fix
Explicitly configure
SQLErrorCodeSQLExceptionTranslatorin the lock provider:Migration Notes
Services using
idempotence4j-mariadbwith Spring Boot 3.x / Spring Framework 6.x should upgrade to version 2.0.0 to get the corrected exception translation behavior.Impact of the bug: Wrong exception type (
UncategorizedSQLExceptioninstead ofConflictingActionException). Lock acquisition and timeout behavior are NOT affected.Test Plan
🤖 Investigated and fixed with Claude Code 🔬