Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

micronaut framework implemented. #673

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
15 changes: 7 additions & 8 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import org.gradle.kotlin.dsl.libs
import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.dokka.gradle.DokkaMultiModuleTask
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
Expand All @@ -15,6 +14,7 @@ plugins {
idea
java
}

group = "com.trendyol"
version = CI.version(project)

Expand Down Expand Up @@ -42,14 +42,14 @@ kover {
}
}
}
val related = subprojects.of("lib", "spring", "examples", "ktor")
val related = subprojects.of("lib", "spring", "examples", "ktor", "micronaut")
dependencies {
related.forEach {
kover(it)
}
}

subprojects.of("lib", "spring", "examples", "ktor") {
subprojects.of("lib", "spring", "examples", "ktor", "micronaut") {
apply {
plugin("kotlin")
plugin(rootProject.libs.plugins.spotless.get().pluginId)
Expand All @@ -76,13 +76,12 @@ subprojects.of("lib", "spring", "examples", "ktor") {
testImplementation(libs.kotest.runner.junit5)
testImplementation(libs.kotest.framework.api)
testImplementation(libs.kotest.property)
testImplementation(libs.kotest.arrow)
detektPlugins(libs.detekt.formatting)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why removed?

}

spotless {
kotlin {
ktlint(libs.versions.ktlint.get()).setEditorConfigPath(rootProject.layout.projectDirectory.file(".editorconfig"))
ktlint().setEditorConfigPath(rootProject.layout.projectDirectory.file(".editorconfig"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should not change.

targetExclude("build/", "generated/", "out/")
targetExcludeIfContentContains("generated")
targetExcludeIfContentContainsRegex("generated.*")
Expand Down Expand Up @@ -141,10 +140,11 @@ val publishedProjects = listOf(
"stove-testing-e2e-redis",
"stove-ktor-testing-e2e",
"stove-spring-testing-e2e",
"stove-spring-testing-e2e-kafka"
"stove-spring-testing-e2e-kafka",
"stove-micronaut-testing-e2e"
)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can remove it for now, until it gets matured, we don't want to publish it.


subprojects.of("lib", "spring", "ktor", filter = { p -> publishedProjects.contains(p.name) }) {
subprojects.of("lib", "spring", "ktor", "micronaut", filter = { p -> publishedProjects.contains(p.name) }) {
apply {
plugin("java")
plugin("stove-publishing")
Expand All @@ -159,4 +159,3 @@ subprojects.of("lib", "spring", "ktor", filter = { p -> publishedProjects.contai
tasks.withType<DokkaMultiModuleTask>().configureEach {
outputDirectory.set(file(rootDir.resolve("docs/source")))
}

76 changes: 76 additions & 0 deletions examples/micronaut-example/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
plugins {
kotlin("jvm") version libs.versions.kotlin
id("org.jetbrains.kotlin.plugin.allopen") version libs.versions.kotlin
kotlin("plugin.serialization") version libs.versions.kotlin
alias(libs.plugins.google.ksp)
alias(libs.plugins.shadowJar)
alias(libs.plugins.micronaut.application)
alias(libs.plugins.micronaut.aot)
application
idea
}

dependencies {
runtimeOnly(libs.snakeyaml)
implementation(platform(libs.micronaut.parent))
ksp(libs.micronaut.http.validation)
ksp(libs.micronaut.serde.processor)
implementation(libs.dagger.compiler)
ksp(libs.dagger.compiler)
implementation(libs.micronaut.kotlin.runtime)
implementation(libs.micronaut.serde.jackson)
implementation(libs.micronaut.http.client)
implementation(libs.micronaut.http.server.netty)
implementation(libs.micronaut.inject)
implementation(libs.micronaut.core)
runtimeOnly(libs.jackson.kotlin)
implementation(libs.couchbase.client.metrics)
implementation(libs.micronaut.micrometer.core)
implementation(libs.kafka.clients)
implementation(libs.kotlinx.reactor)
implementation(libs.kotlinx.core)
implementation(libs.kotlinx.reactive)
implementation(libs.couchbase.client)
implementation(libs.couchbase.client.metrics)
implementation(libs.jackson.kotlin)
implementation(libs.kotlinx.slf4j)
}

dependencies {
testImplementation(libs.kotest.property)
testImplementation(libs.kotest.runner.junit5)
testImplementation(projects.stove.lib.stoveTestingE2eHttp)
testImplementation(projects.stove.lib.stoveTestingE2eWiremock)
testImplementation(projects.stove.lib.stoveTestingE2eCouchbase)
testImplementation(projects.stove.lib.stoveTestingE2eElasticsearch)
testImplementation(projects.stove.starters.micronaut.stoveMicronautTestingE2e)
}

application {
mainClass = "stove.micronaut.example.ApplicationKt"
}

graalvmNative.toolchainDetection = false

java {
sourceCompatibility = JavaVersion.toVersion("17")
}

micronaut {
runtime("netty")
testRuntime("kotest5")
processing {
incremental(true)
annotations("stove.micronaut.example.*")
}
aot {
optimizeServiceLoading = false
convertYamlToJava = false
precomputeOperations = true
cacheEnvironment = true
optimizeClassLoading = true
deduceEnvironment = true
optimizeNetty = true
replaceLogbackXml = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package stove.micronaut.example

import io.micronaut.context.ApplicationContext
import io.micronaut.runtime.EmbeddedApplication

fun main(args: Array<String>) {
run(args)
}

fun run(
args: Array<String>,
init: ApplicationContext.() -> Unit = {}
): ApplicationContext {
val context = ApplicationContext
.builder()
.args(*args)
.build()
.also(init)
.start()

context.findBean(EmbeddedApplication::class.java).ifPresent { app ->
if (!app.isRunning) {
app.start()
}
}

return context
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package stove.micronaut.example.application.domain

import io.micronaut.serde.annotation.Serdeable
import java.util.*

@Serdeable
data class Product(
val id: String,
val name: String,
val supplierId: Long,
val isBlacklist: Boolean,
val createdDate: Date
) {
companion object {

fun new(id: String, name: String, supplierId: Long, isBlacklist: Boolean): Product {
return Product(
id = id,
name = name,
supplierId = supplierId,
createdDate = Date(),
isBlacklist = isBlacklist
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package stove.micronaut.example.application.repository

import stove.micronaut.example.application.domain.Product

interface ProductRepository {
suspend fun save(product: Product): Product
suspend fun findById(id: Long): Product?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package stove.micronaut.example.application.services

import jakarta.inject.Singleton
import stove.micronaut.example.application.domain.Product
import stove.micronaut.example.application.repository.ProductRepository
import stove.micronaut.example.infrastructure.http.SupplierHttpService

@Singleton
class ProductService(
private val productRepository: ProductRepository,
private val supplierHttpService: SupplierHttpService
) {
suspend fun createProduct(id: String, productName: String, supplierId: Long): Product {
val supplier = supplierHttpService.getSupplierPermission(supplierId)
val product = Product.new(id, productName, supplierId, supplier!!.isBlacklisted)
productRepository.save(product)
return product
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package stove.micronaut.example.application.services

import io.micronaut.serde.annotation.Serdeable

@Serdeable
data class SupplierPermission(
val id: Long,
val isBlacklisted: Boolean
)

interface SupplierService {
suspend fun getSupplierPermission(supplierId: Long): SupplierPermission?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package stove.micronaut.example.infrastructure.api

import io.micronaut.http.annotation.*
import stove.micronaut.example.application.domain.Product
import stove.micronaut.example.application.services.ProductService
import stove.micronaut.example.infrastructure.api.model.request.CreateProductRequest

@Controller("/products")
class ProductController(
private val productService: ProductService
) {
@Get("/index")
fun get(
@QueryValue keyword: String = "default"
): String = "Hi from Stove framework with $keyword"

@Post("/create")
suspend fun createProduct(
@Body request: CreateProductRequest
): Product = productService.createProduct(
id = request.id,
productName = request.name,
supplierId = request.supplierId
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package stove.micronaut.example.infrastructure.api.model.request

import io.micronaut.serde.annotation.Serdeable

@Serdeable
data class CreateProductRequest(
val id: String,
val name: String,
val supplierId: Long
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package stove.micronaut.example.infrastructure.couchbase

import com.couchbase.client.java.*
import com.couchbase.client.java.Collection
import com.couchbase.client.java.codec.JacksonJsonSerializer
import com.couchbase.client.java.env.ClusterEnvironment
import com.couchbase.client.java.json.JsonValueModule
import com.fasterxml.jackson.databind.ObjectMapper
import io.micronaut.context.annotation.*
import jakarta.annotation.PreDestroy
import jakarta.inject.Singleton
import java.time.Duration

@Factory
class CouchbaseConfiguration(
private val couchbaseProperties: CouchbaseProperties
) {
companion object {
val objectMapper: ObjectMapper =
ObjectMapper()
.findAndRegisterModules()
.registerModule(JsonValueModule())
}

@Primary
@Context
fun clusterEnvironment(): ClusterEnvironment {
val cbSerializer = JacksonJsonSerializer.create(objectMapper)
return ClusterEnvironment
.builder()
.timeoutConfig {
it
.kvTimeout(Duration.ofMillis(couchbaseProperties.kvTimeout))
.connectTimeout(Duration.ofMillis(couchbaseProperties.connectTimeout))
.queryTimeout(Duration.ofMillis(couchbaseProperties.queryTimeout))
.viewTimeout(Duration.ofMillis(couchbaseProperties.viewTimeout))
}.jsonSerializer(cbSerializer)
.build()
}

@Primary
@Singleton
fun cluster(clusterEnvironment: ClusterEnvironment): Cluster {
val clusterOptions = ClusterOptions
.clusterOptions(couchbaseProperties.username, couchbaseProperties.password)
.environment(clusterEnvironment)

return Cluster.connect(couchbaseProperties.hosts.joinToString(","), clusterOptions)
}

@Primary
@Singleton
fun bucket(cluster: Cluster): Bucket = cluster.bucket(couchbaseProperties.bucketName)

@Primary
@Singleton
fun productCouchbaseCollection(bucket: Bucket): Collection = bucket.defaultCollection()

@PreDestroy
fun cleanup(cluster: Cluster, clusterEnvironment: ClusterEnvironment) {
cluster.disconnect()
clusterEnvironment.shutdown()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package stove.micronaut.example.infrastructure.couchbase

import io.micronaut.context.annotation.*

@ConfigurationProperties("couchbase")
class CouchbaseProperties {
var username: String? = null
var password: String? = null
var bucketName: String = ""
var hosts: List<String> = listOf()
var kvTimeout: Long = 0
var connectTimeout: Long = 0
var queryTimeout: Long = 0
var viewTimeout: Long = 0
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package stove.micronaut.example.infrastructure.couchbase

import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.module.kotlin.KotlinModule
import io.micronaut.context.annotation.Bean
import io.micronaut.context.annotation.Factory

@Factory
class ObjectMapperConfig {

companion object {
fun createObjectMapperWithDefaults(): ObjectMapper {
val isoInstantModule = SimpleModule()
return ObjectMapper()
.registerModule(KotlinModule.Builder().build())
.registerModule(isoInstantModule)
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
}
}

@Bean
fun objectMapper(): ObjectMapper {
return createObjectMapperWithDefaults()
}
}
Loading
Loading