Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Spring Boot 3.2, Hibernate >= 6.3, Gradle 8.5 and Java 21 #593

Merged
merged 5 commits into from
Jan 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions docs/modules/ROOT/pages/devops/update.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,20 @@ distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
$ ./gradlew wrapper --gradle-version 8.5
----

And Make sure intellij setup matches
.Make sure Java version in github setup workflow action is https://github.com/actions/setup-java?tab=readme-ov-file#supported-version-syntax[available] and matches your local dev setup:
----
$ more ../.github/workflows/kotlin.yml
- name: Set up Eclipse Temurin JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: 21
----

Make sure Intellij config matches the Java and Gradle versions / paths used on the commandline

* IntelliJ -> Preferences -> Build Tools -> Gradle -> Specified Location -> use the 8.5 Path
* Make sure Gradle JVM is the same as File -> Project Structure -> Project SDK
* IntelliJ -> Preferences -> Build Tools -> Gradle -> Specified Location -> Use the 8.x.x Path (not the softlink)
* IntelliJ -> Project Structure -> Project SDK: Make sure Gradle JVM is the same as on OS Level

=== API Dockerfile

Expand Down
21 changes: 10 additions & 11 deletions kotlin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,13 @@ plugins {
// Plugin to determine which dependencies have updates, including updates for gradle itself.
id("com.github.ben-manes.versions") version versionsVersion
// Gradle plugin for running SonarQube analysis. https://plugins.gradle.org/plugin/org.sonarqube
id("org.sonarqube") version "4.3.1.3277" // "4.3.1.3277" // "4.0.0.2929" // new ones has issues
id("org.sonarqube") version "4.3.1.3277" // new ones may cause issues against sonarcloud.io, so test first

kotlin("jvm") version kotlinVersion
kotlin("plugin.spring") version kotlinVersion
kotlin("plugin.jpa") version kotlinVersion
// The no-arg compiler plugin generates an additional zero-argument constructor for classes with a specific annotation.
// (...) is synthetic so it can’t be directly called from Java or Kotlin, but it can be called using reflection.
// (...) is synthetic, so it can’t be directly called from Java or Kotlin, but it can be called using reflection.
// https://kotlinlang.org/docs/no-arg-plugin.html
// As with the kotlin-spring plugin wrapped on top of all-open, kotlin-jpa is wrapped on top of no-arg.
// The plugin specifies @Entity, @Embeddable, and @MappedSuperclass no-arg annotations automatically.
Expand Down Expand Up @@ -118,9 +118,7 @@ dependencies {
val hypersistenceUtilsVersion: String by System.getProperties()
implementation(libs.postgresql)
implementation(libs.flyway.core)

// implementation("org.flywaydb:flyway-core:$flywayVersion") // looks for classpath:db/migration
implementation("io.hypersistence:hypersistence-utils-hibernate-62:$hypersistenceUtilsVersion") // https://vladmihalcea.com/how-to-map-java-and-sql-arrays-with-jpa-and-hibernate/
implementation(libs.hypersistence.utils.hibernate)

// Jackson JSON Parsing Dependencies
// For Gradle users, if you use the Spring Boot Gradle plugin you can omit the version number to adopt
Expand All @@ -146,7 +144,7 @@ dependencies {
val greenmailVersion: String by System.getProperties()
// Mockito Inline required to mock final classes (https://stackoverflow.com/a/14292888/4292075)
testImplementation("org.mockito:mockito-inline:$mockitoInlineVersion")
testImplementation( "com.github.tomakehurst:wiremock:$wiremockVersion")
testImplementation( libs.wiremock)
testImplementation("com.tngtech.archunit:archunit-junit5-api:$archUnitVersion")
testImplementation("com.icegreen:greenmail:$greenmailVersion")
testRuntimeOnly("com.tngtech.archunit:archunit-junit5-engine:$archUnitVersion")
Expand All @@ -157,7 +155,7 @@ tasks.test {
useJUnitPlatform()
finalizedBy("jacocoTestReport")
doLast {
println("Code coverage report at: file://$buildDir/reports/jacoco/test/html/index.html")
println("Code coverage report at: file://${layout.buildDirectory}/reports/jacoco/test/html/index.html")
}
}

Expand All @@ -178,10 +176,11 @@ tasks.bootJar {
}

jacoco {
toolVersion = "0.8.11"
// why get()? See https://github.com/gradle/gradle/issues/20392
toolVersion = libs.versions.jacoco.get()
}

// Configure which reports are generated by Jacococ coverage tool
// Configure which reports are generated by Jacoco coverage tool
// https://kevcodez.de/posts/2018-08-19-test-coverage-in-kotlin-with-jacoco/
tasks.jacocoTestReport {
reports {
Expand Down Expand Up @@ -220,7 +219,7 @@ tasks.register("bootRunProd") {
// https://github.com/ben-manes/gradle-versions-plugin#tasks
// disallow release candidates as upgradable versions from stable versions
fun isNonStable(version: String): Boolean {
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) }
val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.uppercase().contains(it) }
val regex = "^[0-9,.v-]+(-r)?$".toRegex()
val isStable = stableKeyword || regex.matches(version)
return isStable.not()
Expand All @@ -238,7 +237,7 @@ sonarqube {
property("sonar.projectName", "Angkor API")
property("sonar.projectDescription", "API for Angular Kotlin Rest App")
property("sonar.coverage.jacoco.xmlReportPaths","build/reports/jacoco/test/jacocoTestReport.xml")
// domain objects are mostly data classes which don't support inheritance really well, so we exlude
// domain objects are mostly data classes which don't support inheritance really well, so we exclude
// them from duplication detection (cf. https://docs.sonarqube.org/7.4/analysis/analysis-parameters/)
property("sonar.cpd.exclusions","src/main/kotlin/net/timafe/angkor/domain/**/*")
}
Expand Down
2 changes: 1 addition & 1 deletion kotlin/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ systemProp.romeVersion=1.19.0
#systemProp.springBootVersion=3.1.3
systemProp.unirestVersion=1.4.9
systemProp.versionsVersion=0.47.0
systemProp.wiremockVersion=3.0.0-beta-10
#systemProp.wiremockVersion=3.0.0-beta-10

# enable to support incremental processing
# https://medium.com/@daniel_novak/making-incremental-kapt-work-speed-up-your-kotlin-projects-539db1a771cf
Expand Down
23 changes: 18 additions & 5 deletions kotlin/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
# dependencies we use in our build and tests. Next we must add a section [plugins] where we can define our plugin
# dependencies. We can use the full power of the version catalog here, the only thing we need to remember is to use the
# id property of we use the longer notation option. With the shorthand notation we can simply define a string value
# with the id of the plugin, a colon (:) and the version."
# with the id of the plugin, a colon : and the version."
#
# You can use separators such as -, _, . that will be normalized
# You can use separators such as -, _, . that will be normalized
# by Gradle to . in the catalog and allow you to create subsections.
# File: gradle/libs.versions.toml

Expand All @@ -23,25 +23,38 @@
# 10.4.1 newest causes java.lang.NoSuchMethodError at FlywayAutoConfiguration.java:254
flyway = "9.22.3"
postgresql="42.7.1"
jacoco = "0.8.11"
wiremock = "3.0.1"

# implementation("io.hypersistence:hypersistence-utils-hibernate-62:$hypersistenceUtilsVersion") // https://vladmihalcea.com/how-to-map-java-and-sql-arrays-with-jpa-and-hibernate/

# plugins Were added in Gradle 7.2, are used (obviouly) to define plugins.
[plugins]
# We can use shorthand notation with the plugin id and version.
# use like "alias(libs.plugins.spring.boot)" in build.gradle.kts plugins section
spring-boot = "org.springframework.boot:3.1.5"
spring-boot = "org.springframework.boot:3.2.0" # 3.1.5

# We can use the longer notation option where we set
# the id and version for the plugin.
spring-dep-mgmt = { id = "io.spring.dependency-management", version = "1.1.3" }
spring-dep-mgmt = { id = "io.spring.dependency-management", version = "1.1.4" }

# Here we use the longer notation and version.ref to reference
# the version defined in the [versions] section.
flyway-plugin = { id = "org.flywaydb.flyway", version.ref = "flyway" }

# Define the libraries that will be later accessed in our Gradle files.
# use like "implementation(libs.flyway.core)" in build.gradle.kts dependencies section
# use like "implementation(libs.flyway.core)" in build.gradle.kts dependencies section
# replace hyphens in name with dots: flyway-core -> flyway.core
[libraries]
flyway-core = { module = "org.flywaydb:flyway-core", version.ref = "flyway" }
postgresql = { module = "org.postgresql:postgresql", version.ref = "postgresql" }
# make sure to align module AND version with the hibernate version used by Spring Boot (Releases Notes)
# Example: Spring Boot 3.2 uses Hibernate 6.3, so the module is hypersistence-utils-hibernate-63
hypersistence-utils-hibernate = { module = "io.hypersistence:hypersistence-utils-hibernate-63", version="3.7.0"}

# testImplementation
# testImplementation( "com.github.tomakehurst:wiremock:$wiremockVersion")
# Use standalone b/c of issue "jetty 12 / springboot 3.2 #2395" https://github.com/wiremock/wiremock/issues/2395
wiremock = { module= "com.github.tomakehurst:wiremock-standalone", version="3.0.1"} # 3.0.0-beta-10

# bundles? maybe coming soon. maybe not
4 changes: 2 additions & 2 deletions kotlin/src/main/kotlin/net/timafe/angkor/Application.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package net.timafe.angkor

import jakarta.annotation.PostConstruct
import jakarta.annotation.PreDestroy
import net.timafe.angkor.config.AppProperties
import net.timafe.angkor.config.Constants
import net.timafe.angkor.domain.Event
Expand All @@ -19,8 +21,6 @@ import org.springframework.core.env.Environment
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
import org.springframework.data.jpa.repository.config.EnableJpaRepositories
import java.util.*
import jakarta.annotation.PostConstruct
import jakarta.annotation.PreDestroy

@SpringBootApplication
@EnableJpaRepositories
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package net.timafe.angkor.domain

import java.util.*
import jakarta.persistence.Id
import jakarta.persistence.MappedSuperclass
import java.util.*

/**
* New superclass for all Entities that use pre-generated UUIDs
Expand Down
17 changes: 11 additions & 6 deletions kotlin/src/main/kotlin/net/timafe/angkor/domain/Area.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package net.timafe.angkor.domain

// import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
// with 6.3 we can use org.hibernate.dialect.PostgreSQLEnumJdbcType
import io.hypersistence.utils.hibernate.type.array.ListArrayType
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
import net.timafe.angkor.domain.enums.AreaLevel
import jakarta.persistence.*
import net.timafe.angkor.domain.enums.Area_Level
import net.timafe.angkor.domain.interfaces.Mappable
import org.hibernate.annotations.JdbcType
import org.hibernate.annotations.Type
import org.hibernate.dialect.PostgreSQLEnumJdbcType
import java.util.*
import jakarta.persistence.*

/**
* Area code (Managed Domain Entity)
Expand All @@ -23,10 +26,12 @@ data class Area(
var name: String,
var parentCode: String,

// As of 6.3: @Type(PostgreSQLEnumType::class) -> @JdbcTypeCode(SqlTypes.NAMED_ENUM)
// https://github.com/vladmihalcea/hypersistence-utils/issues/657#issuecomment-1824018550
@Enumerated(EnumType.STRING)
@Column(columnDefinition = "level")
@Type(PostgreSQLEnumType::class)
var level: AreaLevel = AreaLevel.COUNTRY,
@JdbcType(PostgreSQLEnumJdbcType::class)
var level: Area_Level = Area_Level.COUNTRY,

/**
* Adjectival representation of the name, e.g. France => French
Expand All @@ -38,7 +43,7 @@ data class Area(
name = "coordinates",
columnDefinition = "double precision[]"
)
override var coordinates: List<Double> = listOf(), /* lon, lat */
override var coordinates: List<Double> = listOf(),/* lon, lat */

) : Mappable {

Expand Down
9 changes: 6 additions & 3 deletions kotlin/src/main/kotlin/net/timafe/angkor/domain/Dish.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
package net.timafe.angkor.domain

// import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
import io.hypersistence.utils.hibernate.type.array.ListArrayType
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
import jakarta.persistence.*
import net.timafe.angkor.config.annotations.EntityTypeInfo
import net.timafe.angkor.domain.enums.AuthScope
import net.timafe.angkor.domain.interfaces.EventSupport
import net.timafe.angkor.domain.interfaces.Taggable
import net.timafe.angkor.service.EntityEventListener
import org.hibernate.annotations.JdbcType
import org.hibernate.annotations.Type
import org.hibernate.dialect.PostgreSQLEnumJdbcType
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedBy
import org.springframework.data.annotation.LastModifiedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.ZonedDateTime
import java.util.*
import jakarta.persistence.*

/**
* Local Dish (Managed Domain Entity)
Expand Down Expand Up @@ -51,7 +53,8 @@ data class Dish(

@Enumerated(EnumType.STRING)
@Column(columnDefinition = "scope")
@Type(PostgreSQLEnumType::class)
// @Type(PostgreSQLEnumType::class)
@JdbcType(PostgreSQLEnumJdbcType::class)
override var authScope: AuthScope = AuthScope.PUBLIC,

@Type(ListArrayType::class)
Expand Down
6 changes: 3 additions & 3 deletions kotlin/src/main/kotlin/net/timafe/angkor/domain/Event.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package net.timafe.angkor.domain

import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import java.time.ZonedDateTime
import java.util.*
import jakarta.persistence.Column
import jakarta.persistence.Entity
import jakarta.persistence.Id

@Entity
data class Event(
Expand Down
19 changes: 12 additions & 7 deletions kotlin/src/main/kotlin/net/timafe/angkor/domain/Link.kt
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
package net.timafe.angkor.domain

// import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
import com.fasterxml.jackson.annotation.JsonFormat
import com.fasterxml.jackson.annotation.JsonInclude
import io.hypersistence.utils.hibernate.type.array.ListArrayType
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLHStoreType
import jakarta.persistence.*
import net.timafe.angkor.config.Constants
import net.timafe.angkor.domain.enums.AuthScope
import net.timafe.angkor.domain.enums.EntityType
import net.timafe.angkor.domain.enums.LinkMediaType
import net.timafe.angkor.domain.enums.Media_Type
import net.timafe.angkor.domain.interfaces.AuthScoped
import net.timafe.angkor.domain.interfaces.Mappable
import org.hibernate.annotations.JdbcType
import org.hibernate.annotations.Type
import org.hibernate.dialect.PostgreSQLEnumJdbcType
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.time.ZonedDateTime
import java.util.*
import jakarta.persistence.*

@Entity
@EntityListeners(AuditingEntityListener::class)
Expand All @@ -35,14 +37,16 @@ data class Link(

@Enumerated(EnumType.STRING)
@Column(columnDefinition = "media_type")
@Type(PostgreSQLEnumType::class)
var mediaType: LinkMediaType = LinkMediaType.DEFAULT,
// @Type(PostgreSQLEnumType::class)
@JdbcType(PostgreSQLEnumJdbcType::class)
var mediaType: Media_Type = Media_Type.DEFAULT,

var entityId: UUID? = null,

@Enumerated(EnumType.STRING)
@Column(columnDefinition = "entity_type")
@Type(PostgreSQLEnumType::class)
// @Type(PostgreSQLEnumType::class)
@JdbcType(PostgreSQLEnumJdbcType::class)
var entityType: EntityType? = null,

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = Constants.JACKSON_DATE_TIME_FORMAT)
Expand All @@ -55,7 +59,8 @@ data class Link(
@Enumerated(EnumType.STRING)
@Column(columnDefinition = "scope")
// @Type(type = "pgsql_enum") -> @Type(PostgreSQLEnumType::class)
@Type(PostgreSQLEnumType::class)
// @Type(PostgreSQLEnumType::class)
@JdbcType(PostgreSQLEnumJdbcType::class)
override var authScope: AuthScope = AuthScope.PUBLIC,

// @Type(type = "list-array") -> @Type(ListArrayType::class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package net.timafe.angkor.domain

// import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
// import org.hibernate.annotations.TypeDef
// import org.hibernate.annotations.TypeDefs
import com.fasterxml.jackson.annotation.JsonIgnore
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonProperty
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLHStoreType
import io.hypersistence.utils.hibernate.type.array.ListArrayType
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLEnumType
import io.hypersistence.utils.hibernate.type.basic.PostgreSQLHStoreType
import jakarta.persistence.*
import net.timafe.angkor.config.Constants
import net.timafe.angkor.domain.enums.AuthScope
import net.timafe.angkor.domain.enums.EntityType
Expand All @@ -14,9 +17,9 @@ import net.timafe.angkor.domain.interfaces.EventSupport
import net.timafe.angkor.domain.interfaces.Mappable
import net.timafe.angkor.domain.interfaces.Taggable
import net.timafe.angkor.service.EntityEventListener
import org.hibernate.annotations.JdbcType
import org.hibernate.annotations.Type
// import org.hibernate.annotations.TypeDef
// import org.hibernate.annotations.TypeDefs
import org.hibernate.dialect.PostgreSQLEnumJdbcType
import org.springframework.data.annotation.CreatedBy
import org.springframework.data.annotation.CreatedDate
import org.springframework.data.annotation.LastModifiedBy
Expand All @@ -25,7 +28,6 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener
import java.io.Serializable
import java.time.ZonedDateTime
import java.util.*
import jakarta.persistence.*

/**
* Base class for anything that qualifies as a [LocatableEntity]
Expand Down Expand Up @@ -81,7 +83,8 @@ open class LocatableEntity(
@Enumerated(EnumType.STRING)
@Column(columnDefinition = "scope")
// https://vladmihalcea.com/the-best-way-to-map-an-enum-type-with-jpa-and-hibernate/
@Type(PostgreSQLEnumType::class)
// @Type(PostgreSQLEnumType::class)
@JdbcType(PostgreSQLEnumJdbcType::class)
override var authScope: AuthScope = AuthScope.PUBLIC,

/**
Expand Down
Loading