Skip to content

Commit

Permalink
feat: initial commit #0
Browse files Browse the repository at this point in the history
  • Loading branch information
AdamHavlicek committed Jul 8, 2022
1 parent feaf406 commit 55c366d
Show file tree
Hide file tree
Showing 52 changed files with 1,531 additions and 169 deletions.
43 changes: 33 additions & 10 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,38 +1,61 @@
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "3.0.0-M3"
id("org.springframework.boot") version "2.7.1"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.6.21"
kotlin("plugin.spring") version "1.6.21"
id("org.jetbrains.kotlin.plugin.noarg") version "1.7.10"
kotlin("jvm") version "1.7.10"
kotlin("plugin.jpa") version "1.7.10"
kotlin("plugin.spring") version "1.7.10"
}

group = "com.todo"
group = "com.app"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_17
java.sourceCompatibility = JavaVersion.VERSION_18

noArg {
annotation("javax.persistence.Entity")
}

repositories {
mavenCentral()
maven { url = uri("https://repo.spring.io/milestone") }
maven { url = uri("https://repo.spring.io/snapshot") }
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.boot:spring-boot-starter-webflux")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-validation")
testImplementation("org.springframework.boot:spring-boot-starter-test")
developmentOnly("org.springframework.boot:spring-boot-devtools")
implementation("com.linecorp.kotlin-jdsl:spring-data-kotlin-jdsl-starter:2.0.4.RELEASE")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
developmentOnly("org.springframework.boot:spring-boot-devtools")
implementation("org.junit.jupiter:junit-jupiter:5.8.2")
implementation("org.springdoc:springdoc-openapi-data-rest:1.6.9")
implementation("org.springdoc:springdoc-openapi-ui:1.6.9")
implementation("org.springdoc:springdoc-openapi-kotlin:1.6.9")
implementation("org.springdoc:springdoc-openapi-webflux-ui:1.6.9")
implementation("io.arrow-kt:arrow-core:1.1.2")
runtimeOnly("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation(kotlin("test"))
testImplementation("io.kotest:kotest-runner-junit5:5.3.2")
testImplementation("io.kotest:kotest-assertions-core:5.3.2")
testImplementation("io.kotest:kotest-property:5.3.2")
testImplementation("io.kotest.extensions:kotest-assertions-arrow")
testImplementation("io.kotest.extensions:kotest-extensions-spring")
}

tasks.withType<KotlinCompile> {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "17"
jvmTarget = "18"
}
}

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

