-
Notifications
You must be signed in to change notification settings - Fork 38.8k
Description
Archie Cobbs opened SPR-10000 and commented
My application had a bug causing an exception to be thrown during construction of a bean.
This caused the application context refresh operation to be aborted. However, in the process of aborting the refresh, an additional exception was thrown by AbstractApplicationContext.getLifecycleProcessor().
This second exception got logged to the error log, but the first exception never did.
As a result, it was very difficult to debug what the actual problem was.
The error logs, including the second exception that did get logged, are here (edited for brevity):
2012-11-15 17:27:29,067 [localhost-startStop-1] INFO : Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7dbafc22: defining beans [...]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@5697c78b
2012-11-15 17:27:29,551 [localhost-startStop-1] INFO : Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@7dbafc22: defining beans [...]; parent: org.springframework.beans.factory.support.DefaultListableBeanFactory@5697c78b
2012-11-15 17:27:29,595 [localhost-startStop-1] INFO : Closing Root WebApplicationContext: startup date [Thu Nov 15 17:27:08 CST 2012]; root of context hierarchy
2012-11-15 17:27:29,607 [localhost-startStop-1] WARN : Exception thrown from LifecycleProcessor on context close
java.lang.IllegalStateException: LifecycleProcessor not initialized - call 'refresh' before invoking lifecycle methods via the context: Root WebApplicationContext: startup date [Thu Nov 15 17:27:08 CST 2012]; root of context hierarchy
at org.springframework.context.support.AbstractApplicationContext.getLifecycleProcessor(AbstractApplicationContext.java:350)
at org.springframework.context.support.AbstractApplicationContext.doClose(AbstractApplicationContext.java:1038)
at org.springframework.context.support.AbstractApplicationContext.close(AbstractApplicationContext.java:993)
at org.springframework.context.support.AbstractApplicationContext.destroy(AbstractApplicationContext.java:981)
at org.springframework.beans.factory.support.DisposableBeanAdapter.destroy(DisposableBeanAdapter.java:211)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:498)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:474)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroyBean(DefaultSingletonBeanRegistry.java:509)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.destroySingleton(DefaultSingletonBeanRegistry.java:474)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:300)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:609)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:918)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:469)
at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:383)
at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:283)
at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791)
at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:618)
at org.apache.catalina.startup.HostConfig.deployDirectory(HostConfig.java:1100)
at org.apache.catalina.startup.HostConfig$DeployDirectory.run(HostConfig.java:1618)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:722)
It appears that the following snippet of code in AbstractBeanFactory (visible in the above stack trace) may be contributing to the problem (but I haven't verified that for sure). Note how the second exception occurs during the call to destroySingleton().
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
Possibly relevant: I have a slightly unusual setup where an outer application context contains a bean which is itself an inner application context:
<bean id="updatesContext" class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-arg>
<util:list>
<value>classpath:updates.xml</value>
</util:list>
</constructor-arg>
<constructor-arg>
<value>false</value>
</constructor-arg>
<constructor-arg>
<bean factory-bean="applicationContextBean" factory-method="getApplicationContext"/>
</constructor-arg>
</bean>
The applicationContextBean is a bean that exposes the containing application context. It is set as the parent of the nested context. Note the refresh constructor parameter is false, so the inner application context is not refreshed until afterPropertiesSet().
Bottom line: ideally, secondary exceptions should never occur; but if they do, they should never prevent a primary exception from being logged.
Affects: 3.1.2
Attachments:
- SPR-10000.tgz (12.27 kB)
Issue Links:
- Exceptions thrown during AbstractApplicationContext.refresh() not being logged right when they are caught [SPR-12010] #16626 Exceptions thrown during AbstractApplicationContext.refresh() not being logged right when they are caught
Backported to: 3.2.11