-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Description
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.