Reputation: 209
The cool enterprise app I'm working on is in the process of going Spring. That's very cool and exciting exercise to all the team, but also a huge source of stress. What we do is we gradually move legacy components to Spring context. Now what we have is a huuuge, I mean it, huuuuge component that is not piece of cake to spring-ify, and at the same time it needs to get access to some of the Spring beans.
Now here comes the problem: this component is being loaded at application startup (or bootstrap, whatever you prefer!). That means that there is a race condition between this guy and a Spring itself, so sometimes when I access the context from within that non-spring monstrosity, I get sweet and nice NPE. Which basically means that at the time we need that context, it's not yet initialized!
You might be curious how exactly we're accessing the context: and the answer is - it's a standard AppContextProvider pattern.
public class ApplicationContextProvider implements ApplicationContextAware {
private static ApplicationContext ctx;
public void setApplicationContext(ApplicationContext applicationContext) {
ctx = applicationContext;
}
public static ApplicationContext getApplicationContext() {
return ctx;
}
}
The ideal workaround for me in this case would be to tell Spring to notify that non-spring component "Okay, I'm up!", and perform all actions that require the context only after that. Is this actually possible?
Thanks in advance!
Upvotes: 3
Views: 2588
Reputation: 242726
Take a look at the mechanism of context events.
Perhaps you can block getApplicationConext()
until receiving of ContextRefreshedEvent
(if it wouldn't create deadlocks):
public class ApplicationContextProvider implements ApplicationListener<ContextRefreshedEvent> {
private static ApplicationContext ctx;
private static Object lock = new Object();
public void onApplicationEvent(ContextRefreshedEvent e) {
synchronized (lock) {
ctx = e.getApplicationContext();
lock.notifyAll();
}
}
public static ApplicationContext getApplicationContext() {
synchronized (lock) {
while (ctx == null) lock.wait();
return ctx;
}
}
}
Upvotes: 1
Reputation: 21000
The correct way to make the application context available to non-spring beans is to use the ContextSingletonBeanFactoryLocator.
Take a look at this answer for more details.
Upvotes: 2