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.
Comment From: wilkinsona
Judging by the comments on your SO question, someone is already trying to help you. You have also added a bounty to the question, encouraging more people to do so. Cross-posting here will just waste their time so I am going to close this. To make it easier for people to help you on Stack Overflow, you may want to try providing a link to a complete yet minimal example so that they don't have to copy-paste the snippets and piece things back together again.