Dependency on non-existant bean when trying to create
kabirkhan Nov 3, 2009 1:11 PMWhat's wrong with this? Attempting to add the intermediate bean mentioned in http://www.jboss.org/index.html?module=bb&op=viewtopic&t=162791. I found that adding BeanMetaData as a property to a bean seems to cause an unresolved dependency:
public class ThrowawayTestCase extends MicrocontainerTest { public ThrowawayTestCase(String name) { super(name); } public void testIndirectBean() throws Throwable { BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder("Bean", MyBean.class.getName()); BeanMetaData bmd = builder.getBeanMetaData(); builder = BeanMetaDataBuilder.createBuilder("BeanInstaller", MyBeanInstaller.class.getName()); // builder.addPropertyMetaData("context", builder.createFromContextInject(FromContext.CONTEXT)); //1 builder.addPropertyMetaData("beanMetaData", builder.createValue(bmd)); //2 KernelControllerContext ctx = deploy(builder.getBeanMetaData()); try { System.out.println("----------> " + ctx.getDependencyInfo().getIDependOn(null)); MyBeanInstaller myBeanInstaller = assertBean("BeanInstaller", MyBeanInstaller.class); // MyBean myBean = assertBean("MyBean", MyBean.class); // assertNotNull(myBean); } finally { undeploy(ctx); } } public static class MyBeanInstaller { KernelControllerContext context; BeanMetaData beanMetaData; boolean started; public BeanMetaData getBeanMetaData() { return beanMetaData; } public void setBeanMetaData(BeanMetaData beanMetaData) { this.beanMetaData = beanMetaData; } public KernelControllerContext getContext() { return context; } public void setContext(KernelControllerContext context) { this.context = context; } public boolean isStarted() { return started; } public void start() throws Exception { //Use context.getController() and beanmetadata to install indirect bean } } public static class MyBean { } }
The output dependency info is shown as:
----------> [AbstractDependencyItem@5f49d886{name=BeanInstaller dependsOn=Bean whenRequired=Configured dependentState=Installed resolved=false}]
Looking at the stack trace of AbstractDependencyItem's constructor it looks like the property value gets visited as well?
Thread [main] (Suspended (breakpoint at line 78 in AbstractDependencyItem)) AbstractDependencyItem.<init>(Object, Object, ControllerState, ControllerState) line: 78 AbstractBeanMetaData.initialVisit(MetaDataVisitor) line: 669 PreprocessMetaDataVisitor(AbstractMetaDataVisitor).internalInitialVisit(MetaDataVisitorNode) line: 111 PreprocessMetaDataVisitor(AbstractMetaDataVisitor).initialVisit(MetaDataVisitorNode) line: 74 AbstractValueMetaData.initialVisit(MetaDataVisitor) line: 116 PreprocessMetaDataVisitor(AbstractMetaDataVisitor).internalInitialVisit(MetaDataVisitorNode) line: 111 PreprocessMetaDataVisitor(AbstractMetaDataVisitor).initialVisit(MetaDataVisitorNode) line: 74 AbstractPropertyMetaData(AbstractFeatureMetaData).initialVisit(MetaDataVisitor) line: 101 AbstractPropertyMetaData.initialVisit(MetaDataVisitor) line: 287 PreprocessMetaDataVisitor(AbstractMetaDataVisitor).internalInitialVisit(MetaDataVisitorNode) line: 111 PreprocessMetaDataVisitor(AbstractMetaDataVisitor).initialVisit(MetaDataVisitorNode) line: 74 AbstractBeanMetaData(AbstractFeatureMetaData).initialVisit(MetaDataVisitor) line: 101 AbstractBeanMetaData.initialVisit(MetaDataVisitor) line: 680 PreprocessMetaDataVisitor.run() line: 53 AccessController.doPrivileged(PrivilegedAction<T>) line: not available [native method] AbstractKernelControllerContext.preprocessMetaData() line: 232 AbstractKernelControllerContext.setController(Controller) line: 198 AbstractKernelController(AbstractController).install(ControllerContext, boolean) line: 778 AbstractKernelController(AbstractController).install(ControllerContext) line: 564 AbstractKernelController.install(BeanMetaData, Object) line: 107 AbstractKernelController.install(BeanMetaData) line: 101 MicrocontainerTestDelegate.deploy(BeanMetaData) line: 329 ThrowawayTestCase(MicrocontainerTest).deploy(BeanMetaData) line: 358 ThrowawayTestCase.testIndirectBean() line: 54
I'm not sure this is something we should fix, without a better understanding of how the value metadata is visited. I can work around it by creating an intermediate class
public static class BeanMetaDataWrapper { private final BeanMetaData beanMetaData; public BeanMetaDataWrapper(BeanMetaData beanMetaData) { this.beanMetaData = beanMetaData; } public BeanMetaData getBeanMetaData() { return beanMetaData; } }
and to set that instead when creating BeanInstaller
builder.addPropertyMetaData("beanMetaDataWrapper", builder.createValue(wrapper));