/**
* Licensed to Apereo under one or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information regarding copyright ownership. Apereo
* licenses this file to you under the Apache 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 the
* following location:
*
* <p>http://www.apache.org/licenses/LICENSE-2.0
*
* <p>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.apereo.portal.spring.beans.factory;
import java.util.List;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.util.Assert;
/**
* Takes a list of bean names and attempts to load each in order. If the loading of a bean throws an
* Exception it is logged and the next bean name in the list is tried. If no beans can be loaded a
* {@link BeanCreationException} is thrown.
*/
public class MediatingFactoryBean<T> extends AbstractFactoryBean<T> implements BeanFactoryAware {
private List<String> delegateBeanNames;
private Class<T> type = null;
/** @return the delegateBeanNames */
public List<String> getDelegateBeanNames() {
return this.delegateBeanNames;
}
/** @param delegateBeanNames the delegateBeanNames to set */
public void setDelegateBeanNames(List<String> delegateBeanNames) {
this.delegateBeanNames = delegateBeanNames;
}
/** @return the type */
public Class<T> getType() {
return this.type;
}
/** @param type the type to set */
public void setType(Class<T> type) {
this.type = type;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.AbstractFactoryBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
Assert.notEmpty(this.delegateBeanNames, "delegateBeanNames list cannot be empty");
super.afterPropertiesSet();
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
*/
@Override
protected T createInstance() throws Exception {
for (final String beanName : this.delegateBeanNames) {
try {
final T bean;
if (this.type == null) {
bean = (T) this.getBeanFactory().getBean(beanName);
} else {
bean = this.getBeanFactory().getBean(beanName, this.type);
}
if (this.logger.isInfoEnabled()) {
this.logger.info("Loaded bean for name " + beanName);
}
return bean;
} catch (final Exception e) {
final String msg =
"Failed to load bean '"
+ beanName
+ "' from ApplicationContext"
+ (this.type != null ? " expecting type: " + this.type : "")
+ ". Will try to load the next bean in the list instead. Error message from the attempt to load this bean ('"
+ beanName
+ "'): ";
if (this.logger.isDebugEnabled()) {
this.logger.debug(msg, e);
} else if (this.logger.isInfoEnabled()) {
this.logger.info(
msg + " " + e.getMessage() + " (enable debug for stack trace)");
}
}
}
throw new BeanCreationException(
"None of the configured bean names could be loaded. BeanNames: "
+ this.delegateBeanNames);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType()
*/
@Override
public Class<?> getObjectType() {
return this.type;
}
}