Skip to content

Unable to Proxy with Kotlin DSL #35985

@olgunkaya

Description

@olgunkaya

Hi all,

Not sure if this is a question or a known issue that I am hitting. (already asked in SO but no real answers arrived yet)

I have some beans defined/registered in an ApplicationContextInitializr via BeanDefinitionDsl

abstract class AbstractConfig: ApplicationContextInitializer<GenericApplicationContext> {
    ...
    abstract val config: BeanDefinitionDsl
    ...

    final override fun initialize(applicationContext: GenericApplicationContext) {
        ...
        config.initialize(applicationContext)
        ...
    }
}

class UserSignInConfig : AbstractConfig() {
    ...
    bean(name = "googleUserSignIn") {
            IndividualUserSignIn(
                ref("googleUserSignInService"),
                ref("userHibernateDAO"),
                ref("socialAccountHibernateDAO"),
                ref("userService"),
                ...
            )
        }

    bean(name = "appleUserSignIn") {
            IndividualUserSignIn(
                ref("appleUserSignInService"),
                ref("userHibernateDAO"),
                ref("socialAccountHibernateDAO"),
                ref("userService"),
                ...
            )
        }
    
    bean<UserSignInFactory>()
}
    

The implementation of these classes are look like below; first the AbstractStrategy

abstract class AbstractUserSignIn(
    private val userSignInService: UserSignInService,
    private val userDAO: UserDAO,
    private val socialAccountDAO: SocialAccountDAO,
    private val userService: UserService,
    ....
   ) {

    @Transactional
    open fun signIn(userSignInRequest: SignInRequest): SignInResult {...}
    
    fun getSignInStrategy(): UserSignInStrategy{ // **(A)**
       return userSignInService.getSignInStrategy()
    }
}

Then the classes inherited from this class;

open class IndividualUserSignIn constructor(
    userSignInService: UserSignInService,
    userDAO: UserDAO,
    socialAccountDAO: SocialAccountDAO,
    userService: UserService,
    ...
   ) : AbstractUserSignIn(
    userSignInService,
    userDAO,
    socialAccountDAO,
    userService,
    ...
    ) {

    @PostConstruct
    private fun init()
    {
        println("strategy :" + getSignInStrategy()) // **(B)**
    }
...
}

And the factory class

@Component
open class UserSignInFactory @Autowired constructor(private val userSignInServices: Set<IndividualUserSignIn>) {

    @PostConstruct
    private fun createStrategies() {
        userSignInServices.forEach { strategy ->
            strategyMap[strategy.getSignInStrategy()] = strategy // **(C)**
        }
    }
    ....
    companion object {
        private val strategyMap: EnumMap<UserSignInStrategy, AbstractUserSignIn> = EnumMap(UserSignInStrategy::class.java)
    }
}

Point (A) is where the problem arising. Abstract class uses the injected service to let callers know about it's supporting implementation.

Well here the problem is.

At the point (B); While the concrete strategies are being instantiated, the @PostConstruct works as expected and prints the supported strategy. Debugging says this is the instance itself of strategy.

At the point (C); While traversing the Set, I am receiving a NPE because the injected service that is used in point (A) looks null. In here the elements in the set, are instances of spring generated proxies pointing to instances from step #1 above.

Metadata

Metadata

Assignees

No one assigned

    Labels

    for: stackoverflowA question that's better suited to stackoverflow.comstatus: invalidAn issue that we don't feel is valid

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions