feat: propper db persistence w/ docker support
This commit is contained in:
parent
2c4995f9d7
commit
4c3d939d9a
9 changed files with 276 additions and 160 deletions
|
|
@ -1,4 +1,6 @@
|
||||||
|
PORT=9000
|
||||||
|
HOST=localhost
|
||||||
|
|
||||||
DB_URL=jdbc:postgresql://localhost:5432/homepage
|
DB_URL=jdbc:postgresql://localhost:5432/homepage
|
||||||
DB_MIGRATION=src/main/resources/db/migration
|
|
||||||
DB_USERNAME=postgres
|
DB_USERNAME=postgres
|
||||||
DB_PASSWORD=postgres
|
DB_PASSWORD=postgres
|
||||||
13
Dockerfile
13
Dockerfile
|
|
@ -1,6 +1,13 @@
|
||||||
# --- Stage 1: Build the JAR ---
|
# --- Stage 1: Build the JAR ---
|
||||||
FROM gradle:9.2.1-jdk21 AS build
|
FROM gradle:9.2.1-jdk21 AS build
|
||||||
|
|
||||||
|
ARG DB_URL
|
||||||
|
ARG DB_USERNAME
|
||||||
|
ARG DB_PASSWORD
|
||||||
|
ENV DB_URL=${DB_URL}
|
||||||
|
ENV DB_USERNAME=${DB_USERNAME}
|
||||||
|
ENV DB_PASSWORD=${DB_PASSWORD}
|
||||||
|
|
||||||
# Set working dir
|
# Set working dir
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|
@ -12,18 +19,20 @@ COPY --chown=gradle:gradle gradle ./gradle
|
||||||
COPY --chown=gradle:gradle src ./src
|
COPY --chown=gradle:gradle src ./src
|
||||||
|
|
||||||
# Build the fat jar
|
# Build the fat jar
|
||||||
RUN ./gradlew clean shadowJar --no-daemon
|
RUN ./gradlew clean build --no-daemon
|
||||||
|
|
||||||
# --- Stage 2: Run the app ---
|
# --- Stage 2: Run the app ---
|
||||||
FROM eclipse-temurin:21-jdk-alpine
|
FROM eclipse-temurin:21-jdk-alpine
|
||||||
|
|
||||||
|
ARG PORT=9000
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# Copy the built JAR from the build stage
|
# Copy the built JAR from the build stage
|
||||||
COPY --from=build /app/build/libs/*.jar app.jar
|
COPY --from=build /app/build/libs/*.jar app.jar
|
||||||
|
|
||||||
# Expose port (same as your server)
|
# Expose port (same as your server)
|
||||||
EXPOSE 9000
|
EXPOSE ${PORT}
|
||||||
|
|
||||||
# Run the app
|
# Run the app
|
||||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||||
|
|
|
||||||
308
build.gradle.kts
308
build.gradle.kts
|
|
@ -1,159 +1,147 @@
|
||||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||||
|
import io.github.klahap.dotenv.DotEnv
|
||||||
import io.github.klahap.dotenv.DotEnvBuilder
|
import io.github.klahap.dotenv.DotEnvBuilder
|
||||||
import org.flywaydb.gradle.task.FlywayMigrateTask
|
|
||||||
import org. gradle.api.JavaVersion.VERSION_21
|
import org. gradle.api.JavaVersion.VERSION_21
|
||||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21
|
import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||||
import kotlin.io.path.Path
|
import kotlin.io.path.Path
|
||||||
|
|
||||||
val env = DotEnvBuilder.dotEnv {
|
// ====================================================================================================
|
||||||
addFile("$rootDir/.env")
|
// ENVIRONMENT CONFIGURATION
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
val env = if (File("${layout.projectDirectory.asFile.absolutePath}/.env").exists()) {
|
||||||
|
DotEnvBuilder.dotEnv {
|
||||||
|
addFile("${layout.projectDirectory}/.env")
|
||||||
addSystemEnv()
|
addSystemEnv()
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
DotEnvBuilder.dotEnv {
|
||||||
|
addSystemEnv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val envDbUrl: String = env["DB_URL"] ?: ""
|
val envDbUrl: String = env["DB_URL"] ?: ""
|
||||||
val envDbMigration: String = env["DB_MIGRATIONS"] ?: "src/main/resources/db/migration"
|
|
||||||
val envDbUsername: String = env["DB_USERNAME"] ?: ""
|
val envDbUsername: String = env["DB_USERNAME"] ?: ""
|
||||||
val envDbPassword: String = env["DB_PASSWORD"] ?: ""
|
val envDbPassword: String = env["DB_PASSWORD"] ?: ""
|
||||||
|
|
||||||
val generatedResourcesDirectory = "${layout.buildDirectory.get()}/generated-resources"
|
// ====================================================================================================
|
||||||
val generatedSourcesDirectory = "${layout.buildDirectory.get()}/generated-src"
|
// PLUGIN CONFIGURATION
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.kotlin.jvm)
|
alias(libs.plugins.kotlin.jvm)
|
||||||
alias(libs.plugins.shadow)
|
alias(libs.plugins.shadow)
|
||||||
alias(libs.plugins.dotenv.plugin)
|
alias(libs.plugins.dotenv.plugin)
|
||||||
alias(libs.plugins.jte)
|
alias(libs.plugins.jte)
|
||||||
alias(libs.plugins.flyway)
|
alias(libs.plugins.tasktree)
|
||||||
alias(libs.plugins.jooq.codegen.gradle)
|
alias(libs.plugins.jooq.codegen.gradle)
|
||||||
alias(libs.plugins.taskinfo)
|
alias(libs.plugins.flyway)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// BASIC CONFIGURATION
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvmToolchain {
|
jvmToolchain {
|
||||||
languageVersion.set(JavaLanguageVersion.of(21))
|
languageVersion.set(JavaLanguageVersion.of(21))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = VERSION_21
|
||||||
|
targetCompatibility = VERSION_21
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// GENERATED CODE DIRECTORIES
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
val generatedResourcesDir = layout.buildDirectory.dir("generated-resources")
|
||||||
|
val generatedSourcesDir = layout.buildDirectory.dir("generated-src")
|
||||||
|
val migrationSourceDir = layout.projectDirectory.dir("src/main/resources/db/migration")
|
||||||
|
val jtwSourceDir = layout.projectDirectory.dir("src/main/kte")
|
||||||
|
val jteOutputDir = generatedResourcesDir.get().dir("jte")
|
||||||
|
val jooqOutputDir = generatedSourcesDir.get().dir("jooq")
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
resources.srcDir(jteOutputDir)
|
||||||
|
kotlin.srcDir(jooqOutputDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// DEPENDENCIES
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// HTTP4K
|
||||||
|
implementation(platform(libs.http4k.bom))
|
||||||
|
implementation(libs.bundles.http4k)
|
||||||
|
|
||||||
|
// Environment & Configuration
|
||||||
|
implementation(libs.dotenv)
|
||||||
|
|
||||||
|
// Templating
|
||||||
|
implementation(libs.jte.kotlin)
|
||||||
|
|
||||||
|
// Database
|
||||||
|
implementation(libs.bundles.database)
|
||||||
|
implementation(libs.flyway.core)
|
||||||
|
implementation(libs.flyway.database.postgresql)
|
||||||
|
|
||||||
|
// Testing
|
||||||
|
testImplementation(libs.bundles.testing)
|
||||||
|
|
||||||
|
// Jooq Codegen
|
||||||
|
jooqCodegen(libs.jooq.meta)
|
||||||
|
jooqCodegen(libs.jooq.meta.extensions)
|
||||||
|
jooqCodegen(libs.jooq.postgres)
|
||||||
|
}
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath(libs.postgresql)
|
classpath(libs.jooq.codegen)
|
||||||
|
classpath(libs.jooq.meta)
|
||||||
|
classpath(libs.jooq.meta.extensions)
|
||||||
classpath(libs.flyway.database.postgresql)
|
classpath(libs.flyway.database.postgresql)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets.main {
|
// ====================================================================================================
|
||||||
resources.srcDir("$generatedResourcesDirectory/jte")
|
// JTE TEMPLATE GENERATION
|
||||||
kotlin.srcDir("$generatedSourcesDirectory/jooq")
|
// ====================================================================================================
|
||||||
}
|
|
||||||
|
|
||||||
tasks {
|
|
||||||
withType<KotlinJvmCompile>().configureEach {
|
|
||||||
dependsOn("jooqCodegen")
|
|
||||||
|
|
||||||
compilerOptions {
|
|
||||||
allWarningsAsErrors = false
|
|
||||||
jvmTarget.set(JVM_21)
|
|
||||||
freeCompilerArgs.add("-Xjvm-default=all")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
withType<Test> {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
|
|
||||||
withType<FlywayMigrateTask> {
|
|
||||||
dependsOn("initDb")
|
|
||||||
}
|
|
||||||
|
|
||||||
named("precompileJte") {
|
|
||||||
dependsOn("compileKotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
named<ShadowJar>("shadowJar") {
|
|
||||||
manifest {
|
|
||||||
attributes("Main-Class" to "at.dokkae.homepage.HomepageKt")
|
|
||||||
}
|
|
||||||
|
|
||||||
dependsOn("precompileJte")
|
|
||||||
|
|
||||||
mustRunAfter("flywayMigrate", "jooqCodegen")
|
|
||||||
|
|
||||||
from("$generatedResourcesDirectory/jte")
|
|
||||||
|
|
||||||
archiveFileName.set("app.jar")
|
|
||||||
|
|
||||||
exclude("META-INF/*.RSA", "META-INF/*.SF", "META-INF/*.DSA")
|
|
||||||
}
|
|
||||||
|
|
||||||
register("buildDocker") {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = VERSION_21
|
|
||||||
targetCompatibility = VERSION_21
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(platform(libs.http4k.bom))
|
|
||||||
|
|
||||||
implementation(libs.dotenv)
|
|
||||||
|
|
||||||
implementation(libs.bundles.http4k)
|
|
||||||
implementation(libs.jte.kotlin)
|
|
||||||
implementation(libs.bundles.database)
|
|
||||||
|
|
||||||
testImplementation(libs.bundles.testing)
|
|
||||||
|
|
||||||
jooqCodegen(libs.jooq.meta)
|
|
||||||
jooqCodegen(libs.jooq.postgres)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========== JTE Templating ==========
|
|
||||||
jte {
|
jte {
|
||||||
sourceDirectory.set(Path("src/main/kte"))
|
sourceDirectory.set(Path(jtwSourceDir.asFile.absolutePath))
|
||||||
targetDirectory.set(Path("$generatedResourcesDirectory/jte"))
|
targetDirectory.set(Path(jteOutputDir.asFile.absolutePath))
|
||||||
precompile()
|
precompile()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== FlyWay ==========
|
tasks.named("precompileJte") {
|
||||||
flyway {
|
dependsOn("compileKotlin")
|
||||||
url = envDbUrl
|
|
||||||
user = envDbUsername
|
|
||||||
password = envDbPassword
|
|
||||||
locations = arrayOf("filesystem:$envDbMigration")
|
|
||||||
baselineOnMigrate = true
|
|
||||||
validateMigrationNaming = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register("initDb") {
|
tasks.register("genJte") {
|
||||||
doFirst {
|
group = "codegen"
|
||||||
println("Database Configuration:")
|
description = "Precompile jte template into classes"
|
||||||
println(" Raw URL from env: $envDbUrl")
|
|
||||||
println(" Resolved URL: $envDbUrl")
|
dependsOn("precompileJte")
|
||||||
println(" Migrations: $envDbMigration")
|
|
||||||
println(" Credentials:")
|
|
||||||
println(" Username: $envDbUsername")
|
|
||||||
println(" Password: ${"*".repeat(envDbPassword.length)}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.named("flywayMigrate") {
|
// ====================================================================================================
|
||||||
finalizedBy("jooqCodegen")
|
// JOOQ CODE GENERATION FROM SQL FILES
|
||||||
}
|
// ====================================================================================================
|
||||||
|
|
||||||
// ========== Jooq ==========
|
|
||||||
jooq {
|
jooq {
|
||||||
configuration {
|
configuration {
|
||||||
logging = org.jooq.meta.jaxb.Logging.WARN
|
logging = org.jooq.meta.jaxb.Logging.WARN
|
||||||
|
|
@ -172,7 +160,6 @@ jooq {
|
||||||
name = "org.jooq.meta.postgres.PostgresDatabase"
|
name = "org.jooq.meta.postgres.PostgresDatabase"
|
||||||
inputSchema = "public"
|
inputSchema = "public"
|
||||||
|
|
||||||
// SQLite specific configuration
|
|
||||||
includes = ".*"
|
includes = ".*"
|
||||||
excludes = """
|
excludes = """
|
||||||
flyway_.*|
|
flyway_.*|
|
||||||
|
|
@ -195,7 +182,7 @@ jooq {
|
||||||
|
|
||||||
target {
|
target {
|
||||||
packageName = "at.dokkae.homepage.generated.jooq"
|
packageName = "at.dokkae.homepage.generated.jooq"
|
||||||
directory = "$generatedSourcesDirectory/jooq"
|
directory = jooqOutputDir.asFile.absolutePath
|
||||||
}
|
}
|
||||||
|
|
||||||
strategy {
|
strategy {
|
||||||
|
|
@ -204,3 +191,112 @@ jooq {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register("genJooq") {
|
||||||
|
group = "codegen"
|
||||||
|
description = "Generate jooq classes from migrations"
|
||||||
|
|
||||||
|
dependsOn("jooqCodegen")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// FLYWAY MIGRATE AND CODEGEN TASK
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
flyway {
|
||||||
|
url = envDbUrl
|
||||||
|
user = envDbUsername
|
||||||
|
password = envDbPassword
|
||||||
|
locations = arrayOf("filesystem:${migrationSourceDir.asFile.absolutePath}")
|
||||||
|
baselineOnMigrate = true
|
||||||
|
validateMigrationNaming = true
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.register("migrate") {
|
||||||
|
group = "codegen"
|
||||||
|
description = "Run Flyway migrations and generate JOOQ code (no compilation)"
|
||||||
|
|
||||||
|
dependsOn("flywayMigrate")
|
||||||
|
finalizedBy("jooqCodegen")
|
||||||
|
|
||||||
|
doFirst {
|
||||||
|
logger.lifecycle("╔═══════════════════════════════════════════════════════════════╗")
|
||||||
|
logger.lifecycle("║ Running Migrations and Code Generation ║")
|
||||||
|
logger.lifecycle("╚═══════════════════════════════════════════════════════════════╝")
|
||||||
|
logger.lifecycle("| Database URL: $envDbUrl")
|
||||||
|
logger.lifecycle("| Migrations: ${migrationSourceDir.asFile.absolutePath}")
|
||||||
|
logger.lifecycle("| Username: $envDbUsername")
|
||||||
|
logger.lifecycle("| Password: ${if (envDbUsername.isEmpty()) "not " else ""}provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
logger.lifecycle("✓ Migration and code generation completed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// COMPILATION ORDER
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
withType<KotlinJvmCompile>().configureEach {
|
||||||
|
dependsOn("genJooq")
|
||||||
|
|
||||||
|
compilerOptions {
|
||||||
|
allWarningsAsErrors = false
|
||||||
|
jvmTarget.set(JVM_21)
|
||||||
|
freeCompilerArgs.add("-Xjvm-default=all")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
withType<Test> {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// JAR BUILDING
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
tasks.named<ShadowJar>("shadowJar") {
|
||||||
|
manifest {
|
||||||
|
attributes("Main-Class" to "at.dokkae.homepage.HomepageKt")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependsOn("genJte", "genJooq")
|
||||||
|
|
||||||
|
from(jteOutputDir)
|
||||||
|
|
||||||
|
archiveFileName.set("app.jar")
|
||||||
|
|
||||||
|
mergeServiceFiles()
|
||||||
|
|
||||||
|
exclude(
|
||||||
|
"META-INF/*. RSA",
|
||||||
|
"META-INF/*.SF",
|
||||||
|
"META-INF/*.DSA"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("build") {
|
||||||
|
dependsOn("shadowJar")
|
||||||
|
}
|
||||||
|
|
||||||
|
// ====================================================================================================
|
||||||
|
// HELPER TASKS
|
||||||
|
// ====================================================================================================
|
||||||
|
|
||||||
|
tasks.register("cleanGenerated") {
|
||||||
|
group = "build"
|
||||||
|
description = "Clean all generated code"
|
||||||
|
|
||||||
|
doLast {
|
||||||
|
delete(generatedResourcesDir)
|
||||||
|
delete(generatedSourcesDir)
|
||||||
|
logger.lifecycle("✓ Cleaned generated code directories")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.named("clean") {
|
||||||
|
dependsOn("cleanGenerated")
|
||||||
|
}
|
||||||
13
docker/entrypoint.sh
Executable file
13
docker/entrypoint.sh
Executable file
|
|
@ -0,0 +1,13 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 Setting up deployment environment"
|
||||||
|
|
||||||
|
wait_for_db() {
|
||||||
|
echo "⏳ Waiting for database at $DB_HOST:$DB_PORT..."
|
||||||
|
while ! nc -z $DB_HOST $DB_PORT; do
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
echo "✅ Database is ready!"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -9,16 +9,16 @@ flyway = "11.19.0"
|
||||||
jooq = "3.20.10"
|
jooq = "3.20.10"
|
||||||
junit = "6.0.0"
|
junit = "6.0.0"
|
||||||
postgresql = "42.7.7"
|
postgresql = "42.7.7"
|
||||||
taskinfo = "3.0.0"
|
tasktree = "4.0.1"
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||||
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
shadow = { id = "com.gradleup.shadow", version.ref = "shadow" }
|
||||||
dotenv-plugin = { id = "io.github.klahap.dotenv", version.ref = "dotenv-plugin" }
|
dotenv-plugin = { id = "io.github.klahap.dotenv", version.ref = "dotenv-plugin" }
|
||||||
jte = { id = "gg.jte.gradle", version.ref = "jte" }
|
jte = { id = "gg.jte.gradle", version.ref = "jte" }
|
||||||
flyway = { id = "org.flywaydb.flyway", version.ref = "flyway" }
|
|
||||||
jooq-codegen-gradle = { id = "org.jooq.jooq-codegen-gradle", version.ref = "jooq" }
|
jooq-codegen-gradle = { id = "org.jooq.jooq-codegen-gradle", version.ref = "jooq" }
|
||||||
taskinfo = { id = "org.barfuin.gradle.taskinfo", version.ref = "taskinfo" }
|
tasktree = { id = "com.dorongold.task-tree", version.ref = "tasktree" }
|
||||||
|
flyway = { id = "org.flywaydb.flyway", version.ref = "flyway" }
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
http4k = [
|
http4k = [
|
||||||
|
|
@ -38,11 +38,9 @@ testing = [
|
||||||
]
|
]
|
||||||
|
|
||||||
database = [
|
database = [
|
||||||
|
"postgresql",
|
||||||
"flyway-core",
|
"flyway-core",
|
||||||
"jooq",
|
"jooq"
|
||||||
"jooq-meta",
|
|
||||||
"jooq-codegen",
|
|
||||||
"jooq-postgres"
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
|
@ -72,6 +70,7 @@ flyway-database-postgresql = { module = "org.flywaydb:flyway-database-postgresql
|
||||||
# Jooq
|
# Jooq
|
||||||
jooq = { module = "org.jooq:jooq", version.ref = "jooq" }
|
jooq = { module = "org.jooq:jooq", version.ref = "jooq" }
|
||||||
jooq-meta = { module = "org.jooq:jooq-meta", version.ref = "jooq" }
|
jooq-meta = { module = "org.jooq:jooq-meta", version.ref = "jooq" }
|
||||||
|
jooq-meta-extensions = { module = "org.jooq:jooq-meta-extensions", version.ref = "jooq" }
|
||||||
jooq-codegen = { module = "org.jooq:jooq-codegen", version.ref = "jooq" }
|
jooq-codegen = { module = "org.jooq:jooq-codegen", version.ref = "jooq" }
|
||||||
jooq-postgres = { module = "org.jooq:jooq-postgres-extensions", version.ref = "jooq" }
|
jooq-postgres = { module = "org.jooq:jooq-postgres-extensions", version.ref = "jooq" }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package at.dokkae.homepage
|
package at.dokkae.homepage
|
||||||
|
|
||||||
|
import at.dokkae.homepage.config.Environment
|
||||||
import at.dokkae.homepage.extensions.Precompiled
|
import at.dokkae.homepage.extensions.Precompiled
|
||||||
import at.dokkae.homepage.repository.MessageRepository
|
import at.dokkae.homepage.repository.MessageRepository
|
||||||
import at.dokkae.homepage.repository.impls.JooqMessageRepository
|
import at.dokkae.homepage.repository.impls.JooqMessageRepository
|
||||||
|
|
@ -24,7 +25,6 @@ import org.http4k.sse.SseMessage
|
||||||
import org.http4k.sse.SseResponse
|
import org.http4k.sse.SseResponse
|
||||||
import org.http4k.template.JTETemplates
|
import org.http4k.template.JTETemplates
|
||||||
import org.http4k.template.ViewModel
|
import org.http4k.template.ViewModel
|
||||||
import org.jetbrains.kotlin.backend.common.push
|
|
||||||
import org.jooq.SQLDialect
|
import org.jooq.SQLDialect
|
||||||
import org.jooq.impl.DSL
|
import org.jooq.impl.DSL
|
||||||
import java.sql.DriverManager
|
import java.sql.DriverManager
|
||||||
|
|
@ -51,9 +51,12 @@ data class Message(
|
||||||
}
|
}
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
val env = dotenv()
|
val env = Environment.load(dotenv {
|
||||||
|
ignoreIfMissing = true
|
||||||
|
ignoreIfMalformed = true
|
||||||
|
})
|
||||||
|
|
||||||
val connection = DriverManager.getConnection(env["DB_URL"], env["DB_USERNAME"], env["DB_PASSWORD"])
|
val connection = DriverManager.getConnection(env.dbUrl, env.dbUsername, env.dbPassword)
|
||||||
val dslContext = DSL.using(connection, SQLDialect.POSTGRES)
|
val dslContext = DSL.using(connection, SQLDialect.POSTGRES)
|
||||||
val messageRepository: MessageRepository = JooqMessageRepository(dslContext)
|
val messageRepository: MessageRepository = JooqMessageRepository(dslContext)
|
||||||
|
|
||||||
|
|
@ -98,7 +101,7 @@ fun main() {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
poly(http, sse).asServer(Jetty(port = 9000)).start()
|
poly(http, sse).asServer(Jetty(port = env.port)).start()
|
||||||
|
|
||||||
println("Server started on http://localhost:9000")
|
println("Server started on http://${env.host}:${env.port}")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
src/main/kotlin/at/dokkae/homepage/config/Environment.kt
Normal file
31
src/main/kotlin/at/dokkae/homepage/config/Environment.kt
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package at.dokkae.homepage.config
|
||||||
|
|
||||||
|
import io.github.cdimascio.dotenv.Dotenv
|
||||||
|
|
||||||
|
data class Environment(
|
||||||
|
val port: Int,
|
||||||
|
val host: String,
|
||||||
|
val dbUrl: String,
|
||||||
|
val dbUsername: String,
|
||||||
|
val dbPassword: String,
|
||||||
|
) {
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Returns a loaded Environment object instance.
|
||||||
|
* @throws IllegalStateException if required environment variables were not found within the provided `dotenv` instance.
|
||||||
|
*/
|
||||||
|
fun load(dotenv: Dotenv): Environment = Environment(
|
||||||
|
port = requireEnv(dotenv, "PORT").toInt(),
|
||||||
|
host = requireEnv(dotenv, "HOST"),
|
||||||
|
dbUrl = requireEnv(dotenv, "DB_URL"),
|
||||||
|
dbUsername = requireEnv(dotenv, "DB_USERNAME"),
|
||||||
|
dbPassword = requireEnv(dotenv, "DB_PASSWORD"),
|
||||||
|
)
|
||||||
|
|
||||||
|
private fun requireEnv(dotenv: Dotenv, key: String): String {
|
||||||
|
return dotenv[key] ?: throw IllegalStateException(
|
||||||
|
"Missing required environment variable: $key"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package at.dokkae.homepage
|
|
||||||
|
|
||||||
import org.http4k.client.OkHttp
|
|
||||||
import org.http4k.core.HttpHandler
|
|
||||||
import org.http4k.core.Method.GET
|
|
||||||
import org.http4k.core.Request
|
|
||||||
import org.http4k.core.Response
|
|
||||||
import org.http4k.core.then
|
|
||||||
import org.http4k.filter.DebuggingFilters.PrintResponse
|
|
||||||
|
|
||||||
fun main() {
|
|
||||||
val client: HttpHandler = OkHttp()
|
|
||||||
|
|
||||||
val printingClient: HttpHandler = PrintResponse().then(client)
|
|
||||||
|
|
||||||
val response: Response = printingClient(Request(GET, "http://localhost:9000/ping"))
|
|
||||||
|
|
||||||
println(response.bodyString())
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package at.dokkae.homepage
|
|
||||||
|
|
||||||
import org.http4k.core.Method.GET
|
|
||||||
import org.http4k.core.Request
|
|
||||||
import org.http4k.core.Response
|
|
||||||
import org.http4k.core.Status.Companion.OK
|
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
|
|
||||||
class HomepageTest {
|
|
||||||
@Test
|
|
||||||
fun `Ping test`() {
|
|
||||||
assertEquals(
|
|
||||||
Response(OK).body("pong"),
|
|
||||||
app(Request(GET, "/ping"))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue