Hi Mike,
Here is my first attempt to explain possible cause for this behavior in SJC. As per the first test, bootstrapping JavaConfig from XML with ConfigurationPostProcessor works just fine, including the ability to access beans across contexts. The converse (bootstrapping XML from JavaConfig) is not possible as there is no mechanism to do this in SJC as per my understanding with the second test.
You should be able to find beans defined in JavaConfig which refers beans defined in XML, as long as the context has the XML configuration as shown in both tests.
Code:
public class TestJavaXmlBeans {
@Test
public void testGetBeansFromXmlParentAndJavaChild() throws Exception {
ClassPathXmlApplicationContext parent = new ClassPathXmlApplicationContext("beansFromXmlAndJava.xml", getClass());
FullTime fulltime = (FullTime) parent.getBean("fulltime");//bean defined in parent context (XML)
assertEquals(75000, fulltime.getWage());
Contract contract = (Contract) parent.getBean("contract");//bean defined in parent context (XML)
assertEquals(102000, contract.getWage());
JavaConfigApplicationContext child = new JavaConfigApplicationContext(parent, HrConfig.class);
fulltime = (FullTime) child.getBean("fulltime");//bean defined in child context (Java)
assertEquals(90000, fulltime.getWage());
contract = (Contract) child.getBean("contract");//bean defined in parent context (XML)
assertEquals(102000, contract.getWage());
}
@Test
public void testGetBeansFromJavaParentAndXmlChild() throws Exception {
JavaConfigApplicationContext parent = new JavaConfigApplicationContext(HrConfig.class);
FullTime fulltime = (FullTime) parent.getBean("fulltime");//bean defined in parent context (Java)
assertEquals(90000, fulltime.getWage());
//No bean named 'contract' is defined in parent context. I think this is expected behavior because there in no XML in context.
// Contract contract = (Contract) parent.getBean("contract");
// assertEquals(102000, contract.getWage());
ApplicationContext child = new ClassPathXmlApplicationContext(new String[]{"beansFromXmlAndJava.xml"}, getClass(), parent);
fulltime = (FullTime) child.getBean("fulltime");//bean defined in child context (XML)
assertEquals(75000, fulltime.getWage());
Contract contract = (Contract) child.getBean("contract");//bean defined in child context (XML)
assertEquals(102000, contract.getWage());
}
@Configuration
public abstract static class HrConfig {
private long salary = 90000;
public void setSalary(long salary) {
this.salary = salary;
}
@Bean
public FullTime fulltime() {
FullTime employee = new FullTime();
employee.setSalary(salary);
return employee;
}
// Will be taken from XML
@ExternalBean
public abstract Contract contract();
}
static class FullTime implements Employee {
long salary;
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
public long getWage() {
return salary;
}
}
static class Contract implements Employee {
int hours;
long rate;
public int getHours() {
return hours;
}
public void setHours(int hours) {
this.hours = hours;
}
public long getRate() {
return rate;
}
public void setRate(long rate) {
this.rate = rate;
}
public long getWage() {
return hours * rate;
}
}
static interface Employee {
long getWage();
}
}
Here is beansFromXmlAndJava.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"
>
<beans>
<bean id="contract" class="TestJavaXmlBeans$Contract">
<property name="hours" value="2040"/>
<property name="rate" value="50"/>
</bean>
<bean class="org.springframework.config.java.process.ConfigurationPostProcessor"/>
<bean class="TestJavaXmlBeans$HrConfig">
<property name="salary" value="75000"/>
</bean>
</beans>
Let me know if I am missing your point.
-Arul