Hello community, I’m currently working on a Spring Boot web application with a traditional three-lay...
a

Asif Ahmed

over 1 year ago
Hello community, I’m currently working on a Spring Boot web application with a traditional three-layer architecture: controller, service, and
ApiClient
for blocking calls. Due to certain limitations, adopting a fully reactive approach isn’t feasible at the moment. However, we are keen on finding a middle ground to improve performance through parallel calls. To achieve this, we are exploring Kotlin Coroutines(We have also explored CompletableFuture and @Asyc but not happy with it ). As a relative newcomer to coroutines, I’ve implemented a solution that seems to work, but I’m uncertain if it’s the optimal approach. Below is a simplified snippet of the current implementation:
@Service
class Service(
    private val clientA: ClientA,
    private val clientB: ClientB,
    private val clientC: ClientC
) {

    fun someFunction(): OrderForm {
        runBlocking(RequestCoroutineContext()) {
            val result1 = async(Dispatchers.IO) { callA() }
            val result2 = async(Dispatchers.IO) { callB() }

            val result3 = async(Dispatchers.IO) { callC(result1.await()) }

            OrderForm(result1.await(), result2.await(), result3.await())
        }
    }

    private suspend fun callA() = clientA.get()

    private suspend fun callB() = clientB.get()

    private suspend fun callC(value: SomeType) = clientC.get(value)
}
Initially, the
ApiClient
methods were not marked as
suspend
, but I’m now considering moving towards making these calls suspendable to bring them closer to the client:
class ClientA {
    suspend fun getA() {
        withContext(Dispatchers.IO) {
            // blocking API call
        }
    }
}

class ClientB {
    suspend fun getB() {
        withContext(Dispatchers.IO) {
            // blocking API call
        }
    }
}

class ClientC {
    suspend fun getC(value: SomeType) {
        withContext(Dispatchers.IO) {
            // blocking API call
        }
    }
}
However, attempting to call these suspendable functions in
someFunction()
resulted in an exception
Handler dispatch failed: java.lang.NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt","stack_trace":"jakarta.servlet.ServletException: Handler dispatch failed: java.lang.NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt
related to
NoClassDefFoundError: kotlinx/coroutines/reactor/MonoKt
. I suspect this may be due to the fact that the actual API calls are not reactive and suspendable. I’m seeking recommendations on the best way to handle coroutines in a single thread per request model with Spring Boot. I want to avoid marking private functions as suspended and continually wrapping code in scopes. Any insights or guidance would be greatly appreciated.
Question / issue using kotlin notebooks with local multi-project library code that uses java logging...
a

Andrew

over 2 years ago
Question / issue using kotlin notebooks with local multi-project library code that uses java logging libraries I'm trying to use kotlin notebooks in tandem with my own local library code. However, I have logback and log4j deeply embedded in the local library code I am using and it is preventing me from running any of my own code in the kotlin notebook. I am wondering if there is anything obvious I am missing about setting up here that will fix this. If not, I can put together a minimum reproducible example to try and debug this. The java logging libraries I am using are as follows:
@file:DependsOn("ch.qos.logback:logback-classic:1.4.5")
@file:DependsOn("org.slf4j:log4j-over-slf4j:2.0.3")
@file:DependsOn("org.slf4j:slf4j-api:2.0.3")
I am trying to instantiate a single class that prints out a log message when it is created, which leads to the following error stack trace:
Could not initialize class com.smartnews.cg.logging.SnMarker
java.lang.NoClassDefFoundError: Could not initialize class com.smartnews.cg.logging.SnMarker
	at com.smartnews.cg.logging.WithLogger.<init>(WithLogger.kt:10)
	at com.smartnews.cg.helpers.DataDownloadHelper.<init>(DataDownloadHelper.kt:26)
	at Line_4_jupyter.<init>(Line_4.jupyter.kts:33)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:490)
	at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.evalWithConfigAndOtherScriptsResults(BasicJvmScriptEvaluator.kt:105)
	at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.invoke$suspendImpl(BasicJvmScriptEvaluator.kt:47)
	at kotlin.script.experimental.jvm.BasicJvmScriptEvaluator.invoke(BasicJvmScriptEvaluator.kt)
	at kotlin.script.experimental.jvm.BasicJvmReplEvaluator.eval(BasicJvmReplEvaluator.kt:49)
	at org.jetbrains.kotlinx.jupyter.repl.impl.InternalEvaluatorImpl$eval$resultWithDiagnostics$1.invokeSuspend(InternalEvaluatorImpl.kt:103)
	at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
	at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
	at kotlinx.coroutines.EventLoopImplBase.processNextEvent(EventLoop.common.kt:284)
	at kotlinx.coroutines.BlockingCoroutine.joinBlocking(Builders.kt:85)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt:59)
	at kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)
	at kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking$default(Builders.kt:38)
	at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
I am using the latest version of IntelliJ IDEA Ultimate along with the kotlin notebook plugin (installed these yesterday). The notebook functions properly using code that is not from my local library. I am using kotlin version
1.8.10
. I've also tried using various combinations of
@file:DependsOn
or trying to import the missing classes, but have not had any luck. I'd really like to get this working so I can start using kotlin instead of python for my data wrangling needs! Thank you for your time and let me know if I can provide any additional information to help (such as a minimum reproducible example)