-
Notifications
You must be signed in to change notification settings - Fork 38.2k
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
Throw an exception for suspending factory methods #32719
Comments
Suspending functions should not be used with FYI, in your repro, the message is printed 2 times because the decompiled generated bytecode is: public class DemoSbWithValueClassApplication {
@Bean
@Nullable
public Object greeting(@NotNull Continuation $completion) {
return greeting$suspendImpl(this, $completion);
}
// $FF: synthetic method
@Bean
static Object greeting$suspendImpl(DemoSbWithValueClassApplication $this, Continuation $completion) {
String var2 = "Hello, World!";
System.out.println(var2);
return "My test";
}
} |
I don't understand why it's a problem to instantiate a bean in a suspend method. In Kotlin, some libraries create a builder using a suspend method. I suggest creating the Bean using a coroutine attached to the main thread (or the dedicated thread where the Bean are instantiated). For example (that's not the best example, but maybe it will allow you to understand the need and how to do that in Kotlin): import kotlin.properties.Delegates
import kotlinx.coroutines.delay
public class MyClient(
public val arg1: Int,
public val arg2: String,
) {
public companion object {
/**
* ```kotlin
* val client = MyClient {
* arg1 = 1
* // ...
* }
* ```
*/
public suspend inline operator fun invoke(builder: Builder.() -> Unit): MyClient =
Builder().apply(builder).build()
}
public class Builder {
public var arg1: Int by Delegates.notNull()
public lateinit var arg2: String
public var shouldCallMyServer: Boolean = false
public suspend fun build(): MyClient {
return MyClient(
arg1 = arg1,
arg2 = arg2
).apply {
// Init the client with suspending calls according to some builder properties
if (shouldCallMyServer) {
// Simulate a suspending call
delay(1000)
}
}
}
}
} With that, if I need to do something that needs I/O operation, according to the builder properties and to simplify the management of my object, I can do this in the builder. |
After of course, you can wrap your Builder in a run blocking method. Like: @SpringBootApplication
class SpringApplication {
@Bean
fun greeting(): MyClient {
return runBlocking {
MyClient { ... }
}
}
} |
I don't think suspending factory method conceptually make sense, they have side effects, and you indeed have the possibility to use |
Hello
The
@Bean
seems to be called two times according to logs (below) in asuspend
kotlin function.This is my app code:
And the logs when I started the application:
Now, if I try without the
suspend
keyword like:And the logs:
There are the other file to reproduces:
build.gradle.kts
Version:
The text was updated successfully, but these errors were encountered: