Skip to content
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

When using kotlin Collection then @Autowire Collection<SomeInterface> does not work correctly [SPR-15940] #20494

Open
spring-issuemaster opened this issue Sep 8, 2017 · 1 comment
Assignees
Milestone

Comments

@spring-issuemaster
Copy link
Collaborator

@spring-issuemaster spring-issuemaster commented Sep 8, 2017

Mario Zagar opened SPR-15940 and commented

Using:

  • spring-framework 5.0.0.RC3 (also tested wth 1.5.6.RELEASE, problem also present)
  • kotlin-stdlib 1.1.4-3

Following test fails when autowiring kotlin Collection @Autowired lateinit var beans : Collection.

When using java.util.Collection autowiring works as expected.

Not really sure if this is kotlin issue or spring issue.

Here's the test:

package spring.autowire.test

import org.assertj.core.api.Assertions
import org.junit.Test
import org.junit.runner.RunWith
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.test.context.ContextConfiguration
import org.springframework.test.context.junit4.SpringRunner

interface FirstInterface
interface SecondInterface
interface ThirdInterface

class Bean1 : FirstInterface, SecondInterface, ThirdInterface
class Bean2 : FirstInterface, SecondInterface, ThirdInterface
class Bean3 : FirstInterface, SecondInterface, ThirdInterface
class Bean4 : FirstInterface, SecondInterface, ThirdInterface

@Configuration
open class TestSpringConfig {
    @Bean open fun bean1() : Bean1 = Bean1()
    @Bean open fun bean2() : FirstInterface = Bean2()
    @Bean open fun bean3() : SecondInterface = Bean3();
    @Bean open fun bean4() : ThirdInterface = Bean4();
}

@RunWith(SpringRunner::class)
@ContextConfiguration(classes = arrayOf(TestSpringConfig::class))
class KotlinAutowireTest {
    @Autowired
    lateinit var beans : Collection<SecondInterface> // test passes if I use java.util.Collection<SecondInterface>

    @Test
    fun test() {
        Assertions.assertThat(beans)
                .extracting{it.javaClass.name}
                .containsOnly(
                        "spring.autowire.test.Bean1",
                        "spring.autowire.test.Bean2",
                        "spring.autowire.test.Bean3",
                        "spring.autowire.test.Bean4"
                )
    }
}

Test output:

java.lang.AssertionError: 
Expecting:
  <["spring.autowire.test.Bean1", "spring.autowire.test.Bean3"]>
to contain only:
  <["spring.autowire.test.Bean1",
    "spring.autowire.test.Bean2",
    "spring.autowire.test.Bean3",
    "spring.autowire.test.Bean4"]>
but could not find the following elements:
  <["spring.autowire.test.Bean2", "spring.autowire.test.Bean4"]>

Affects: 5.0 RC3

1 votes, 3 watchers

@spring-issuemaster

This comment has been minimized.

Copy link
Collaborator Author

@spring-issuemaster spring-issuemaster commented Sep 11, 2017

Sébastien Deleuze commented

I had a look to this repro test and found that MutableCollection is working as expected while indeed Collection (the Kotlin one) ones returns 2 beans. After comparing both cases, I found that the difference of behavior comes from GenericTypeAwareAutowireCandidateResolver#checkGenericTypeMatch which could behave differently because of Kotlin declaration-site variance:

  • Collection is declared as interface Collection<out E>
  • MutableCollection is declared as interface MutableCollection<E>

Juergen Hoeller I have added a unit test in this branch to compare Kotlin MutableCollection and Collection, do you have any thoughts about this behavior being related to our generics comparison algorythm having to be tuned to support Kotlin declaration-site variance or if the issue could be on Kotlin side?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can’t perform that action at this time.