I seem to be able to disambiguate @Beans
via suppliers of Kotlin inline/value classes, even with Spring 6.0, but not as direct Kotlin value classes as of 6.1.0-M5.
With:
@JvmInline
value class TestBean1(val value: String)
@JvmInline
value class TestBean2(val value: String)
class TestService1(
private val testBean1: TestBean1
) {
fun init() = println(testBean1.value)
}
class TestService2(
private val testBean2: TestBean2
) {
fun init() = println(testBean2.value)
}
This works:
@SpringBootApplication
class KotlinValueClassSupplierApp {
@Bean
fun testBean1Supplier(): () -> TestBean1 =
{ TestBean1("Test 1") }
@Bean
fun testBean2Supplier(): () -> TestBean2 =
{ TestBean2("Test 2") }
@Bean
fun testService1(
testBean1Supplier: () -> TestBean1
): TestService1 =
TestService1(testBean1Supplier())
.also { it.init() }
@Bean
fun testService2(
testBean2Supplier: () -> TestBean2
): TestService2 =
TestService2(testBean2Supplier())
.also { it.init() }
}
But this doesn't work:
@SpringBootApplication
class KotlinValueClassApp {
@Bean
fun testBean1(): TestBean1 =
TestBean1("Test 1")
@Bean
fun testBean2(): TestBean2 =
TestBean2("Test 2")
@Bean
fun testService1(
testBean1: TestBean1
): TestService1 =
TestService1(testBean1)
.also { it.init() }
@Bean
fun testService2(
testBean2: TestBean2
): TestService2 =
TestService2(testBean2)
.also { it.init() }
}
With the latter I get:
2023-10-06T11:55:38.461-07:00 WARN 27495 --- [ main] s.c.a.AnnotationConfigApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'testService1-W6siHTI' defined in org.sdkotlin.springvalueclassdemo.direct.KotlinValueClassApp: Unsatisfied dependency expressed through method 'testService1-W6siHTI' parameter 0: No qualifying bean of type 'java.lang.String' available: expected single matching bean but found 2: testBean1-vOanaPk,testBean2-0g9j1a8
2023-10-06T11:55:38.468-07:00 INFO 27495 --- [ main] .s.b.a.l.ConditionEvaluationReportLogger :
Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2023-10-06T11:55:38.493-07:00 ERROR 27495 --- [ main] o.s.b.d.LoggingFailureAnalysisReporter :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method testService1-W6siHTI in org.sdkotlin.springvalueclassdemo.direct.KotlinValueClassApp required a single bean, but 2 were found:
- testBean1-vOanaPk: defined by method 'testBean1-vOanaPk' in org.sdkotlin.springvalueclassdemo.direct.KotlinValueClassApp
- testBean2-0g9j1a8: defined by method 'testBean2-0g9j1a8' in org.sdkotlin.springvalueclassdemo.direct.KotlinValueClassApp
Action:
Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed
Process finished with exit code 1
Full reproducer in a project:
https://github.com/sdkotlin/sd-kotlin-spring-talks/blob/8f1bae8217f2b876d51843a12fe118eb9fd7bc12/subprojects/app/src/main/kotlin/org/sdkotlin/springvalueclassdemo/direct/KotlinValueClassApp.kt
This may relate to #28638.
Comment From: ianbrandt
Reproducer as a test (failing case is @Disabled
):
https://github.com/sdkotlin/sd-kotlin-spring-talks/blob/d5ab2387e1879a854176fac7d14fce09bbeac72c/subprojects/app/src/it/kotlin/org/sdkotlin/springdemo/SpringKotlinValueClassIT.kt
Comment From: sdeleuze
I seem to be able to disambiguate @Beans via suppliers of Kotlin inline/value classes, even with Spring 6.0, but not as direct Kotlin value classes as of 6.1.0-M5.
It looks like I can reproduce on both 6.0 and 6.1, so I don't think that's a regression, while your description seems to imply it unless I misunderstood. Could you please clarify that point?
Comment From: ianbrandt
Hi @sdeleuze, Thank you for looking into this. I meant this as a feature request, and did not mean to imply it was a regression. Better wording on my part might have been, "...but not as direct Kotlin value classes in 6.0.12 or 6.1.0-M5."
Comment From: sdeleuze
I have mixed feelings about introducing Kotlin specific logic for that use case because conceptually with @JvmInline
you are asking not difference at JVM bytecode level. That may change with Project Valhalla, and then Spring could potentially support this use case since it could be visible at JVM bytecode level, see related design notes here.
Could you please share more details about your use case, and share your feedback after reading the Keep design notes?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.