diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 08311b7..5d6fcf3 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -12,24 +12,9 @@ // Note: if the rule feels generic enough, should consider adding it to the jore4 default preset packageRules: [ { - // restrict spring boot updates to <4 versions for now. - // Maven depName is "groupId:artifactId", so match with a glob to also catch - // spring-boot-starter-parent (a plain "org.springframework.boot" does not match it). - groupName: "spring boot", - groupSlug: "spring-boot", - matchPackageNames: ["org.springframework.boot:**"], - allowedVersions: "<4", - }, - { - // java-jdk 25 needs Kotlin 2.x, which only comes with Spring Boot 4. Stay on 21 for now - // (jOOQ needs 21, Kotlin 1.9.x supports 21 but not 25). - matchDepNames: ["java-jdk"], - allowedVersions: "<25", - }, - { - // springmockk 5 is compiled against Kotlin 2.x; blocked until Spring Boot 4 raises Kotlin. - matchPackageNames: ["com.ninja-squad:springmockk"], - allowedVersions: "<5", + // jOOQ 3.20+ Open Source editions require PostgreSQL 17/18; stay on 3.19 until the database is upgraded. + matchPackageNames: ["org.jooq:**"], + allowedVersions: "<3.20", }, { // give each major update its own PR instead of the big "all dependencies" bundle. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 674a25d..d4f629c 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -22,4 +22,4 @@ jobs: with: languages: '["actions", "java-kotlin"]' java_build_command: "cp profiles/dev/config.properties profiles/dev/config.runner.properties && mvn clean install -DskipTests" - java_version: "17" + java_version: "25" diff --git a/.github/workflows/run-kotlin-tests.yml b/.github/workflows/run-kotlin-tests.yml index b4e7bc9..d24b9b9 100644 --- a/.github/workflows/run-kotlin-tests.yml +++ b/.github/workflows/run-kotlin-tests.yml @@ -24,10 +24,10 @@ jobs: - name: Start dependencies (blocking until up) run: ./development.sh start:deps - - name: Set up JDK 17 + - name: Set up JDK 25 uses: actions/setup-java@v6 with: - java-version: "17" + java-version: "25" java-package: jdk architecture: x64 distribution: temurin diff --git a/Dockerfile b/Dockerfile index 369a2fa..4c6dcda 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM maven:3-eclipse-temurin-17 AS builder +FROM maven:3-eclipse-temurin-25 AS builder # set up workdir WORKDIR /build diff --git a/pom.xml b/pom.xml index 3f58023..01e2ae5 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 3.5.16 + 4.1.1 @@ -19,7 +19,7 @@ UTF-8 - 17 + 25 true ${java.version} @@ -36,10 +36,12 @@ 3.7.1 + + 3.19.39 8.0.4 0.26 1.14.11 - 4.0.2 + 5.0.1 fi.hsl.jore4.timetables.TimetablesApiApplicationKt @@ -285,6 +287,8 @@ -Xjsr305=strict + + -java-parameters @@ -501,7 +505,7 @@ org.springframework.boot - spring-boot-starter-web + spring-boot-starter-webmvc org.springframework.boot @@ -544,20 +548,14 @@ - com.fasterxml.jackson.module + tools.jackson.module jackson-module-kotlin - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 - - - org.springframework.boot - spring-boot-starter-test + spring-boot-starter-webmvc-test test diff --git a/src/main/kotlin/fi/hsl/jore4/timetables/TimetablesApiApplication.kt b/src/main/kotlin/fi/hsl/jore4/timetables/TimetablesApiApplication.kt index 78fe2b1..acc9afa 100644 --- a/src/main/kotlin/fi/hsl/jore4/timetables/TimetablesApiApplication.kt +++ b/src/main/kotlin/fi/hsl/jore4/timetables/TimetablesApiApplication.kt @@ -1,10 +1,6 @@ package fi.hsl.jore4.timetables import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.KotlinFeature -import com.fasterxml.jackson.module.kotlin.KotlinModule import fi.hsl.jore4.timetables.config.DatabaseProperties import fi.hsl.jore4.timetables.config.JOOQProperties import org.springframework.boot.autoconfigure.SpringBootApplication @@ -12,6 +8,9 @@ import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.boot.runApplication import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Primary +import tools.jackson.databind.json.JsonMapper +import tools.jackson.module.kotlin.KotlinFeature +import tools.jackson.module.kotlin.KotlinModule fun main(args: Array) { runApplication(*args) @@ -25,11 +24,11 @@ fun main(args: Array) { class TimetablesApiApplication { @Bean @Primary - fun objectMapper(): ObjectMapper = - ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_NULL) - .registerModule(JavaTimeModule()) - .registerModule( + fun jsonMapper(): JsonMapper = + JsonMapper + .builder() + .changeDefaultPropertyInclusion { it.withValueInclusion(JsonInclude.Include.NON_NULL) } + .addModule( KotlinModule .Builder() .withReflectionCacheSize(512) @@ -39,5 +38,5 @@ class TimetablesApiApplication { .configure(KotlinFeature.SingletonSupport, false) .configure(KotlinFeature.StrictNullChecks, true) .build() - ) + ).build() } diff --git a/src/main/kotlin/fi/hsl/jore4/timetables/repository/VehicleScheduleFrameRepository.kt b/src/main/kotlin/fi/hsl/jore4/timetables/repository/VehicleScheduleFrameRepository.kt index 7f0d341..19dd113 100644 --- a/src/main/kotlin/fi/hsl/jore4/timetables/repository/VehicleScheduleFrameRepository.kt +++ b/src/main/kotlin/fi/hsl/jore4/timetables/repository/VehicleScheduleFrameRepository.kt @@ -78,7 +78,7 @@ class VehicleScheduleFrameRepository( .and(replacedFrame.VALIDITY_START.lessThan(stagingFrame.VALIDITY_START)) return dsl - .select() + .select(*VEHICLE_SCHEDULE_FRAME.fields()) // Returns a row for each day type id. // We are not interested in those here, just the replaced frame ids. .distinctOn(replacedVehicleScheduleFrameIdField) @@ -142,7 +142,7 @@ class VehicleScheduleFrameRepository( .and(targetFrame.PRIORITY.eq(targetPriority.value)) return dsl - .select() + .select(*VEHICLE_SCHEDULE_FRAME.fields()) // Returns a row for each day type id. // We are not interested in those here, just the overlapping frame ids. .distinctOn(targetVehicleScheduleFrameIdField) diff --git a/src/test/kotlin/fi/hsl/jore4/timetables/TimetablesDataset.kt b/src/test/kotlin/fi/hsl/jore4/timetables/TimetablesDataset.kt index fae97f4..2bbf795 100644 --- a/src/test/kotlin/fi/hsl/jore4/timetables/TimetablesDataset.kt +++ b/src/test/kotlin/fi/hsl/jore4/timetables/TimetablesDataset.kt @@ -1,8 +1,8 @@ package fi.hsl.jore4.timetables -import com.fasterxml.jackson.core.type.TypeReference -import com.fasterxml.jackson.databind.ObjectMapper import io.github.oshai.kotlinlogging.KotlinLogging +import tools.jackson.core.type.TypeReference +import tools.jackson.databind.json.JsonMapper private val LOGGER = KotlinLogging.logger {} @@ -10,7 +10,7 @@ class TimetablesDataset : MutableMap by mutableMapOf() { fun toJSONString(): String = OBJECT_MAPPER.writeValueAsString(this) companion object { - private val OBJECT_MAPPER = ObjectMapper() + private val OBJECT_MAPPER = JsonMapper() fun createFromResource(resourcePath: String): TimetablesDataset { val jsonStream = this::class.java.classLoader.getResourceAsStream(resourcePath) diff --git a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesCombineApiTest.kt b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesCombineApiTest.kt index cee7b8a..7a8095e 100644 --- a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesCombineApiTest.kt +++ b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesCombineApiTest.kt @@ -1,6 +1,5 @@ package fi.hsl.jore4.timetables.api -import com.fasterxml.jackson.databind.ObjectMapper import com.ninjasquad.springmockk.MockkBean import fi.hsl.jore4.timetables.enumerated.TimetablesPriority import fi.hsl.jore4.timetables.service.CombineTimetablesService @@ -14,8 +13,8 @@ import io.mockk.verify import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc import org.springframework.http.MediaType import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.servlet.MockMvc @@ -24,6 +23,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.transaction.TransactionSystemException +import tools.jackson.databind.json.JsonMapper import java.util.UUID @ExtendWith(MockKExtension::class) @@ -325,6 +325,6 @@ class TimetablesCombineApiTest( } companion object { - private val MAPPER = ObjectMapper() + private val MAPPER = JsonMapper() } } diff --git a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesReplaceApiTest.kt b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesReplaceApiTest.kt index ef8c3af..1aa6adf 100644 --- a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesReplaceApiTest.kt +++ b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesReplaceApiTest.kt @@ -1,6 +1,5 @@ package fi.hsl.jore4.timetables.api -import com.fasterxml.jackson.databind.ObjectMapper import com.ninjasquad.springmockk.MockkBean import fi.hsl.jore4.timetables.enumerated.TimetablesPriority import fi.hsl.jore4.timetables.service.InvalidTargetPriorityException @@ -13,8 +12,8 @@ import io.mockk.verify import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc import org.springframework.http.MediaType import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.servlet.MockMvc @@ -23,6 +22,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders import org.springframework.test.web.servlet.result.MockMvcResultMatchers.content import org.springframework.test.web.servlet.result.MockMvcResultMatchers.status import org.springframework.transaction.TransactionSystemException +import tools.jackson.databind.json.JsonMapper import java.util.UUID private val LOGGER = KotlinLogging.logger {} @@ -270,6 +270,6 @@ class TimetablesReplaceApiTest( } companion object { - private val OBJECT_MAPPER = ObjectMapper() + private val OBJECT_MAPPER = JsonMapper() } } diff --git a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToCombineApiTest.kt b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToCombineApiTest.kt index 32d0a5b..5408d15 100644 --- a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToCombineApiTest.kt +++ b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToCombineApiTest.kt @@ -10,8 +10,8 @@ import io.mockk.verify import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc import org.springframework.http.MediaType import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.servlet.MockMvc diff --git a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToReplaceApiTest.kt b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToReplaceApiTest.kt index 3923d45..09dd318 100644 --- a/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToReplaceApiTest.kt +++ b/src/test/kotlin/fi/hsl/jore4/timetables/api/TimetablesToReplaceApiTest.kt @@ -10,8 +10,8 @@ import io.mockk.verify import org.junit.jupiter.api.Test import org.junit.jupiter.api.extension.ExtendWith import org.springframework.beans.factory.annotation.Autowired -import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc import org.springframework.boot.test.context.SpringBootTest +import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc import org.springframework.http.MediaType import org.springframework.test.context.ActiveProfiles import org.springframework.test.web.servlet.MockMvc diff --git a/src/test/kotlin/fi/hsl/jore4/timetables/extensions/TimetablesDatasetExtensions.kt b/src/test/kotlin/fi/hsl/jore4/timetables/extensions/TimetablesDatasetExtensions.kt index d755d0a..6075045 100644 --- a/src/test/kotlin/fi/hsl/jore4/timetables/extensions/TimetablesDatasetExtensions.kt +++ b/src/test/kotlin/fi/hsl/jore4/timetables/extensions/TimetablesDatasetExtensions.kt @@ -1,8 +1,8 @@ package fi.hsl.jore4.timetables.extensions -import com.fasterxml.jackson.core.type.TypeReference -import com.fasterxml.jackson.databind.ObjectMapper import io.github.oshai.kotlinlogging.KotlinLogging +import tools.jackson.core.type.TypeReference +import tools.jackson.databind.json.JsonMapper private val LOGGER = KotlinLogging.logger {} @@ -23,7 +23,7 @@ fun MutableMap.getNested(propertyPath: String): MutableMap.deepClone(): MutableMap { val asString = OBJECT_MAPPER.writeValueAsString(this)