1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
pluginManagement {
repositories {
maven { url = uri("https://repo.spring.io/milestone") }
maven { url = uri("https://repo.spring.io/snapshot") }
gradlePluginPortal()
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/main/kotlin/com/app/TodoDDDApplication.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package com.todo.tododdd
package com.app

import io.swagger.v3.oas.models.OpenAPI
import io.swagger.v3.oas.models.info.Info
import org.springdoc.core.GroupedOpenApi
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication
import org.springframework.context.annotation.Bean


@SpringBootApplication
class TodoDddApplication
class TodoDDDApplication

fun main(args: Array<String>) {
runApplication<TodoDddApplication>(*args)
val context = runApplication<TodoDDDApplication>(*args)
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.app.core.exceptions

class EntityNotFound(
class EntityNotFoundException(
message: String = "Entity Not Found"
) : Exception(message = message)
) : Exception(message)
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.app.core.exceptions

import java.util.*

class InvalidOperationException(message: String) : Exception(
message = message
message
)
11 changes: 9 additions & 2 deletions src/main/kotlin/com/app/core/failures/BadRequestFailure.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
package com.app.core.failures

class BadRequestFailure {
}
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus
import java.util.*

@ResponseStatus(HttpStatus.BAD_REQUEST)
class BadRequestFailure(
override val id: UUID,
override val message: String,
) : BaseFailure(), IBaseFailure
57 changes: 34 additions & 23 deletions src/main/kotlin/com/app/core/failures/BaseFailure.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,50 @@ package com.app.core.failures

import com.app.core.exceptions.EntityNotFoundException
import com.app.core.exceptions.InvalidOperationException
import com.fasterxml.jackson.annotation.JsonIgnore
import org.springframework.http.HttpStatus
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ResponseStatus
import java.util.*
import kotlin.reflect.full.findAnnotations


interface IBaseFailure {
val id: UUID
val message: String
}

abstract class BaseFailure {

private fun getFactories(id: UUID, message: String): HashMap<Any, () -> IBaseFailure> = hashMapOf(
InvalidOperationException::class to { BadRequestFailure(id, message) },
EntityNotFoundException::class to { NotFoundFailures(id, message) }
)
fun getAnnotatedStatus(): HttpStatus
}

fun fromException(exception: Exception): () -> IBaseFailure {
val message: String = exception.message.orEmpty()
abstract class BaseFailure : IBaseFailure {

val factories = getFactories(
id = UUID.randomUUID(),
message = message
)
@JsonIgnore
override fun getAnnotatedStatus(): HttpStatus {
val failureStatus = this::class.findAnnotations(ResponseStatus::class).firstOrNull()?.value
return failureStatus ?: HttpStatus.INTERNAL_SERVER_ERROR
}

return factories[exception::class] ?: throw exception
companion object {
fun fromException(exception: Exception): () -> IBaseFailure {
val message: String = exception.message.orEmpty()
val uuid: UUID = UUID.randomUUID()

val factories = hashMapOf(
InvalidOperationException::class to { BadRequestFailure(uuid, message) },
EntityNotFoundException::class to { NotFoundFailure(uuid, message) },
MethodArgumentNotValidException::class to {
val validationErrors = (exception as MethodArgumentNotValidException).bindingResult.fieldErrors
val validationMessage = validationErrors.joinToString(
separator = ", "
) { "${it.field}: ${it.defaultMessage}" }
ValidationFailure(uuid, validationMessage)
},
)

// throw exception which will be caught and transformed to ServerFailureResponse
return factories[exception::class] ?: { ServerFailure(id = uuid, message = message) }
}
}
}

data class BadRequestFailure(
override val id: UUID,
override val message: String,
) : BaseFailure(), IBaseFailure
}

data class NotFoundFailures(
override val id: UUID,
override val message: String,
) : BaseFailure(), IBaseFailure
13 changes: 11 additions & 2 deletions src/main/kotlin/com/app/core/failures/NotFoundFailure.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
package com.app.core.failures

class NotFoundFailure {
}
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus
import java.util.*

@ResponseStatus(HttpStatus.NOT_FOUND)
class NotFoundFailure(
override val id: UUID,
override val message: String,
) : BaseFailure() {

}
11 changes: 10 additions & 1 deletion src/main/kotlin/com/app/core/failures/ServerFailure.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
package com.app.core.failures

class ServerFailure {
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus
import java.util.*

@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
class ServerFailure(
override val id: UUID,
override val message: String
) : BaseFailure() {

}
11 changes: 9 additions & 2 deletions src/main/kotlin/com/app/core/failures/ValidationFailure.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
package com.app.core.failures

class ValidationFailure {
}
import org.springframework.http.HttpStatus
import org.springframework.web.bind.annotation.ResponseStatus
import java.util.*

@ResponseStatus(HttpStatus.BAD_REQUEST)
class ValidationFailure(
override val id: UUID,
override val message: String
) : BaseFailure()
6 changes: 5 additions & 1 deletion src/main/kotlin/com/app/core/routes/BaseRoute.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
package com.app.core.routes

class BaseRoute {
import org.springframework.web.reactive.function.server.RouterFunction
import org.springframework.web.reactive.function.server.ServerResponse

interface BaseRoute {
operator fun invoke(): RouterFunction<ServerResponse>
}
8 changes: 6 additions & 2 deletions src/main/kotlin/com/app/core/unitofwork/UnitOfWork.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
package com.app.core.unitofwork

class UnitOfWork {
}
interface IUnitOfWork<out T> {

fun begin(): Unit
fun commit(): Unit
fun rollback(): Unit
}
11 changes: 9 additions & 2 deletions src/main/kotlin/com/app/core/usecases/Usecase.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
package com.app.core.usecases

class Usecase {
}
import arrow.core.Either

interface IUseCaseNoParams<Type> {
operator fun invoke(): Either<Exception, Type>
}

interface IUseCase<Type, Params> {
operator fun invoke(params: Params): Either<Exception, Type>
}
78 changes: 77 additions & 1 deletion src/main/kotlin/com/app/features/todo/data/models/Todo.kt
Original file line number Diff line number Diff line change
@@ -1,4 +1,80 @@
package com.app.features.todo.data.models

class Todo {
import com.app.features.todo.domain.entities.TodoReadModel
import com.app.features.user.data.models.User
import com.app.features.todo.domain.entities.Todo as TodoEntity
import org.hibernate.annotations.DynamicUpdate
import org.springframework.data.annotation.LastModifiedDate
import java.util.Date
import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.ForeignKey
import javax.persistence.GeneratedValue
import javax.persistence.Id
import javax.persistence.JoinColumn
import javax.persistence.ManyToOne
import javax.persistence.OneToMany

@Entity(name = "Todos")
@DynamicUpdate
class Todo(
@Id
@GeneratedValue
val id: Int,
val title: String,
@Column(
nullable = false
)
val ownerId: Int,
@Column(
updatable = false
)
val createdAt: Date,
@LastModifiedDate
val updatedAt: Date,
val isCompleted: Boolean,
val isDeleted: Boolean,
) {
@ManyToOne
@JoinColumn(
name = "ownerId",
nullable = false,
insertable = false,
updatable = false
)
lateinit var owner: User

constructor(todo: TodoEntity) : this(
id = todo.id,
title = todo.title,
ownerId = todo.ownerId,
createdAt = todo.createdAt,
updatedAt = todo.updatedAt,
isCompleted = todo.isCompleted,
isDeleted = todo.isDeleted
)

fun toDomainEntity(): TodoEntity{
return TodoEntity(
id = this.id,
title = this.title,
ownerId = this.ownerId,
createdAt = this.createdAt,
updatedAt = this.updatedAt,
isCompleted = this.isCompleted,
isDeleted = this.isDeleted
)
}

fun toReadModel(): TodoReadModel {
return TodoReadModel(
id = this.id,
title = this.title,
ownerId = this.ownerId,
createdAt = this.createdAt,
updatedAt = this.updatedAt,
isCompleted = this.isCompleted,
isDeleted = this.isDeleted
)
}
}
Loading

0 comments on commit 55c366d

Please sign in to comment.