I was going through the spring IOC documentation and came across the following code snippet:
<bean name="messageBroker,mBroker,MyBroker" class="com.components.MessageBroker">
<property name="tokenBluePrint">
<ref parent="tokenService" />
</property>
</bean>
As per the documentation, parent attribute of "ref" tag is used to refer the parent bean factory of the current bean factory, but to set the parent of a bean factory.
I have tried following code snippet. But still, I get the error.
String[] xmlFies=new String[1];
xmlFies[0]="applicationContext.xml";
ClassPathXmlApplicationContext parentContext=new ClassPathXmlApplicationContext("tokenConfiguration.xml");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlFies);
context.setParent(parentContext);
context.getBeanFactory().setParentBeanFactory(parentContext.getBeanFactory());
context.close();
parentContext.close();
Error :
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'messageBroker' defined in class path resource [applicationContext.xml]: Can't resolve reference to bean 'tokenService' in parent factory: no parent factory available at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:360)
Am I missing something? Please have a look.
I believe the issue is that your child context is refreshing before the parent context is set.
Here are the relevant constructors from ClassPathXmlApplicationContext
:
// this is the constructor that 'context' is using, and refresh is defaulted to true
public ClassPathXmlApplicationContext(String... configLocations) throws BeansException {
this(configLocations, true, null);
}
// the constructor that both others are calling
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
// you don't want to refresh until your parent context is set
refresh();
}
}
// the constructor I think you should use, it will set the parent first and then refresh
public ClassPathXmlApplicationContext(String[] configLocations, ApplicationContext parent) throws BeansException {
this(configLocations, true, parent);
}
I would instead use the last constructor so that the parent context is set before refresh()
is called.
Like this:
String[] xmlFies=new String[1];
xmlFies[0]="applicationContext.xml";
ClassPathXmlApplicationContext parentContext = new ClassPathXmlApplicationContext("tokenConfiguration.xml");
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlFies, parentContext);
. . .