Skip to content

Commit

Permalink
Merge pull request #19 from zucchero-sintattico/feature/micronaut-pro…
Browse files Browse the repository at this point in the history
…ject-structure

Prepare Template for Microservice Develop
  • Loading branch information
manuandru authored Mar 5, 2024
2 parents f937adb + 97ef2dd commit d15a458
Show file tree
Hide file tree
Showing 38 changed files with 454 additions and 4 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ jobs:
fail-fast: false
matrix:
os:
- macos-13
# Commented until we find a way to run containertests on macOS and Windows
# - macos-13
- ubuntu-22.04
- windows-2022
# - windows-2022
java-version: [ 17, 21 ]
java-distribution:
- adopt
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
.idea/.gitignore
.idea/vcs.xml
.idea/ktfmt.xml
.idea/codeStyles/**
.idea/detekt.xml
.idea/ktlint-plugin.xml

# CMake
cmake-build-*/
Expand Down
7 changes: 7 additions & 0 deletions build-logic/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@ repositories {
}

dependencies {
implementation(libs.plugins.allOpen.asDependency())
implementation(libs.plugins.detekt.asDependency())
implementation(libs.plugins.kotlin.asDependency())
implementation(libs.plugins.kover.asDependency())
implementation(libs.plugins.ksp.asDependency())
implementation(libs.plugins.ktfmt.asDependency())
implementation(libs.plugins.micronaut.app.asDependency())
implementation(libs.plugins.micronaut.aot.asDependency())
implementation(libs.plugins.micronaut.test.asDependency())
implementation(libs.micronaut.buildtools)
implementation(libs.plugins.shadow.asDependency())
}

fun Provider<PluginDependency>.asDependency(): Provider<String> =
Expand Down
6 changes: 5 additions & 1 deletion build-logic/src/main/kotlin/Utils.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import org.gradle.api.artifacts.ExternalModuleDependencyBundle
import org.gradle.api.artifacts.MinimalExternalModuleDependency
import org.gradle.api.artifacts.VersionCatalog
import org.gradle.api.provider.Provider

fun VersionCatalog.getLibrary(name: String): Provider<MinimalExternalModuleDependency> = findLibrary(name).get()

fun VersionCatalog.getBundle(name: String): Provider<ExternalModuleDependencyBundle> = findBundle(name).get()

object JavaVersion {
const val target: Int = 17
const val asInt: Int = 17
val asVersion: org.gradle.api.JavaVersion = org.gradle.api.JavaVersion.toVersion(asInt)
}
2 changes: 1 addition & 1 deletion build-logic/src/main/kotlin/kotlin-base.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,5 @@ tasks.test {
}

kotlin {
jvmToolchain(JavaVersion.target)
jvmToolchain(JavaVersion.asInt)
}
47 changes: 47 additions & 0 deletions build-logic/src/main/kotlin/micronaut-base.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
plugins {
id("kotlin-base")
id("org.jetbrains.kotlin.plugin.allopen")
id("com.google.devtools.ksp")
id("com.github.johnrengelman.shadow")
id("io.micronaut.application")
id("io.micronaut.aot")
id("io.micronaut.test-resources")
}

val catalog: VersionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")

dependencies {
ksp(catalog.getBundle("micronaut-ksp"))
implementation(catalog.getBundle("micronaut-kotlin"))
catalog.getLibrary("micronaut-httpClient").let {
compileOnly(it)
testImplementation(it)
}
runtimeOnly(catalog.getLibrary("logback"))
runtimeOnly(catalog.getLibrary("jackson-kotlin"))
}

java {
sourceCompatibility = JavaVersion.asVersion
}

graalvmNative.toolchainDetection.set(false)
micronaut {
runtime("netty")
testRuntime("kotest5")
processing {
incremental(true)
annotations("micronaut.playground.*")
}
aot {
// Please review carefully the optimizations enabled below
// Check https://micronaut-projects.github.io/micronaut-aot/latest/guide/ for more details
optimizeServiceLoading = false
convertYamlToJava = false
precomputeOperations = true
cacheEnvironment = true
optimizeClassLoading = true
deduceEnvironment = true
optimizeNetty = true
}
}
22 changes: 22 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,45 @@ konsist = "0.13.0"
kotest = "5.8.0"
kotlin = "1.9.22"
kover = "0.7.6"
ksp = "1.9.22-1.0.17"
ktfmt = "0.17.0"
micronaut = "4.3.4"
micronautBuildTools = "2.4.0"
shadow = "8.1.1"

