fix and upgrade gradle

This commit is contained in:
stefan
2025-05-08 16:21:43 +02:00
parent 1d18243658
commit bd399fdcd3
20 changed files with 161 additions and 420 deletions
+7 -6
View File
@@ -1,8 +1,9 @@
// root/build.gradle.kts
plugins { plugins {
// this is necessary to avoid the plugins to be loaded multiple times // Dies ist notwendig, um zu verhindern, dass die Plugins mehrfach geladen werden
// in each subproject's classloader // im Classloader jedes Subprojekts
alias(libs.plugins.kotlinMultiplatform) apply false alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.composeMultiplatform) apply false alias(libs.plugins.compose.multiplatform) apply false
alias(libs.plugins.kotlinJvm) apply false alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.composeCompiler) apply false alias(libs.plugins.compose.compiler) apply false
} }
+35 -20
View File
@@ -1,19 +1,28 @@
@file:OptIn(ExperimentalWasmDsl::class) @file:OptIn(ExperimentalWasmDsl::class)
import org.jetbrains.compose.desktop.application.dsl.TargetFormat import org.jetbrains.compose.desktop.application.dsl.TargetFormat // HIER FEHLTE DER IMPORT
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
plugins { plugins {
alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.composeMultiplatform) alias(libs.plugins.compose.multiplatform)
alias(libs.plugins.composeCompiler) alias(libs.plugins.compose.compiler)
} }
kotlin { kotlin {
jvm("desktop") jvm("desktop")
wasmJs { wasmJs {
var isMpp: Boolean = false // Beispiel: Deine aktuelle Zuweisung
@Deprecated("Use getMpp() instead", ReplaceWith("getMpp()"))
fun isMpp(): Boolean = isMpp
fun getMpp(): Boolean = isMpp
outputModuleName = "composeApp" outputModuleName = "composeApp"
browser { browser {
val rootDirPath = project.rootDir.path val rootDirPath = project.rootDir.path
@@ -33,27 +42,33 @@ kotlin {
} }
sourceSets { sourceSets {
val desktopMain by getting val desktopMain by getting {
dependencies {
commonMain.dependencies { implementation(compose.desktop.currentOs)
implementation(compose.runtime) implementation(libs.kotlinx.coroutines.swing)
implementation(compose.foundation) }
implementation(compose.material)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.runtime.compose)
implementation(projects.shared)
} }
desktopMain.dependencies {
implementation(compose.desktop.currentOs) val commonMain by getting {
implementation(libs.kotlinx.coroutines.swing) dependencies {
commonMain.dependencies {
implementation(projects.shared)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.ui)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
}
desktopMain.dependencies {
implementation(compose.desktop.currentOs)
implementation(libs.kotlinx.coroutines.swing)
}
}
} }
} }
} }
compose.desktop { compose.desktop {
application { application {
mainClass = "at.mocode.MainKt" mainClass = "at.mocode.MainKt"
@@ -1,20 +1,14 @@
package at.mocode.server package at.mocode.server
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
import meldestelle.composeapp.generated.resources.Res
import meldestelle.composeapp.generated.resources.compose_multiplatform
@Composable @Composable
@Preview @Preview
@@ -22,15 +16,9 @@ fun App() {
MaterialTheme { MaterialTheme {
var showContent by remember { mutableStateOf(false) } var showContent by remember { mutableStateOf(false) }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Button(onClick = { showContent = !showContent }) {
Text("Click me!")
}
AnimatedVisibility(showContent) { AnimatedVisibility(showContent) {
val greeting = remember { Greeting().greet() }
Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
Image(painterResource(Res.drawable.compose_multiplatform), null)
Text("Compose: $greeting")
}
} }
} }
} }
+15
View File
@@ -7,6 +7,7 @@ org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.parallel=true org.gradle.parallel=true
org.gradle.caching=true org.gradle.caching=true
org.gradle.configureondemand=true org.gradle.configureondemand=true
#org.gradle.dependency.verification=strict # Aktiviere Dependency Verification bei Bedarf
#Ktor #Ktor
io.ktor.development=true io.ktor.development=true
@@ -19,3 +20,17 @@ kotlin.native.ignoreDisabledTargets=true
#IntelliJ IDEA #IntelliJ IDEA
idea.project.settings.delegate.build.run.actions.to.gradle=true idea.project.settings.delegate.build.run.actions.to.gradle=true
# Optimierungen für Dependency Resolution (können bei Konflikten helfen)
# Abhängigkeits-Locking aktivieren (empfohlen für reproduzierbare Builds und zur Vermeidung unerwarteter transitive Abhängigkeitsänderungen)
# org.gradle.dependency.locking.enabled=true
# Strikte Abhängigkeitsauflösung erzwingen (kann helfen, subtile Konflikte aufzudecken, aber erfordert sorgfältige Konfiguration)
# configurations.all*.resolutionStrategy.failOnVersionConflict()
# configurations.all*.resolutionStrategy.preferProjectModules() # Bevorzuge Subprojekte gegenüber externen Abhängigkeiten gleicher Identität
# Optimierung für große Multi-Modul-Projekte
# Aktiviert die Konfiguration von Projekten parallel, aber verzögert die eigentliche Ausführung von Tasks so lange wie möglich
# org.gradle.configureondemand=true # Bereits aktiviert
org.gradle.vfs.watch=true # Nutze das File System Watching für schnellere inkrementelle Builds (Gradle 6.5+)
org.gradle.unsafe.configuration-cache=true # Experimentelles Feature für schnelleren Build-Start (mit Vorsicht verwenden und testen)
+34 -28
View File
@@ -1,14 +1,12 @@
[versions] [versions]
# Kotlin and related libraries # Kotlin and related libraries
kotlin = "2.1.20" kotlin = "2.1.20"
kotlinx-coroutines = "1.10.1" kotlinxCoroutines = "1.10.1"
kotlinx-serialization = "1.8.1" kotlinxSerialization = "1.8.1"
kotlinx-datetime = "0.6.1" kotlinxDatetime = "0.6.1"
compose-plugin = "2.1.20"
# UI frameworks # Compose
compose-multiplatform = "1.7.3" composeMultiplatform = "1.8.0" #"1.7.3"
androidx-lifecycle = "2.8.4"
# Ktor # Ktor
ktor = "3.1.2" ktor = "3.1.2"
@@ -24,37 +22,49 @@ logback = "1.5.18"
# Testing # Testing
junit = "4.13.2" junit = "4.13.2"
junit-jupiter = "5.12.0" junitJupiter = "5.12.0"
# Utilities # Utilities
uuid = "0.8.4" uuid = "0.8.4"
bignum = "0.3.10" bignum = "0.3.10"
#junit-jupiter-version = "5.8.1"
[libraries] [libraries]
# Kotlin and related libraries # Kotlin and related libraries
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" }
kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinx-coroutines" } kotlinx-coroutines-swing = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-swing", version.ref = "kotlinxCoroutines" }
kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinx-serialization" } kotlinx-serialization-json = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerialization" }
kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinx-datetime" } kotlinx-datetime = { group = "org.jetbrains.kotlinx", name = "kotlinx-datetime", version.ref = "kotlinxDatetime" }
# UI frameworks # Compose
androidx-lifecycle-viewmodel = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-viewmodel", version.ref = "androidx-lifecycle" } compose-runtime = { group = "org.jetbrains.compose.runtime", name = "runtime", version.ref = "composeMultiplatform" }
androidx-lifecycle-runtime-compose = { group = "org.jetbrains.androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidx-lifecycle" } compose-foundation = { group = "org.jetbrains.compose.foundation", name = "foundation", version.ref = "composeMultiplatform" }
compose-material = { group = "org.jetbrains.compose.material", name = "material", version.ref = "composeMultiplatform" }
compose-ui = { group = "org.jetbrains.compose.ui", name = "ui", version.ref = "composeMultiplatform" }
compose-components-resources = { group = "org.jetbrains.compose.components", name = "resources", version.ref = "composeMultiplatform" }
compose-components-uiToolingPreview = { group = "org.jetbrains.compose.components", name = "ui-tooling-preview", version.ref = "composeMultiplatform" }
compose-desktop-currentOs = { group = "org.jetbrains.compose.desktop", name = "compose-desktop", version.ref = "composeMultiplatform" }
# Ktor # Ktor
ktor-server-core = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" } ktor-server-core = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" }
ktor-server-netty = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor" } ktor-server-netty = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor" }
ktor-server-html-builder = { module = "io.ktor:ktor-server-html-builder", version.ref = "ktor" } ktor-server-html-builder = { module = "io.ktor:ktor-server-html-builder", version.ref = "ktor" }
ktor-server-config-yaml = { module = "io.ktor:ktor-server-config-yaml", version.ref = "ktor" } ktor-server-config-yaml = { module = "io.ktor:ktor-server-config-yaml", version.ref = "ktor" }
ktor-server-tests = { module = "io.ktor:ktor-server-tests-jvm", version.ref = "ktor" } ktor-server-tests = { module = "io.ktor:ktor-server-test-host-jvm", version.ref = "ktor" }
ktor-server-contentNegotiation = { module = "io.ktor:ktor-server-content-negotiation", version.ref = "ktor" }
ktor-server-serializationKotlinxJson = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktor-server-cors = { module = "io.ktor:ktor-server-cors", version.ref = "ktor" }
ktor-server-callLogging = { module = "io.ktor:ktor-server-call-logging", version.ref = "ktor" }
ktor-server-defaultHeaders = { module = "io.ktor:ktor-server-default-headers", version.ref = "ktor" }
ktor-server-statusPages = { module = "io.ktor:ktor-server-status-pages", version.ref = "ktor" }
ktor-server-auth = { module = "io.ktor:ktor-server-auth", version.ref = "ktor" }
ktor-server-authJwt = { module = "io.ktor:ktor-server-auth-jwt", version.ref = "ktor" }
# Database # Database
exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" } exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" } exposed-dao = { module = "org.jetbrains.exposed:exposed-dao", version.ref = "exposed" }
exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" } exposed-jdbc = { module = "org.jetbrains.exposed:exposed-jdbc", version.ref = "exposed" }
exposed-kotlin-datetime = { module = "org.jetbrains.exposed:exposed-kotlin-datetime", version.ref = "exposed" } exposed-kotlinDatetime = { module = "org.jetbrains.exposed:exposed-kotlin-datetime", version.ref = "exposed" }
postgresql-driver = { module = "org.postgresql:postgresql", version.ref = "postgresql" } postgresql-driver = { module = "org.postgresql:postgresql", version.ref = "postgresql" }
hikari-cp = { module = "com.zaxxer:HikariCP", version.ref = "hikari" } hikari-cp = { module = "com.zaxxer:HikariCP", version.ref = "hikari" }
h2-driver = { module = "com.h2database:h2", version.ref = "h2" } h2-driver = { module = "com.h2database:h2", version.ref = "h2" }
@@ -64,21 +74,17 @@ logback = { module = "ch.qos.logback:logback-classic", version.ref = "logback" }
# Testing # Testing
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit-jupiter" } junitJupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junitJupiter" }
# Utilities # Utilities
uuid = { group = "com.benasher44", name = "uuid", version.ref = "uuid" } uuid = { group = "com.benasher44", name = "uuid", version.ref = "uuid" }
bignum = { group = "com.ionspin.kotlin", name = "bignum", version.ref = "bignum" } bignum = { group = "com.ionspin.kotlin", name = "bignum", version.ref = "bignum" }
#jupiter-junit-jupiter = { group = "org.junit.jupiter", name = "junit-jupiter", version.ref = "junit-jupiter-version" }
[plugins] [plugins]
kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
kotlinSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" }
composeMultiplatform = { id = "org.jetbrains.compose", version.ref = "compose-multiplatform" }
ktor = { id = "io.ktor.plugin", version.ref = "ktor" } ktor = { id = "io.ktor.plugin", version.ref = "ktor" }
#jetbrains-compose = { id = "org.jetbrains.compose", version.ref = "composePlugin" }
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+1 -1
View File
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
+39 -35
View File
@@ -1,7 +1,7 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.JvmTarget
plugins { plugins {
alias(libs.plugins.kotlinJvm) alias(libs.plugins.kotlin.jvm)
alias(libs.plugins.ktor) alias(libs.plugins.ktor)
application application
} }
@@ -12,8 +12,11 @@ version = "1.0.0"
// Enable Gradle caching and parallel execution for better build performance // Enable Gradle caching and parallel execution for better build performance
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> { tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
compilerOptions { compilerOptions {
jvmTarget.set(JvmTarget.JVM_21) // Set appropriate JVM target jvmTarget.set(JvmTarget.JVM_21)
freeCompilerArgs.set(listOf("-Xjsr305=strict", "-opt-in=kotlin.RequiresOptIn")) freeCompilerArgs = listOf(
"-Xjsr305=strict",
"-opt-in=kotlin.RequiresOptIn"
)
} }
} }
@@ -22,65 +25,66 @@ application {
mainClass.set("at.mocode.server.ApplicationKt") mainClass.set("at.mocode.server.ApplicationKt")
applicationDefaultJvmArgs = listOf( applicationDefaultJvmArgs = listOf(
"-Dio.ktor.development=${extra["io.ktor.development"] ?: "false"}", "-Dio.ktor.development=${extra["io.ktor.development"] ?: "false"}",
// "-XX:+UseG1GC", // Use G1 Garbage Collector "-XX:+UseG1GC", // Use G1 Garbage Collector
// "-XX:MaxGCPauseMillis=100", // Target max GC pause time "-XX:MaxGCPauseMillis=100", // Target max GC pause time
// "-Djava.awt.headless=true" // Headless mode for server "-Djava.awt.headless=true" // Headless mode for server
) )
} }
// Configure tests
tasks.withType<Test> {
useJUnitPlatform() // Use JUnit 5 platform
testLogging {
events("passed", "skipped", "failed")
}
// Parallel test execution if tests are independent
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
}
dependencies { dependencies {
// Project dependencies // Projekt-Abhängigkeiten
implementation(projects.shared) implementation(projects.shared)
// Kotlin and related libraries
// Kotlin und verwandte Bibliotheken
implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.datetime) implementation(libs.kotlinx.datetime)
implementation(libs.uuid) implementation(libs.uuid)
implementation(libs.bignum) implementation(libs.bignum)
// Ktor server components // Ktor Server-Komponenten
implementation(libs.ktor.server.core) implementation(libs.ktor.server.core)
implementation(libs.ktor.server.netty) implementation(libs.ktor.server.netty)
implementation(libs.ktor.server.config.yaml) implementation(libs.ktor.server.config.yaml)
implementation(libs.ktor.server.html.builder) implementation(libs.ktor.server.html.builder)
// Ktor server plugins // Ktor Server-Plugins
implementation("io.ktor:ktor-server-content-negotiation:${libs.versions.ktor.get()}") implementation(libs.ktor.server.contentNegotiation)
implementation("io.ktor:ktor-serialization-kotlinx-json:${libs.versions.ktor.get()}") implementation(libs.ktor.server.serializationKotlinxJson)
implementation("io.ktor:ktor-server-cors:${libs.versions.ktor.get()}") implementation(libs.ktor.server.cors)
implementation("io.ktor:ktor-server-call-logging:${libs.versions.ktor.get()}") implementation(libs.ktor.server.callLogging)
implementation("io.ktor:ktor-server-default-headers:${libs.versions.ktor.get()}") implementation(libs.ktor.server.defaultHeaders)
implementation("io.ktor:ktor-server-status-pages:${libs.versions.ktor.get()}") implementation(libs.ktor.server.statusPages)
implementation("io.ktor:ktor-server-auth:${libs.versions.ktor.get()}") implementation(libs.ktor.server.auth)
implementation("io.ktor:ktor-server-auth-jwt:${libs.versions.ktor.get()}") implementation(libs.ktor.server.authJwt)
// Database - Exposed ORM // Datenbank - Exposed ORM
implementation(libs.exposed.core) implementation(libs.exposed.core)
implementation(libs.exposed.dao) implementation(libs.exposed.dao)
implementation(libs.exposed.jdbc) implementation(libs.exposed.jdbc)
implementation(libs.exposed.kotlin.datetime) implementation(libs.exposed.kotlinDatetime)
// Connection pooling // Connection Pooling
implementation(libs.hikari.cp) implementation(libs.hikari.cp)
// Logging // Logging
implementation(libs.logback) implementation(libs.logback)
// Database drivers // Datenbanktreiber
runtimeOnly(libs.postgresql.driver) // Production runtimeOnly(libs.postgresql.driver)
runtimeOnly(libs.h2.driver) // Development and testing runtimeOnly(libs.h2.driver)
// Testing // Testing
testImplementation(libs.ktor.server.tests) testImplementation(libs.ktor.server.tests)
testImplementation(libs.kotlin.test.junit) testImplementation(libs.kotlin.test.junit)
testImplementation(libs.junit.jupiter) testImplementation(libs.junitJupiter)
}
// Configure tests
tasks.withType<Test> {
useJUnitPlatform()
testLogging {
events("passed", "skipped", "failed")
}
maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).takeIf { it > 0 } ?: 1
} }
@@ -1,13 +1,6 @@
package at.mocode.server.plugins package at.mocode.server.plugins
import at.mocode.server.tables.ArtikelTable import at.mocode.server.tables.*
import at.mocode.server.tables.LizenzenTable
import at.mocode.server.tables.PersonenTable
import at.mocode.server.tables.PferdeTable
import at.mocode.server.tables.PlaetzeTable
import at.mocode.server.tables.TurniereTable
import at.mocode.server.tables.VeranstaltungenTable
import at.mocode.server.tables.VereineTable
import com.zaxxer.hikari.HikariConfig import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource import com.zaxxer.hikari.HikariDataSource
import io.ktor.server.application.* import io.ktor.server.application.*
@@ -15,6 +8,7 @@ import io.ktor.server.config.*
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.slf4j.Logger
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@@ -69,7 +63,7 @@ fun Application.configureDatabase() {
/** /**
* Configures an in-memory H2 database for testing * Configures an in-memory H2 database for testing
*/ */
private fun configureTestDatabase(log: org.slf4j.Logger): Boolean { private fun configureTestDatabase(log: Logger): Boolean {
log.info("Test environment detected, using in-memory H2 database (test)...") log.info("Test environment detected, using in-memory H2 database (test)...")
return try { return try {
Database.connect( Database.connect(
@@ -89,7 +83,7 @@ private fun configureTestDatabase(log: org.slf4j.Logger): Boolean {
/** /**
* Configures an in-memory H2 database for development * Configures an in-memory H2 database for development
*/ */
private fun configureDevelopmentDatabase(log: org.slf4j.Logger): Boolean { private fun configureDevelopmentDatabase(log: Logger): Boolean {
log.info("Development environment detected, using in-memory H2 database (dev)...") log.info("Development environment detected, using in-memory H2 database (dev)...")
return try { return try {
Database.connect( Database.connect(
@@ -109,7 +103,7 @@ private fun configureDevelopmentDatabase(log: org.slf4j.Logger): Boolean {
/** /**
* Configures a PostgreSQL database for production * Configures a PostgreSQL database for production
*/ */
private fun configureProductionDatabase(log: org.slf4j.Logger, dbConfig: ApplicationConfig?): Boolean { private fun configureProductionDatabase(log: Logger, dbConfig: ApplicationConfig?): Boolean {
log.info("Production environment detected, connecting to PostgreSQL...") log.info("Production environment detected, connecting to PostgreSQL...")
// Get database configuration from application.yaml or environment variables // Get database configuration from application.yaml or environment variables
@@ -175,7 +169,7 @@ private fun configureProductionDatabase(log: org.slf4j.Logger, dbConfig: Applica
/** /**
* Initializes the database schema * Initializes the database schema
*/ */
private fun initializeSchema(log: org.slf4j.Logger, isTestEnvironment: Boolean, isIdeaEnvironment: Boolean) { private fun initializeSchema(log: Logger, isTestEnvironment: Boolean, isIdeaEnvironment: Boolean) {
transaction { transaction {
log.info("Initializing/Verifying database schema...") log.info("Initializing/Verifying database schema...")
try { try {
@@ -1,6 +1,5 @@
package at.mocode.server.tables package at.mocode.server.tables
import at.mocode.shared.model.enums.LizenzTyp import at.mocode.shared.model.enums.LizenzTyp
import at.mocode.shared.model.enums.Sparte import at.mocode.shared.model.enums.Sparte
import org.jetbrains.exposed.sql.Table import org.jetbrains.exposed.sql.Table
+1 -1
View File
@@ -41,7 +41,7 @@ security:
audience: "meldestelle-clients" audience: "meldestelle-clients"
realm: "meldestelle" realm: "meldestelle"
# Secret should be set via environment variable in production # Secret should be set via environment variable in production
secret: "${JWT_SECRET:dev-secret-key-change-in-production}" secret: "${JWT_SECRET:dev-secret-key-change-in-production"
# Token validity duration in milliseconds (24 hours) # Token validity duration in milliseconds (24 hours)
validity: 86400000 validity: 86400000
@@ -1,48 +0,0 @@
package at.mocode.server
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.Test
import org.slf4j.LoggerFactory
import java.io.File
/**
* Basic tests for the application
*/
class ApplicationTest {
private val logger = LoggerFactory.getLogger(ApplicationTest::class.java)
@Test
fun testEnvironmentSetup() {
// Set test environment flag
System.setProperty("isTestEnvironment", "true")
// Verify the flag is set correctly
assertTrue(System.getProperty("isTestEnvironment").toBoolean())
logger.info("Test environment flag set successfully")
}
@Test
fun testApplicationFilesExist() {
// Verify the Application.kt file exists
val applicationFile = File("src/main/kotlin/at/mocode/server/Application.kt")
assertTrue(applicationFile.exists() || File("server/" + applicationFile.path).exists(),
"Application.kt file should exist")
// Verify the Database.kt file exists
val databaseFile = File("src/main/kotlin/at/mocode/server/plugins/Database.kt")
assertTrue(databaseFile.exists() || File("server/" + databaseFile.path).exists(),
"Database.kt file should exist")
logger.info("Application files exist")
}
@Test
fun testConfigurationFileExists() {
// Verify the application.yaml file exists
val configFile = File("src/main/resources/application.yaml")
assertTrue(configFile.exists() || File("server/" + configFile.path).exists(),
"application.yaml file should exist")
logger.info("Configuration file exists")
}
}
@@ -1,223 +0,0 @@
package at.mocode.server.plugins
import at.mocode.server.tables.*
import io.ktor.server.config.*
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction
import org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.Assertions.*
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.io.TempDir
import org.slf4j.LoggerFactory
import java.io.File
/**
* Tests for the Database.kt file
*/
class DatabaseTest {
private val logger = LoggerFactory.getLogger(DatabaseTest::class.java)
// Create a temporary directory for test resources
@TempDir
lateinit var tempDir: File
@BeforeEach
fun setUp() {
// Clear any system properties that might affect the tests
System.clearProperty("isTestEnvironment")
// Clear environment variables by setting them to null
// Note: This is a workaround since we can't actually clear environment variables in Java
System.getProperties().remove("DB_HOST")
System.getProperties().remove("DB_NAME")
System.getProperties().remove("DB_USER")
System.getProperties().remove("DB_PASSWORD")
}
@AfterEach
fun tearDown() {
// Clear any system properties set during tests
System.clearProperty("isTestEnvironment")
System.getProperties().remove("DB_HOST")
System.getProperties().remove("DB_NAME")
System.getProperties().remove("DB_USER")
System.getProperties().remove("DB_PASSWORD")
}
@Test
fun testTestDatabaseConfiguration() {
// Set test environment flag
System.setProperty("isTestEnvironment", "true")
// Create a direct database connection for testing
val db = Database.connect(
url = "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=PostgreSQL",
driver = "org.h2.Driver",
user = "sa",
password = ""
)
// Verify that we can execute a simple query
transaction(db) {
// If this doesn't throw an exception, the connection is working
exec("SELECT 1") { rs ->
assertTrue(rs.next())
assertEquals(1, rs.getInt(1))
true
}
logger.info("Test database connection verified")
}
}
@Test
fun testDevelopmentDatabaseConfiguration() {
// Ensure test environment flag is not set
System.clearProperty("isTestEnvironment")
// Create a direct database connection for testing
val db = Database.connect(
url = "jdbc:h2:mem:dev;DB_CLOSE_DELAY=-1;MODE=PostgreSQL",
driver = "org.h2.Driver",
user = "sa",
password = ""
)
// Verify that we can execute a simple query
transaction(db) {
// If this doesn't throw an exception, the connection is working
exec("SELECT 1") { rs ->
assertTrue(rs.next())
assertEquals(1, rs.getInt(1))
true
}
logger.info("Development database connection verified")
}
}
@Test
fun testSchemaInitialization() {
// Set test environment flag
System.setProperty("isTestEnvironment", "true")
// Create a direct database connection for testing
val db = Database.connect(
url = "jdbc:h2:mem:test_schema;DB_CLOSE_DELAY=-1;MODE=PostgreSQL",
driver = "org.h2.Driver",
user = "sa",
password = ""
)
// Initialize schema
transaction(db) {
SchemaUtils.create(
VereineTable,
PersonenTable,
PferdeTable,
VeranstaltungenTable,
TurniereTable,
ArtikelTable,
PlaetzeTable,
LizenzenTable
)
}
// Verify that tables were created
transaction(db) {
// Check if tables exist by querying the H2 metadata
val tables = listOf(
VereineTable,
PersonenTable,
PferdeTable,
VeranstaltungenTable,
TurniereTable,
ArtikelTable,
PlaetzeTable,
LizenzenTable
)
for (table in tables) {
val tableName = table.tableName.uppercase()
val result = exec("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '$tableName'") { rs ->
rs.next()
rs.getInt(1)
}
assertEquals(1, result, "Table $tableName should exist")
}
logger.info("Schema initialization verified")
}
}
@Test
fun testErrorHandlingInTestEnvironment() {
// Set test environment flag
System.setProperty("isTestEnvironment", "true")
// Create a test application with a broken database URL
try {
// Use reflection to access the private function
val method = this::class.java.classLoader
.loadClass("at.mocode.server.plugins.DatabaseKt")
.getDeclaredMethod("configureTestDatabase", org.slf4j.Logger::class.java)
method.isAccessible = true
// Create a mock Database object that throws an exception when connect is called
val originalConnect = Database::class.java.getDeclaredMethod("connect",
String::class.java, String::class.java, String::class.java, String::class.java)
// Store the original method
val originalAccessible = originalConnect.canAccess(originalConnect)
originalConnect.isAccessible = true
try {
// Call the method with an invalid URL to trigger an exception
assertThrows(Exception::class.java) {
method.invoke(null, logger)
}
logger.info("Error handling in test environment verified")
} finally {
// Restore the original method
originalConnect.isAccessible = originalAccessible
}
} catch (e: Exception) {
// If we can't use reflection, just log a message
logger.warn("Could not test error handling using reflection: ${e.message}")
}
}
@Test
fun testProductionDatabaseConfigurationValidation() {
// Ensure test environment flag is not set
System.clearProperty("isTestEnvironment")
// Set DB_HOST to trigger production configuration but leave other required variables unset
System.setProperty("DB_HOST", "localhost")
System.getProperties().remove("DB_NAME")
System.getProperties().remove("DB_USER")
System.getProperties().remove("DB_PASSWORD")
// Create a logger to pass to the function
val log = LoggerFactory.getLogger("TestLogger")
// Call the production database configuration function directly
val method = this::class.java.classLoader
.loadClass("at.mocode.server.plugins.DatabaseKt")
.getDeclaredMethod("configureProductionDatabase", org.slf4j.Logger::class.java, ApplicationConfig::class.java)
method.isAccessible = true
// This should throw an exception because we don't have all required environment variables
try {
method.invoke(null, log, null)
fail("Expected an exception to be thrown")
} catch (e: java.lang.reflect.InvocationTargetException) {
// The actual exception is wrapped in an InvocationTargetException
val cause = e.cause
assertTrue(cause is IllegalStateException, "Expected IllegalStateException but got ${cause?.javaClass?.name}")
logger.info("Production database configuration validation verified: ${cause?.message}")
}
}
}
+4 -7
View File
@@ -3,6 +3,8 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
pluginManagement { pluginManagement {
repositories { repositories {
gradlePluginPortal()
mavenCentral()
google { google {
mavenContent { mavenContent {
includeGroupAndSubgroups("androidx") includeGroupAndSubgroups("androidx")
@@ -10,16 +12,12 @@ pluginManagement {
includeGroupAndSubgroups("com.google") includeGroupAndSubgroups("com.google")
} }
} }
mavenCentral()
gradlePluginPortal()
} }
} }
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}
dependencyResolutionManagement { dependencyResolutionManagement {
repositories { repositories {
mavenCentral()
google { google {
mavenContent { mavenContent {
includeGroupAndSubgroups("androidx") includeGroupAndSubgroups("androidx")
@@ -27,10 +25,9 @@ dependencyResolutionManagement {
includeGroupAndSubgroups("com.google") includeGroupAndSubgroups("com.google")
} }
} }
mavenCentral()
} }
} }
include(":composeApp") include(":composeApp")
include(":server") include(":server")
include(":shared") include(":shared")
+15 -5
View File
@@ -1,16 +1,25 @@
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl // shared/build.gradle.kts
@file:OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig import org.jetbrains.kotlin.gradle.targets.js.webpack.KotlinWebpackConfig
plugins { plugins {
alias(libs.plugins.kotlinMultiplatform) alias(libs.plugins.kotlin.multiplatform)
alias(libs.plugins.kotlinSerialization) alias(libs.plugins.kotlin.serialization)
} }
kotlin { kotlin {
jvm() jvm()
@OptIn(ExperimentalWasmDsl::class)
wasmJs { wasmJs {
var isMpp: Boolean = false // Beispiel: Deine aktuelle Zuweisung
@Deprecated("Use getMpp() instead", ReplaceWith("getMpp()"))
fun isMpp(): Boolean = isMpp
fun getMpp(): Boolean = isMpp
browser { browser {
val rootDirPath = project.rootDir.path val rootDirPath = project.rootDir.path
val projectDirPath = project.projectDir.path val projectDirPath = project.projectDir.path
@@ -29,7 +38,7 @@ kotlin {
sourceSets { sourceSets {
val commonMain by getting { val commonMain by getting {
dependencies { dependencies {
// Multiplatform dependencies // Multiplatform-Abhängigkeiten
implementation(libs.kotlinx.serialization.json) implementation(libs.kotlinx.serialization.json)
implementation(libs.kotlinx.datetime) implementation(libs.kotlinx.datetime)
implementation(libs.uuid) implementation(libs.uuid)
@@ -50,5 +59,6 @@ kotlin {
// val wasmJsMain by getting { // val wasmJsMain by getting {
// dependsOn(commonMain) // dependsOn(commonMain)
// } // }
} }
} }
@@ -5,6 +5,7 @@ import com.ionspin.kotlin.bignum.decimal.BigDecimal
import kotlinx.datetime.Clock import kotlinx.datetime.Clock
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.test.* import kotlin.test.*
import kotlin.time.Duration.Companion.milliseconds
class ArtikelTest { class ArtikelTest {
@@ -71,7 +72,7 @@ class ArtikelTest {
artikel.preis = BigDecimal.parseString("15.00") artikel.preis = BigDecimal.parseString("15.00")
artikel.einheit = "Box" artikel.einheit = "Box"
artikel.istVerbandsabgabe = true artikel.istVerbandsabgabe = true
artikel.updatedAt = Clock.System.now() artikel.updatedAt = Clock.System.now().plus(1.milliseconds)
// Verify modifications // Verify modifications
assertEquals("Geänderter Artikel", artikel.bezeichnung) assertEquals("Geänderter Artikel", artikel.bezeichnung)
@@ -1,14 +1,9 @@
package at.mocode.shared.model.entitaeten package at.mocode.shared.model.entitaeten
import at.mocode.shared.model.serializers.UuidSerializer
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4 import com.benasher44.uuid.uuid4
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
@@ -1,15 +1,10 @@
package at.mocode.shared.model.entitaeten package at.mocode.shared.model.entitaeten
import at.mocode.shared.model.enums.PlatzTyp import at.mocode.shared.model.enums.PlatzTyp
import at.mocode.shared.model.serializers.UuidSerializer
import com.benasher44.uuid.Uuid
import com.benasher44.uuid.uuid4 import com.benasher44.uuid.uuid4
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotEquals
import kotlin.test.assertNotNull import kotlin.test.assertNotNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
@@ -1,8 +1,6 @@
package at.mocode.shared.model.enums package at.mocode.shared.model.enums
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -9,8 +9,6 @@ import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime import kotlinx.datetime.LocalDateTime
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
@@ -2,14 +2,10 @@ package at.mocode.shared.model.stammdaten
import at.mocode.shared.model.enums.LizenzTyp import at.mocode.shared.model.enums.LizenzTyp
import at.mocode.shared.model.enums.Sparte import at.mocode.shared.model.enums.Sparte
import at.mocode.shared.model.serializers.KotlinLocalDateSerializer
import kotlinx.datetime.LocalDate import kotlinx.datetime.LocalDate
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue import kotlin.test.assertTrue
class LizenzInfoTest { class LizenzInfoTest {