Skip to content

Add support for Kotlin inline/value classes as beans #31372

Closed as not planned
Closed as not planned
@ianbrandt

Description

@ianbrandt

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.

Metadata

Metadata

Assignees

Labels

theme: kotlinAn issue related to Kotlin support

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions