feat(horses-service): remove legacy configuration and repository classes
Build and Publish Docker Images / build-and-push (., backend/infrastructure/gateway/Dockerfile, api-gateway, api-gateway) (push) Successful in 7m12s
Build and Publish Docker Images / build-and-push (., backend/services/ping/Dockerfile, ping-service, ping-service) (push) Successful in 6m42s
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Successful in 6m28s
Build and Publish Docker Images / build-and-push (., config/docker/keycloak/Dockerfile, keycloak, keycloak) (push) Successful in 1m51s
Build and Publish Docker Images / build-and-push (., backend/infrastructure/gateway/Dockerfile, api-gateway, api-gateway) (push) Successful in 7m12s
Build and Publish Docker Images / build-and-push (., backend/services/ping/Dockerfile, ping-service, ping-service) (push) Successful in 6m42s
Build and Publish Docker Images / build-and-push (., config/docker/caddy/web-app/Dockerfile, web-app, web-app) (push) Successful in 6m28s
Build and Publish Docker Images / build-and-push (., config/docker/keycloak/Dockerfile, keycloak, keycloak) (push) Successful in 1m51s
- Deleted outdated `ApplicationConfiguration` and `HorseRepositoryImpl` classes. - Migrated to streamlined modular Gradle configuration in `build.gradle.kts`. - Updated domain models and dependencies to use multiplatform and serialization plugins. - Added modular setup for `horses` namespace in `settings.gradle.kts`. - Reorganized database configuration with minimal JDBC bindings for development. Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
alias(libs.plugins.kotlinJvm)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,9 +1,26 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
testImplementation(projects.platform.platformTesting)
|
||||
kotlin {
|
||||
jvm()
|
||||
|
||||
sourceSets {
|
||||
commonMain {
|
||||
kotlin.srcDir("src/main/kotlin")
|
||||
dependencies {
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
implementation(libs.kotlinx.datetime)
|
||||
implementation(libs.kotlinx.serialization.json)
|
||||
}
|
||||
}
|
||||
commonTest {
|
||||
kotlin.srcDir("src/test/kotlin")
|
||||
dependencies {
|
||||
implementation(projects.platform.platformTesting)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-6
@@ -1,16 +1,16 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
package at.mocode.horses.domain.model
|
||||
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.domain.serialization.KotlinInstantSerializer
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
import kotlin.uuid.Uuid
|
||||
import kotlinx.datetime.Clock
|
||||
import kotlinx.datetime.Instant
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlinx.datetime.todayIn
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlin.time.Clock
|
||||
import kotlin.time.Instant
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Domain model representing a horse in the registry system.
|
||||
@@ -129,7 +129,7 @@ data class DomPferd(
|
||||
*/
|
||||
fun getAge(): Int? {
|
||||
return geburtsdatum?.let { birthDate ->
|
||||
val today = kotlinx.datetime.Clock.System.todayIn(kotlinx.datetime.TimeZone.currentSystemDefault())
|
||||
val today = kotlin.time.Clock.System.todayIn(kotlinx.datetime.TimeZone.currentSystemDefault())
|
||||
var age = today.year - birthDate.year
|
||||
|
||||
// Check if birthday has occurred this year
|
||||
@@ -167,6 +167,6 @@ data class DomPferd(
|
||||
* Creates a copy of this horse with updated timestamp.
|
||||
*/
|
||||
fun withUpdatedTimestamp(): DomPferd {
|
||||
return this.copy(updatedAt = Clock.System.now())
|
||||
return this.copy(updatedAt = kotlin.time.Clock.System.now())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
plugins {
|
||||
// KORREKTUR: Alle Plugins werden jetzt konsistent über den Version Catalog geladen.
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.kotlin.spring)
|
||||
// Das JPA-Plugin wird jetzt ebenfalls zentral verwaltet.
|
||||
alias(libs.plugins.kotlin.jpa)
|
||||
alias(libs.plugins.kotlinJvm)
|
||||
alias(libs.plugins.kotlinSpring)
|
||||
alias(libs.plugins.kotlinSerialization)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Interne Module
|
||||
implementation(projects.platform.platformDependencies)
|
||||
implementation(projects.horses.horsesDomain)
|
||||
implementation(projects.horses.horsesApplication)
|
||||
// horses-common: ON HOLD
|
||||
// implementation(projects.horses.horsesCommon)
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
implementation(projects.infrastructure.cache.cacheApi)
|
||||
implementation(projects.infrastructure.eventStore.eventStoreApi)
|
||||
implementation(projects.infrastructure.messaging.messagingClient)
|
||||
|
||||
// KORREKTUR: Alle externen Abhängigkeiten werden jetzt über den Version Catalog bezogen.
|
||||
// Spring
|
||||
implementation(libs.spring.boot.starter.web)
|
||||
|
||||
// Spring Data JPA
|
||||
implementation(libs.spring.boot.starter.data.jpa)
|
||||
// Datenbank via Exposed
|
||||
implementation(libs.exposed.core)
|
||||
implementation(libs.exposed.dao)
|
||||
implementation(libs.exposed.jdbc)
|
||||
implementation(libs.exposed.kotlin.datetime)
|
||||
|
||||
// Datenbank-Treiber
|
||||
runtimeOnly(libs.postgresql.driver)
|
||||
|
||||
-336
@@ -1,336 +0,0 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
package at.mocode.horses.infrastructure.persistence
|
||||
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.horses.domain.model.DomPferd
|
||||
import at.mocode.horses.domain.repository.HorseRepository
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import kotlin.uuid.Uuid
|
||||
import kotlinx.datetime.Clock
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.statements.UpdateBuilder
|
||||
import org.springframework.stereotype.Repository
|
||||
|
||||
/**
|
||||
* PostgreSQL implementation of the HorseRepository using Exposed ORM.
|
||||
*
|
||||
* This implementation provides database operations for horse entities,
|
||||
* mapping between the domain model (DomPferd) and the database table (HorseTable).
|
||||
*/
|
||||
@Repository
|
||||
class HorseRepositoryImpl : HorseRepository {
|
||||
|
||||
override suspend fun findById(id: Uuid): DomPferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.id eq id }
|
||||
.map { rowToDomPferd(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByLebensnummer(lebensnummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.lebensnummer eq lebensnummer }
|
||||
.map { rowToDomPferd(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByChipNummer(chipNummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.chipNummer eq chipNummer }
|
||||
.map { rowToDomPferd(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByPassNummer(passNummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.passNummer eq passNummer }
|
||||
.map { rowToDomPferd(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByOepsNummer(oepsNummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.oepsNummer eq oepsNummer }
|
||||
.map { rowToDomPferd(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByFeiNummer(feiNummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.feiNummer eq feiNummer }
|
||||
.map { rowToDomPferd(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.pferdeName like "%$searchTerm%" }
|
||||
.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.limit(limit)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.besitzerId eq ownerId }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.verantwortlichePersonId eq responsiblePersonId }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findByGeschlecht(geschlecht: PferdeGeschlechtE, activeOnly: Boolean, limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.geschlecht eq geschlecht }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.limit(limit)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findByRasse(rasse: String, activeOnly: Boolean, limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.rasse eq rasse }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.limit(limit)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where {
|
||||
HorseTable.geburtsdatum.isNotNull() and
|
||||
(CustomFunction(
|
||||
"EXTRACT",
|
||||
IntegerColumnType(),
|
||||
stringLiteral("YEAR FROM "),
|
||||
HorseTable.geburtsdatum
|
||||
) eq birthYear)
|
||||
}
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where {
|
||||
HorseTable.geburtsdatum.isNotNull() and
|
||||
(CustomFunction(
|
||||
"EXTRACT",
|
||||
IntegerColumnType(),
|
||||
stringLiteral("YEAR FROM "),
|
||||
HorseTable.geburtsdatum
|
||||
) greaterEq fromYear) and
|
||||
(CustomFunction(
|
||||
"EXTRACT",
|
||||
IntegerColumnType(),
|
||||
stringLiteral("YEAR FROM "),
|
||||
HorseTable.geburtsdatum
|
||||
) lessEq toYear)
|
||||
}
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.geburtsdatum, SortOrder.DESC)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findAllActive(limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.istAktiv eq true }
|
||||
.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.limit(limit)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findOepsRegistered(activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.oepsNummer.isNotNull() }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun findFeiRegistered(activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.feiNummer.isNotNull() }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.orderBy(HorseTable.pferdeName to SortOrder.ASC)
|
||||
.map { rowToDomPferd(it) }
|
||||
}
|
||||
|
||||
override suspend fun save(horse: DomPferd): DomPferd = DatabaseFactory.dbQuery {
|
||||
val now = Clock.System.now()
|
||||
val existingHorse = findById(horse.pferdId)
|
||||
|
||||
if (existingHorse != null) {
|
||||
// Update existing horse
|
||||
val updatedHorse = horse.copy(updatedAt = now)
|
||||
HorseTable.update({ HorseTable.id eq horse.pferdId }) {
|
||||
domPferdToStatement(it, updatedHorse)
|
||||
}
|
||||
updatedHorse
|
||||
} else {
|
||||
// Insert a new horse
|
||||
HorseTable.insert {
|
||||
it[id] = horse.pferdId
|
||||
domPferdToStatement(it, horse.copy(updatedAt = now))
|
||||
}
|
||||
horse.copy(updatedAt = now)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
|
||||
val deletedRows = HorseTable.deleteWhere { HorseTable.id eq id }
|
||||
deletedRows > 0
|
||||
}
|
||||
|
||||
override suspend fun existsByLebensnummer(lebensnummer: String): Boolean = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.lebensnummer eq lebensnummer }
|
||||
.count() > 0
|
||||
}
|
||||
|
||||
override suspend fun existsByChipNummer(chipNummer: String): Boolean = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.chipNummer eq chipNummer }
|
||||
.count() > 0
|
||||
}
|
||||
|
||||
override suspend fun existsByPassNummer(passNummer: String): Boolean = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.passNummer eq passNummer }
|
||||
.count() > 0
|
||||
}
|
||||
|
||||
override suspend fun existsByOepsNummer(oepsNummer: String): Boolean = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.oepsNummer eq oepsNummer }
|
||||
.count() > 0
|
||||
}
|
||||
|
||||
override suspend fun existsByFeiNummer(feiNummer: String): Boolean = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.feiNummer eq feiNummer }
|
||||
.count() > 0
|
||||
}
|
||||
|
||||
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.istAktiv eq true }
|
||||
.count()
|
||||
}
|
||||
|
||||
override suspend fun countByOwnerId(ownerId: Uuid, activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where { HorseTable.besitzerId eq ownerId }
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.count()
|
||||
}
|
||||
|
||||
override suspend fun countOepsRegistered(activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where {
|
||||
HorseTable.oepsNummer.isNotNull() and (HorseTable.oepsNummer neq "")
|
||||
}
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.count()
|
||||
}
|
||||
|
||||
override suspend fun countFeiRegistered(activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
|
||||
val query = HorseTable.selectAll().where {
|
||||
HorseTable.feiNummer.isNotNull() and (HorseTable.feiNummer neq "")
|
||||
}
|
||||
|
||||
if (activeOnly) {
|
||||
query.andWhere { HorseTable.istAktiv eq true }
|
||||
} else {
|
||||
query
|
||||
}.count()
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a database row to a DomPferd domain object.
|
||||
*/
|
||||
private fun rowToDomPferd(row: ResultRow): DomPferd {
|
||||
return DomPferd(
|
||||
pferdId = row[HorseTable.id].value,
|
||||
pferdeName = row[HorseTable.pferdeName],
|
||||
geschlecht = row[HorseTable.geschlecht],
|
||||
geburtsdatum = row[HorseTable.geburtsdatum],
|
||||
rasse = row[HorseTable.rasse],
|
||||
farbe = row[HorseTable.farbe],
|
||||
besitzerId = row[HorseTable.besitzerId],
|
||||
verantwortlichePersonId = row[HorseTable.verantwortlichePersonId],
|
||||
zuechterName = row[HorseTable.zuechterName],
|
||||
zuchtbuchNummer = row[HorseTable.zuchtbuchNummer],
|
||||
lebensnummer = row[HorseTable.lebensnummer],
|
||||
chipNummer = row[HorseTable.chipNummer],
|
||||
passNummer = row[HorseTable.passNummer],
|
||||
oepsNummer = row[HorseTable.oepsNummer],
|
||||
feiNummer = row[HorseTable.feiNummer],
|
||||
vaterName = row[HorseTable.vaterName],
|
||||
mutterName = row[HorseTable.mutterName],
|
||||
mutterVaterName = row[HorseTable.mutterVaterName],
|
||||
stockmass = row[HorseTable.stockmass],
|
||||
istAktiv = row[HorseTable.istAktiv],
|
||||
bemerkungen = row[HorseTable.bemerkungen],
|
||||
datenQuelle = row[HorseTable.datenQuelle],
|
||||
createdAt = row[HorseTable.createdAt],
|
||||
updatedAt = row[HorseTable.updatedAt]
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a DomPferd domain object to database statement values.
|
||||
*/
|
||||
private fun domPferdToStatement(statement: UpdateBuilder<*>, horse: DomPferd) {
|
||||
statement[HorseTable.pferdeName] = horse.pferdeName
|
||||
statement[HorseTable.geschlecht] = horse.geschlecht
|
||||
statement[HorseTable.geburtsdatum] = horse.geburtsdatum
|
||||
statement[HorseTable.rasse] = horse.rasse
|
||||
statement[HorseTable.farbe] = horse.farbe
|
||||
statement[HorseTable.besitzerId] = horse.besitzerId
|
||||
statement[HorseTable.verantwortlichePersonId] = horse.verantwortlichePersonId
|
||||
statement[HorseTable.zuechterName] = horse.zuechterName
|
||||
statement[HorseTable.zuchtbuchNummer] = horse.zuchtbuchNummer
|
||||
statement[HorseTable.lebensnummer] = horse.lebensnummer
|
||||
statement[HorseTable.chipNummer] = horse.chipNummer
|
||||
statement[HorseTable.passNummer] = horse.passNummer
|
||||
statement[HorseTable.oepsNummer] = horse.oepsNummer
|
||||
statement[HorseTable.feiNummer] = horse.feiNummer
|
||||
statement[HorseTable.vaterName] = horse.vaterName
|
||||
statement[HorseTable.mutterName] = horse.mutterName
|
||||
statement[HorseTable.mutterVaterName] = horse.mutterVaterName
|
||||
statement[HorseTable.stockmass] = horse.stockmass
|
||||
statement[HorseTable.istAktiv] = horse.istAktiv
|
||||
statement[HorseTable.bemerkungen] = horse.bemerkungen
|
||||
statement[HorseTable.datenQuelle] = horse.datenQuelle
|
||||
statement[HorseTable.createdAt] = horse.createdAt
|
||||
statement[HorseTable.updatedAt] = horse.updatedAt
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,11 +1,11 @@
|
||||
package at.mocode.horses.infrastructure.persistence
|
||||
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import org.jetbrains.exposed.v1.core.dao.id.java.UUIDTable
|
||||
import org.jetbrains.exposed.v1.core.kotlin.datetime.date
|
||||
import org.jetbrains.exposed.v1.core.kotlin.datetime.timestamp
|
||||
import org.jetbrains.exposed.v1.core.javaUUID
|
||||
import org.jetbrains.exposed.v1.core.java.javaUUID
|
||||
import org.jetbrains.exposed.v1.datetime.date
|
||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
|
||||
/**
|
||||
* Database table definition for horses in the horse-registry context.
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.exposed.v1.core.javaUUID
|
||||
* This table stores all horse information including identification,
|
||||
* ownership, breeding data, and administrative information.
|
||||
*/
|
||||
object HorseTable : UUIDTable("horses") {
|
||||
object HorseTable : UUIDTable("zns_horses") {
|
||||
// Basic Information
|
||||
val pferdeName = varchar("pferde_name", 255)
|
||||
val geschlecht = enumerationByName<PferdeGeschlechtE>("geschlecht", 20)
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
plugins {
|
||||
// KORREKTUR: Alle Plugins werden jetzt konsistent über den Version Catalog geladen.
|
||||
alias(libs.plugins.kotlin.jvm)
|
||||
alias(libs.plugins.kotlin.spring)
|
||||
alias(libs.plugins.kotlinJvm)
|
||||
alias(libs.plugins.kotlinSpring)
|
||||
alias(libs.plugins.spring.boot)
|
||||
alias(libs.plugins.spring.dependencyManagement)
|
||||
}
|
||||
|
||||
// Der springBoot-Block konfiguriert die Anwendung, wenn sie als JAR-Datei ausgeführt wird.
|
||||
springBoot {
|
||||
mainClass.set("at.mocode.horses.service.HorsesServiceApplicationKt")
|
||||
}
|
||||
@@ -17,16 +15,9 @@ dependencies {
|
||||
implementation(projects.core.coreDomain)
|
||||
implementation(projects.core.coreUtils)
|
||||
implementation(projects.horses.horsesDomain)
|
||||
implementation(projects.horses.horsesApplication)
|
||||
// horses-common: ON HOLD – veraltete API-Referenzen
|
||||
// implementation(projects.horses.horsesCommon)
|
||||
implementation(projects.horses.horsesInfrastructure)
|
||||
implementation(projects.horses.horsesApi)
|
||||
|
||||
// Infrastruktur-Clients
|
||||
implementation(projects.infrastructure.cache.redisCache)
|
||||
implementation(projects.infrastructure.messaging.messagingClient)
|
||||
implementation(projects.infrastructure.monitoring.monitoringClient)
|
||||
|
||||
// KORREKTUR: Alle externen Abhängigkeiten werden jetzt über den Version Catalog bezogen.
|
||||
|
||||
// Spring Boot Starters
|
||||
implementation(libs.spring.boot.starter.web)
|
||||
@@ -42,11 +33,10 @@ dependencies {
|
||||
runtimeOnly(libs.postgresql.driver)
|
||||
testRuntimeOnly(libs.h2.driver)
|
||||
|
||||
|
||||
// Testing
|
||||
testImplementation(projects.platform.platformTesting)
|
||||
testImplementation(libs.spring.boot.starter.test)
|
||||
testImplementation(libs.logback.classic) // SLF4J provider for tests
|
||||
testImplementation(libs.logback.classic)
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
|
||||
-60
@@ -1,60 +0,0 @@
|
||||
package at.mocode.horses.service.config
|
||||
|
||||
import at.mocode.horses.application.usecase.CreateHorseUseCase
|
||||
import at.mocode.horses.application.usecase.TransactionalCreateHorseUseCase
|
||||
import at.mocode.horses.application.usecase.UpdateHorseUseCase
|
||||
import at.mocode.horses.application.usecase.DeleteHorseUseCase
|
||||
import at.mocode.horses.application.usecase.GetHorseUseCase
|
||||
import at.mocode.horses.domain.repository.HorseRepository
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
* Application configuration for the Horses Service.
|
||||
*
|
||||
* This configuration wires the use cases as Spring beans.
|
||||
*/
|
||||
@Configuration
|
||||
class ApplicationConfiguration {
|
||||
|
||||
/**
|
||||
* Creates the CreateHorseUseCase as a Spring bean.
|
||||
*/
|
||||
@Bean
|
||||
fun createHorseUseCase(horseRepository: HorseRepository): CreateHorseUseCase {
|
||||
return CreateHorseUseCase(horseRepository)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the TransactionalCreateHorseUseCase as a Spring bean.
|
||||
* This version ensures all database operations run within a single transaction.
|
||||
*/
|
||||
@Bean
|
||||
fun transactionalCreateHorseUseCase(horseRepository: HorseRepository): TransactionalCreateHorseUseCase {
|
||||
return TransactionalCreateHorseUseCase(horseRepository)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the UpdateHorseUseCase as a Spring bean.
|
||||
*/
|
||||
@Bean
|
||||
fun updateHorseUseCase(horseRepository: HorseRepository): UpdateHorseUseCase {
|
||||
return UpdateHorseUseCase(horseRepository)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the DeleteHorseUseCase as a Spring bean.
|
||||
*/
|
||||
@Bean
|
||||
fun deleteHorseUseCase(horseRepository: HorseRepository): DeleteHorseUseCase {
|
||||
return DeleteHorseUseCase(horseRepository)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the GetHorseUseCase as a Spring bean.
|
||||
*/
|
||||
@Bean
|
||||
fun getHorseUseCase(horseRepository: HorseRepository): GetHorseUseCase {
|
||||
return GetHorseUseCase(horseRepository)
|
||||
}
|
||||
}
|
||||
+21
-90
@@ -1,106 +1,37 @@
|
||||
package at.mocode.horses.service.config
|
||||
|
||||
import at.mocode.core.utils.database.DatabaseConfig
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.horses.infrastructure.persistence.HorseTable
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties
|
||||
import at.mocode.horses.infrastructure.persistence.ZnsClubTable
|
||||
import at.mocode.horses.infrastructure.persistence.ZnsPersonTable
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.jetbrains.exposed.v1.jdbc.Database
|
||||
import org.jetbrains.exposed.v1.jdbc.SchemaUtils
|
||||
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Profile
|
||||
import org.springframework.stereotype.Component
|
||||
import jakarta.annotation.PostConstruct
|
||||
import jakarta.annotation.PreDestroy
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.jetbrains.exposed.sql.SchemaUtils
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
/**
|
||||
* Database configuration for the Horses Service.
|
||||
*
|
||||
* This configuration ensures that Database.connect() is called properly
|
||||
* before any Exposed operations are performed.
|
||||
* Minimale Datenbank-Konfiguration für den Horses-Service (Dev-Profil).
|
||||
* Verbindet sich direkt via JDBC und legt die Tabellen an.
|
||||
*/
|
||||
@Configuration
|
||||
@Profile("!test")
|
||||
class HorsesDatabaseConfiguration {
|
||||
|
||||
@Profile("dev")
|
||||
class HorsesDatabaseConfiguration(
|
||||
@Value("\${spring.datasource.url}") private val jdbcUrl: String,
|
||||
@Value("\${spring.datasource.username}") private val username: String,
|
||||
@Value("\${spring.datasource.password}") private val password: String
|
||||
) {
|
||||
private val log = LoggerFactory.getLogger(HorsesDatabaseConfiguration::class.java)
|
||||
|
||||
@PostConstruct
|
||||
fun initializeDatabase() {
|
||||
log.info("Initializing database schema for Horses Service...")
|
||||
|
||||
try {
|
||||
// Database connection is already initialized by the gateway
|
||||
// Only initialize the schema for this service
|
||||
transaction {
|
||||
SchemaUtils.createMissingTablesAndColumns(HorseTable)
|
||||
log.info("Horse database schema initialized successfully")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Failed to initialize database schema", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
fun closeDatabase() {
|
||||
log.info("Closing database connection for Horses Service...")
|
||||
try {
|
||||
DatabaseFactory.close()
|
||||
log.info("Database connection closed successfully")
|
||||
} catch (e: Exception) {
|
||||
log.error("Error closing database connection", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test-specific database configuration.
|
||||
*/
|
||||
@Configuration
|
||||
@Profile("test")
|
||||
class HorsesTestDatabaseConfiguration {
|
||||
|
||||
private val log = LoggerFactory.getLogger(HorsesTestDatabaseConfiguration::class.java)
|
||||
|
||||
@PostConstruct
|
||||
fun initializeTestDatabase() {
|
||||
log.info("Initializing test database connection for Horses Service...")
|
||||
|
||||
try {
|
||||
// Use H2 in-memory database for tests
|
||||
val testConfig = DatabaseConfig(
|
||||
jdbcUrl = "jdbc:h2:mem:horses_test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE",
|
||||
username = "sa",
|
||||
password = "",
|
||||
driverClassName = "org.h2.Driver",
|
||||
maxPoolSize = 5,
|
||||
minPoolSize = 1,
|
||||
autoMigrate = true
|
||||
)
|
||||
|
||||
DatabaseFactory.init(testConfig)
|
||||
log.info("Test database connection initialized successfully")
|
||||
|
||||
// Initialize database schema for tests
|
||||
transaction {
|
||||
SchemaUtils.createMissingTablesAndColumns(HorseTable)
|
||||
log.info("Test horse database schema initialized successfully")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
log.error("Failed to initialize test database connection", e)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
fun closeTestDatabase() {
|
||||
log.info("Closing test database connection for Horses Service...")
|
||||
try {
|
||||
DatabaseFactory.close()
|
||||
log.info("Test database connection closed successfully")
|
||||
} catch (e: Exception) {
|
||||
log.error("Error closing test database connection", e)
|
||||
log.info("Initialisiere Datenbank-Schema für Horses-Service...")
|
||||
Database.connect(jdbcUrl, user = username, password = password)
|
||||
transaction {
|
||||
SchemaUtils.createMissingTablesAndColumns(HorseTable, ZnsPersonTable, ZnsClubTable)
|
||||
log.info("Datenbank-Schema erfolgreich initialisiert")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user