[libraries]
cucumber-bom = { module = "io.cucumber:cucumber-bom", version.ref = "cucumber-bom" }
cucumber-java = { module = "io.cucumber:cucumber-java" }
cucumber-junit = { module = "io.cucumber:cucumber-junit-platform-engine" }
junit-platform = { module = "org.junit.platform:junit-platform-suite", version.ref = "junit-platform" }
jackson-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlin-stdlibJdk8 = { module = "org.jetbrains.kotlin:kotlin-stdlib-jdk8", version.ref = "kotlin" }
konsist = { module = "com.lemonappdev:konsist", version.ref = "konsist" }
kotest = { module = "io.kotest:kotest-runner-junit5", version.ref = "kotest" }
logback = { module = "ch.qos.logback:logback-classic" }
micronaut-buildtools = { module = "io.micronaut.testresources:micronaut-test-resources-build-tools", version.ref = "micronautBuildTools" }
micronaut-httpClient = { module = "io.micronaut:micronaut-http-client" }
micronaut-httpValidation = { module = "io.micronaut:micronaut-http-validation" }
micronaut-kotlinRuntime = { module = "io.micronaut.kotlin:micronaut-kotlin-runtime" }
micronaut-serdeJackson = { module = "io.micronaut.serde:micronaut-serde-jackson" }
micronaut-serdeProcessor = { module = "io.micronaut.serde:micronaut-serde-processor" }

[plugins]
allOpen = { id = "org.jetbrains.kotlin.plugin.allopen", version.ref = "kotlin" }
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detekt" }
dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" }
gitSemVer = { id = "org.danilopianini.git-sensitive-semantic-versioning", version.ref = "gitSemVer" }
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
ktfmt = { id = "com.ncorti.ktfmt.gradle", version.ref = "ktfmt" }
micronaut-app = { id = "io.micronaut.application", version.ref = "micronaut" }
micronaut-aot = { id = "io.micronaut.application", version.ref = "micronaut" }
micronaut-test = { id = "io.micronaut.test-resources", version.ref = "micronaut" }
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }

[bundles]
cucumberJunit = [ "cucumber-java", "cucumber-junit" ]
micronaut-ksp = [ "micronaut-httpValidation", "micronaut-serdeProcessor" ]
micronaut-kotlin = [ "kotlin-reflect", "kotlin-stdlibJdk8", "micronaut-kotlinRuntime", "micronaut-serdeJackson", ]
15 changes: 15 additions & 0 deletions micronaut-playground/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Thumbs.db
.DS_Store
.gradle
build/
target/
out/
.micronaut/
.idea
*.iml
*.ipr
*.iws
.project
.settings
.classpath
.factorypath
4 changes: 4 additions & 0 deletions micronaut-playground/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
application:
name: "My Application"
version: "1.0.0"
description: "My Application Description"
9 changes: 9 additions & 0 deletions micronaut-playground/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugins { id("micronaut-base") }

application { mainClass.set("micronaut.playground.ApplicationKt") }

dependencies {
ksp("io.micronaut.data:micronaut-data-document-processor")
implementation("io.micronaut.data:micronaut-data-mongodb")
runtimeOnly("org.mongodb:mongodb-driver-sync")
}
3 changes: 3 additions & 0 deletions micronaut-playground/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
micronautVersion=4.3.2
kotlinVersion=1.9.22
org.gradle.jvmargs=-Xmx4096M
6 changes: 6 additions & 0 deletions micronaut-playground/micronaut-cli.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
applicationType: default
defaultPackage: micronaut.playground
testFramework: kotest
sourceLanguage: kotlin
buildTool: gradle_kotlin
features: [ app-name, gradle, http-client-test, kotest, kotlin, kotlin-application, ksp, logback, micronaut-aot, micronaut-build, micronaut-http-validation, netty-server, properties, readme, serialization-jackson, shade, static-resources ]
1 change: 1 addition & 0 deletions micronaut-playground/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = "micronaut-playground"
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package piperkt.services.template

import io.micronaut.runtime.Micronaut.run

fun main(vararg args: String) {
run(*args)
}

