Skip to content

Commit ac42cfc

Browse files
authored
chore: migrate to Spring Boot 4 (#3804)
## Summary Migrates the Tolgee platform backend from **Spring Boot 3 to Spring Boot 4** (Spring Framework 7). This is a large, cross-cutting framework upgrade; opening as a **draft** while the test suite is brought fully green. Core version bumps: | Area | From → To | |------|-----------| | Spring Boot | 3.x → **4.1.0** | | Spring Framework | 6 → **7** | | Hibernate ORM | 6 → **7.4.1** | | Spring Data | 3 → **4** | | Spring Batch | 5 → **6** | | Spring Security | 6 → **7** | | Jackson | 2 (`com.fasterxml`) → **3 (`tools.jackson`)** | | Redisson | 3.27 → **4.6.1** | | Spring Cloud Azure | 5.x → **7.3.0** | | Kotlin | → **2.3.21** | | Gradle | → **9.6.0** | ## Notable migration work - **Autoconfigure package splits** — Boot 4 splits the autoconfigure monolith into per-module packages (data-redis, hibernate, persistence, security, servlet, webmvc-test, restclient, liquibase, …); imports and excludes updated accordingly. - **Jackson 2 → 3** — moved to `tools.jackson` coordinates and APIs; annotations remain on `com.fasterxml.jackson.annotation`. - **Liquibase** — Boot 4 moved Liquibase auto-configuration to a separate `spring-boot-liquibase` module; added it so the custom `SpringLiquibase` beans run before the `EntityManagerFactory`. - **Redisson 4.x** — extend `RedissonAutoConfigurationV4`, exclude the new unconditional V4 autoconfig, add `redisson-spring-cache` (split out of core), and declare `micrometer-core` explicitly (Redisson 4 marks it optional). - **Hibernate 7 HQL** — added explicit `select` clauses to join queries that no longer infer a result type. - **JSONB attributes** — restored JSON-based deep-copy for non-`Serializable` values (hypersistence-utils 3.15 dropped that fallback). - **JPA auditing / startup ordering** — wire the date-time provider via `dateTimeProviderRef` and defer DB access out of bean construction, since Boot 4 creates servlet-filter beans before Liquibase migrates. ### Upstream bug found Hibernate 7's `hibernate-models` crashes with `IndexOutOfBoundsException` on a JSONB entity attribute whose type is a `Map` subclass reaching `Map<K,V>` through a one-type-parameter generic intermediate. Reported upstream: hibernate/hibernate-models#263 (worked around in `CompactSharedMap`). ## Status - ✅ Full backend compiles (all modules) - ✅ Application boots end-to-end (context loads, Liquibase migrates, web server starts, batch jobs execute) - ✅ Core integration tests green (e.g. `BatchJobsGeneralWithoutRedisTest`) - ⏳ Widening test-suite coverage; the Redis-backed concurrent batch tests (`BatchJobsGeneralWithRedisTest`, `BatchJobRecoveryTest`, …) are pre-existing flaky/timing-sensitive tests still being verified ## Related The matching `billing` branch (`bdshadow/spring-boot-4`) carries the corresponding billing changes.
1 parent bbb5a3c commit ac42cfc

424 files changed

Lines changed: 6780 additions & 2700 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/setup-env/action.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ runs:
3232
if: "${{ inputs.java == 'true' }}"
3333
uses: actions/setup-java@v4
3434
with:
35-
java-version: 21
35+
java-version: 25
3636
distribution: temurin
3737

3838
- name: Setup Gradle

.github/workflows/prerelease-alpha.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414

1515
- uses: actions/setup-java@v3
1616
with:
17-
java-version: 21
17+
java-version: 25
1818
distribution: adopt
1919

2020
- name: Setup node

.github/workflows/preview.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
- uses: actions/setup-java@v3
1818
with:
19-
java-version: 21
19+
java-version: 25
2020
distribution: adopt
2121

2222
- name: Setup node

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818

1919
- uses: actions/setup-java@v3
2020
with:
21-
java-version: 21
21+
java-version: 25
2222
distribution: adopt
2323

2424
- name: Setup node

backend/api/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ apply plugin: 'io.spring.dependency-management'
2727

2828
java {
2929
toolchain {
30-
languageVersion = JavaLanguageVersion.of(21)
30+
languageVersion = JavaLanguageVersion.of(javaVersion.toInteger())
3131
}
3232
}
3333

3434
kotlin {
3535
compilerOptions {
36-
freeCompilerArgs.addAll("-Xjsr305=strict")
36+
freeCompilerArgs.addAll("-Xjsr305=strict", "-Xannotation-default-target=param-property")
3737
}
3838
}
3939

@@ -59,6 +59,7 @@ dependencies {
5959
implementation libs.springDocWebmvcApi
6060
implementation libs.springDocOpenApiUi
6161
implementation libs.redissonSpringBootStarter
62+
implementation libs.redissonSpringCache
6263

6364
/**
6465
* Misc

backend/api/src/main/kotlin/io/tolgee/api/v2/controllers/suggestion/MtResultStreamer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.tolgee.api.v2.controllers.suggestion
22

3-
import com.fasterxml.jackson.databind.ObjectMapper
43
import io.sentry.Sentry
54
import io.tolgee.constants.MtServiceType
65
import io.tolgee.dtos.cacheable.ProjectDto
@@ -27,6 +26,7 @@ import kotlinx.coroutines.runBlocking
2726
import org.springframework.context.ApplicationContext
2827
import org.springframework.security.core.context.SecurityContextHolder
2928
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody
29+
import tools.jackson.databind.ObjectMapper
3030
import java.io.OutputStream
3131
import java.io.OutputStreamWriter
3232

backend/api/src/main/kotlin/io/tolgee/component/EnumNameKryo5Codec.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ class EnumNameKryo5Codec : Kryo5Codec {
1010
/** Redisson reflectively requires a `(ClassLoader, <this exact type>)` constructor to rebind the codec. */
1111
constructor(classLoader: ClassLoader?, codec: EnumNameKryo5Codec) : super(classLoader, codec)
1212

13-
override fun createKryo(classLoader: ClassLoader?): Kryo {
14-
return super.createKryo(classLoader).apply {
13+
override fun createKryo(
14+
classLoader: ClassLoader?,
15+
useReferences: Boolean,
16+
): Kryo {
17+
return super.createKryo(classLoader, useReferences).apply {
1518
addDefaultSerializer(Enum::class.java, EnumNameSerializer::class.java)
1619
}
1720
}

backend/api/src/main/kotlin/io/tolgee/component/KeyComplexEditHelper.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package io.tolgee.component
22

3-
import com.fasterxml.jackson.databind.ObjectMapper
43
import io.tolgee.activity.ActivityHolder
54
import io.tolgee.activity.data.ActivityType
65
import io.tolgee.constants.Message
@@ -28,6 +27,7 @@ import io.tolgee.util.executeInNewRepeatableTransaction
2827
import org.springframework.context.ApplicationContext
2928
import org.springframework.transaction.PlatformTransactionManager
3029
import org.springframework.transaction.TransactionDefinition
30+
import tools.jackson.databind.ObjectMapper
3131
import kotlin.properties.Delegates
3232

3333
class KeyComplexEditHelper(

backend/api/src/main/kotlin/io/tolgee/component/ProjectLastModifiedManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ class ProjectLastModifiedManager(
3636
* - Cache-Control header set to max-age=0 to ensure validation on each request
3737
*
3838
*/
39-
fun <T> onlyWhenProjectDataChanged(
39+
fun <T : Any> onlyWhenProjectDataChanged(
4040
request: WebRequest,
4141
fn: (
4242
/**

backend/api/src/main/kotlin/io/tolgee/component/TestClockHeaderFilter.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ package io.tolgee.component
33
import jakarta.servlet.FilterChain
44
import jakarta.servlet.http.HttpServletRequest
55
import jakarta.servlet.http.HttpServletResponse
6+
import org.springframework.context.annotation.Lazy
67
import org.springframework.stereotype.Component
78
import org.springframework.web.filter.OncePerRequestFilter
89

910
@Component
1011
class TestClockHeaderFilter(
11-
private val currentDateProvider: CurrentDateProvider,
12+
@Lazy private val currentDateProvider: CurrentDateProvider,
1213
) : OncePerRequestFilter() {
1314
companion object {
1415
const val TOLGEE_TEST_CLOCK_HEADER_NAME = "X-Tolgee-Test-Clock"

0 commit comments

Comments
 (0)