Skip to content

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

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

Closed
ianbrandt opened this issue Oct 6, 2023 · 6 comments
Closed

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

ianbrandt opened this issue Oct 6, 2023 · 6 comments
Assignees
Labels
theme: kotlin An issue related to Kotlin support

Comments

@ianbrandt
Copy link
Contributor

ianbrandt commented Oct 6, 2023

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.

@ianbrandt
Copy link
Contributor Author

@sdeleuze sdeleuze added the theme: kotlin An issue related to Kotlin support label Oct 8, 2023
@sdeleuze sdeleuze self-assigned this Oct 8, 2023
@sdeleuze
Copy link
Contributor

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?

@sdeleuze sdeleuze added status: feedback-provided Feedback has been provided status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Oct 11, 2023
@ianbrandt
Copy link
Contributor Author

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."

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Oct 11, 2023
ianbrandt added a commit to sdkotlin/sd-kotlin-spring-talks that referenced this issue Oct 15, 2023
@sdeleuze
Copy link
Contributor

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?

@sdeleuze sdeleuze added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Oct 17, 2023
@spring-projects-issues
Copy link
Collaborator

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.

@spring-projects-issues spring-projects-issues added the status: feedback-reminder We've sent a reminder that we need additional information before we can continue label Oct 24, 2023
@spring-projects-issues
Copy link
Collaborator

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.

@spring-projects-issues spring-projects-issues closed this as not planned Won't fix, can't repro, duplicate, stale Oct 31, 2023
@spring-projects-issues spring-projects-issues removed status: waiting-for-feedback We need additional information before we can continue status: feedback-reminder We've sent a reminder that we need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged or decided on labels Oct 31, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
theme: kotlin An issue related to Kotlin support
Projects
None yet
Development

No branches or pull requests

3 participants