Skip to content

Commit

Permalink
Added jooq and docker support
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Martishin authored and Alex Martishin committed Jul 11, 2023
1 parent 69eca78 commit 729f207
Show file tree
Hide file tree
Showing 24 changed files with 289 additions and 63 deletions.
10 changes: 10 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Stage 1: Build
FROM gradle:7.6.0-jdk17 AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle build -x test --no-daemon

# Stage 2: Run
FROM openjdk:17-jdk
COPY --from=build /home/gradle/src/build/libs/server.jar /app/server.jar
ENTRYPOINT ["java","-jar","/app/server.jar"]
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.PHONY: build run

build:
docker build --tag spring-coroutines:mac .

run:
docker run -p 8080:8080 spring-coroutines:mac
112 changes: 87 additions & 25 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,44 +1,106 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jooq.meta.jaxb.Property

plugins {
id("org.springframework.boot") version "3.1.0"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.8.21"
kotlin("plugin.spring") version "1.8.21"
id("org.springframework.boot") version "3.1.0"
id("io.spring.dependency-management") version "1.1.0"
kotlin("jvm") version "1.8.21"
kotlin("plugin.spring") version "1.8.21"
id("nu.studer.jooq") version "8.2.1"
}

group = "com.ttymonkey"
version = "0.0.1-SNAPSHOT"

java {
sourceCompatibility = JavaVersion.VERSION_17
}
java.sourceCompatibility = JavaVersion.VERSION_17

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
implementation("org.flywaydb:flyway-core:8.5.11")
runtimeOnly("org.postgresql:postgresql")
runtimeOnly("org.postgresql:r2dbc-postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
// webflux
implementation("org.springframework.boot:spring-boot-starter-webflux")

// kotlin and coroutines support
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("io.projectreactor.kotlin:reactor-kotlin-extensions")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")

// r2dbc and postgresql
implementation("org.springframework.boot:spring-boot-starter-data-r2dbc")
runtimeOnly("org.postgresql:postgresql")
runtimeOnly("org.postgresql:r2dbc-postgresql")

// flyway
implementation("org.flywaydb:flyway-core:8.5.11")

// jooq
implementation("org.springframework.boot:spring-boot-starter-jooq")
implementation("org.jooq:jooq-kotlin")
jooqGenerator("org.jooq:jooq-meta-extensions")

// test dependencies
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("io.projectreactor:reactor-test")
}

tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
kotlinOptions {
freeCompilerArgs += "-Xjsr305=strict"
jvmTarget = "17"
}
}

tasks.withType<Test> {
useJUnitPlatform()
useJUnitPlatform()
}

jooq {
configurations {
create("main") {
jooqConfiguration.apply {
logging = org.jooq.meta.jaxb.Logging.WARN
jdbc = null

generator.apply {
database.apply {
name = "org.jooq.codegen.KotlinGenerator"
name = "org.jooq.meta.extensions.ddl.DDLDatabase"

properties.addAll(
listOf(
Property().apply {
key = "scripts"
value = "src/main/resources/db/migration"
},

Property().apply {
key = "sort"
value = "flyway"
},

Property().apply {
key = "defaultNameCase"
value = "lower"
},
),
)
}
generate.apply {
isPojosAsKotlinDataClasses = true // use data classes
isKotlinNotNullPojoAttributes = true
}
target.apply {
packageName = "com.ttymonkey.springcoroutines.jooq"
}
strategy.name = "org.jooq.codegen.DefaultGeneratorStrategy"
}
}
}
}
}

tasks.withType<org.springframework.boot.gradle.tasks.bundling.BootJar> {
archiveFileName.set("server.jar")
}
28 changes: 28 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
version: '3.1'

services:
app:
build:
context: .
dockerfile: Dockerfile
environment:
DB_HOST: db
DB_USERNAME: postgres
DB_PASSWORD: password
DB_DATABASE: monkey
ports:
- "8080:8080"
depends_on:
- db
db:
image: postgres:15.3-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: password
POSTGRES_DB: monkey
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:
9 changes: 9 additions & 0 deletions src/main/kotlin/com/ttymonkey/springcoroutines/Extensions.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.ttymonkey.springcoroutines

import com.ttymonkey.springcoroutines.dto.*
import com.ttymonkey.springcoroutines.jooq.application.tables.records.CompaniesRecord
import com.ttymonkey.springcoroutines.models.Company
import com.ttymonkey.springcoroutines.models.User

Expand Down Expand Up @@ -47,3 +48,11 @@ fun Company.toIdNameTypeResponse(): IdNameTypeResponse =
name = this.name,
type = ResultType.COMPANY,
)

fun CompaniesRecord.toCompany(): Company {
return Company(
this.get("id", Int::class.java),
this.get("name", String::class.java),
this.get("address", String::class.java),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import org.springframework.context.annotation.Configuration
import org.springframework.core.env.Environment

@Configuration
class FlywayConfiguration(private val env: Environment) {
class FlywayConfig(private val env: Environment) {

@Bean(initMethod = "migrate")
fun flyway(): Flyway {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.ttymonkey.springcoroutines.configs

import io.r2dbc.spi.ConnectionFactory
import org.jooq.DSLContext
import org.jooq.SQLDialect
import org.jooq.impl.DSL
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.r2dbc.connection.TransactionAwareConnectionFactoryProxy

@Configuration
class JooqConfig(private val connectionFactory: ConnectionFactory) {

@Bean
fun dslContext(): DSLContext {
return DSL.using(TransactionAwareConnectionFactoryProxy(connectionFactory), SQLDialect.POSTGRES)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.ttymonkey.springcoroutines.configs

import org.springframework.context.annotation.Configuration
import org.springframework.data.r2dbc.config.EnableR2dbcAuditing

@Configuration
@EnableR2dbcAuditing
class R2dbcConfig
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.toList
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.bind.annotation.*
import org.springframework.web.server.ResponseStatusException

Expand Down Expand Up @@ -49,7 +50,7 @@ class CompanyController(

@GetMapping("/{id}")
suspend fun findCompanyById(
@PathVariable id: Long,
@PathVariable id: Int,
): CompanyResponse =
companyService.findCompanyById(id)
?.let { company ->
Expand All @@ -61,14 +62,15 @@ class CompanyController(

@DeleteMapping("/{id}")
suspend fun deleteCompanyById(
@PathVariable id: Long,
) {
@PathVariable id: Int,
): ResponseEntity<Void> {
companyService.deleteCompanyById(id)
return ResponseEntity.noContent().build()
}

@PutMapping("/{id}")
suspend fun updateCompany(
@PathVariable id: Long,
@PathVariable id: Int,
@RequestBody companyRequest: CompanyRequest,
): CompanyResponse =
companyService.updateCompany(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,22 @@ class UserController(

@GetMapping("/{id}")
suspend fun findUserById(
@PathVariable id: Long,
@PathVariable id: Int,
): UserResponse =
userService.findUserById(id)
?.let(User::toResponse)
?: throw ResponseStatusException(HttpStatus.NOT_FOUND, "User with id $id was not found.")

@DeleteMapping("/{id}")
suspend fun deleteUserById(
@PathVariable id: Long,
@PathVariable id: Int,
) {
userService.deleteUserById(id)
}

@PutMapping("/{id}")
suspend fun updateUser(
@PathVariable id: Long,
@PathVariable id: Int,
@RequestBody userRequest: UserRequest,
): UserResponse =
userService.updateUser(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ttymonkey.springcoroutines.dto

data class CompanyResponse(
val id: Long,
val id: Int,
val name: String,
val address: String,
val users: List<UserResponse>,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ttymonkey.springcoroutines.dto

data class IdNameTypeResponse(
val id: Long,
val id: Int,
val name: String,
val type: ResultType,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ data class UserRequest(
val email: String,
val name: String,
val age: Int,
@JsonProperty("company_id") val companyId: Long,
@JsonProperty("company_id") val companyId: Int,
)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ttymonkey.springcoroutines.dto

data class UserResponse(
val id: Long,
val id: Int,
val email: String,
val name: String,
val age: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package com.ttymonkey.springcoroutines.models
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table

@Table("application.company")
@Table("application.companies")
data class Company(
@Id val id: Long? = null,
@Id val id: Int? = null,
val name: String,
val address: String,
)
6 changes: 3 additions & 3 deletions src/main/kotlin/com/ttymonkey/springcoroutines/models/User.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ package com.ttymonkey.springcoroutines.models
import org.springframework.data.annotation.Id
import org.springframework.data.relational.core.mapping.Table

@Table("application.user")
@Table("application.users")
data class User(
@Id val id: Long? = null,
@Id val id: Int? = null,
val email: String,
val name: String,
val age: Int,
val companyId: Long,
val companyId: Int,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package com.ttymonkey.springcoroutines.repositories

import com.ttymonkey.springcoroutines.models.Company
import kotlinx.coroutines.flow.Flow
import org.springframework.data.repository.kotlin.CoroutineCrudRepository

interface CompanyRepository : CoroutineCrudRepository<Company, Long> {
interface CompanyRepository {
fun findByNameContaining(name: String): Flow<Company>
fun findAll(): Flow<Company>
suspend fun findById(id: Int): Company?
suspend fun deleteById(id: Int): Int
suspend fun save(company: Company): Company?
}
Loading

0 comments on commit 729f207

Please sign in to comment.