/**********************************************************************************
*
* $Id: NoisierDefaultListableBeanFactory.java 105077 2012-02-24 22:54:29Z ottenhoff@longsight.com $
*
***********************************************************************************
*
* Copyright (c) 2007, 2008 Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.util;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;
/**
* In Spring 1.2.6 and 1.2.8, when there's a problem pre-instantiating any
* singleton bean, all existing singleton beans are immediately destroyed.
* Unfortunately for developers, this destruction occurs without any
* explanation: neither the problematic bean's name nor the error stack is
* logged.
*
* This subclasses the default bean factory to log the failing bean's name and a
* stack trace of the exception.
*/
public class NoisierDefaultListableBeanFactory extends
DefaultListableBeanFactory {
public static boolean noisyClose = true;
public void preInstantiateSingletons() throws BeansException {
if (logger.isDebugEnabled()) {
logger.debug("Pre-instantiating singletons in factory [" + this
+ "]");
}
// The superclass's variable by this name is declared private.
String[] beanDefinitionNames = getBeanDefinitionNames();
String beanName = null; // Remember in case of an exception
try {
// for (Iterator it = this.beanDefinitionNames.iterator();
// it.hasNext();) {
for (int i = 0; i < beanDefinitionNames.length; i++) {
beanName = beanDefinitionNames[i];
if (!containsSingleton(beanName)
&& containsBeanDefinition(beanName)) {
RootBeanDefinition bd = (RootBeanDefinition)getMergedBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton()
&& !bd.isLazyInit()) {
if (bd.hasBeanClass()
&& FactoryBean.class.isAssignableFrom(bd
.getBeanClass())) {
FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX
+ beanName);
if (factory.isSingleton()) {
getBean(beanName);
}
} else {
getBean(beanName);
}
}
}
}
} catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.
logger.error("Failed to preinstantiate the singleton named "
+ beanName + ". Destroying all Spring beans.", ex);
try {
destroySingletons();
} catch (Exception ex2) {
logger.error("Pre-instantiating singletons failed, and couldn't destroy already created singletons: "+ex2, ex2);
}
throw ex;
}
}
@Override
public void destroySingletons() {
if ( noisyClose ) {
Exception e = new Exception("traceback");
e.printStackTrace();
}
super.destroySingletons();
}
@Override
protected void afterSingletonCreation(String beanName) {
if (logger.isDebugEnabled()) {
logger.debug("Finished Creating " + beanName);
}
super.afterSingletonCreation(beanName);
}
@Override
public Object getBean(String name, Class requiredType, Object[] args)
throws BeansException {
if (!logger.isDebugEnabled()) {
return super.getBean(name, requiredType, args);
} else {
logger.debug("Getting Name " + name);
try {
return super.getBean(name, requiredType, args);
} catch (BeansException e) {
logger.error("Failed to get bean ", e);
throw e;
} finally {
logger.debug("End getting " + name);
}
}
}
}