// LEVEL -> WHATS -> DEPENDENCIES
// --------------------------------
// DOMAIN -> Language:
// - Entities
// - Value Objects
// - Repositories
// - Factories
// APPLICATION -> Domain
// - Services
// INTERFACES ->
// - Controller (Indepedent of the framework)
// INFRASTRUCTURE
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package piperkt.services.template.application

import piperkt.services.template.application.api.UserEventsApi
import piperkt.services.template.commons.events.UserCreated
import piperkt.services.template.domain.User
import piperkt.services.template.domain.UserRepository

class UserEventsService(private val userRepository: UserRepository) : UserEventsApi {
override fun onUserCreated(userCreated: UserCreated) {
userRepository.save(User(email = userCreated.email, password = userCreated.password))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package piperkt.services.template.application

import piperkt.services.template.application.api.UserServiceApi
import piperkt.services.template.commons.events.EventPublisher
import piperkt.services.template.commons.events.UserCreated
import piperkt.services.template.domain.User
import piperkt.services.template.domain.UserRepository

open class UserService(
private val userRepository: UserRepository,
private val eventPublisher: EventPublisher,
) : UserServiceApi {
override fun registerUser(
email: String,
password: String,
): User {
val user = User(email = email, password = password)
return userRepository.save(user).also {
eventPublisher.publish(UserCreated(email = email, password = password))
}
}

override fun loginUser(
email: String,
password: String,
): User? = userRepository.findByEmail(email)?.takeIf { it.password == password }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package piperkt.services.template.application.api

import piperkt.services.template.commons.events.UserCreated

interface UserEventsApi {
fun onUserCreated(userCreated: UserCreated)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package piperkt.services.template.application.api

import piperkt.services.template.domain.User

interface UserServiceApi {
fun registerUser(
email: String,
password: String,
): User

fun loginUser(
email: String,
password: String,
): User?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package piperkt.services.template.commons.events

interface Event

interface EventPublisher {
fun publish(event: Event)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package piperkt.services.template.commons.events

data class UserCreated(
val email: String,
val password: String,
) : Event
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package piperkt.services.template.domain

data class User(
val email: String,
val password: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package piperkt.services.template.domain

interface UserRepository {
fun findByEmail(email: String): User?

fun save(user: User): User
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package piperkt.services.template.infrastructure.events

import jakarta.inject.Singleton
import piperkt.services.template.commons.events.Event
import piperkt.services.template.commons.events.EventPublisher

@Singleton
class KafkaEventPublisher : EventPublisher {
override fun publish(event: Event) {
println("Publishing event: $event")
}
}

/**
* @Singleton class KafkaEventPublisher(): EventPublisher {
*
* override fun publish(any: Any) {
*
* }
*
* }
*
* @KafkaListener class KafkaListener(userEventsService: UserEventsService): UserEventsApi {
* @Topic("user-created") override fun onUserCreated(userCreated: UserCreated) {
* userEventsService.onUserCreated(userCreated) }
*
* }
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package piperkt.services.template.infrastructure.implementation

import jakarta.inject.Singleton
import piperkt.services.template.commons.events.EventPublisher
import piperkt.services.template.domain.UserRepository

@Singleton
class UserServiceImpl(
userRepository: UserRepository,
eventPublisher: EventPublisher,
) : piperkt.services.template.application.UserService(userRepository, eventPublisher)
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package piperkt.services.template.infrastructure.persistence.model

import io.micronaut.data.annotation.Id
import io.micronaut.data.annotation.MappedEntity
import io.micronaut.data.mongodb.annotation.MongoRepository
import io.micronaut.data.repository.CrudRepository
import jakarta.validation.constraints.NotBlank

@MappedEntity
data class UserEntity(
@Id val email: String,
@NotBlank val password: String,
)

@MongoRepository interface UserModelRepository : CrudRepository<UserEntity, String>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package piperkt.services.template.infrastructure.persistence.repository

import jakarta.inject.Named
import piperkt.services.template.domain.User
import piperkt.services.template.domain.UserRepository

@Named("inMemory")
class InMemoryRepository : UserRepository {
val users = mutableListOf<User>()

override fun findByEmail(email: String): User? = users.find { it.email == email }

override fun save(user: User): User {
users.add(user)
return user
}
}
Loading

0 comments on commit d15a458

Please sign in to comment.