I am trying to get access to the beans instantiated in my Spring Boot ApplicationContext from within static code for Java service provider (META-INF/services). I am using Java 14 (openjdk:14-jdk-slim).
In the remote debugger session, I can see that the static variable for the application context CONTEXT
is getting set to the right value:
@Component
@Slf4j
public class ApplicationContextListener implements ApplicationContextAware {
private static volatile ApplicationContext CONTEXT;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
CONTEXT = applicationContext;
}
...
Next time it is getting accessed at runtime later (from another thread), the variable CONTEXT
is null, e.g. here:
public static MyBean getMyBean() {
return CONTEXT.getBean(MyBean.class);
}
I suspect that the problem is that the class holding the static variable gets "unloaded" in between. But 1) why would that happen to a class defining a valid bean in the application context 2) how can I avoid that?
What can be the reason for the static variable to become null later during the application execution? There is no code setting the variable except for the one listed above. The setApplicationContext
is only gets invoked once.
If the issue is related to the class unloading, how can I avoid that?
Maybe my initialization code is executed against static variable in a class loaded by classloader A and access is taking place to the not initialized static variable in the same class loaded by the classlaoder B? Assuming this is the reason, how could I fix this problem?
Thank you!
Update
The classloader of the class ApplicationContextListener
instance when in the method setApplicationContext
is org.springframework.boot.devtools.restart.classloader.RestartClassLoader
as returned by this.getClass().getClassLoader()
.
When the debugger stops later in the ApplicationContextListener
class static methods the debugger shows ClassLoaders$AppClassLoader
for the ApplicationContextListener.class.getClassLoader()
The Thread.currentThread().getContextClassLoader()
in the latter case (in static get) shows org.springframework.boot.devtools.restart.classloader.RestartClassLoader
too.