How to reliably determine if BeanMetaData contains dependenc
kabirkhan Feb 4, 2009 12:26 PMI need a way to reliably determine if a BeanMetaData contains dependencies. aop-mc-int tests in trunk for aspects with dependencies are failing due to my way of determining this no longer working there, and this in turn causes aop failures in AS Branch_5_0 with the latest mc jars.
The background is: when reading the aop.xml I create different underlying beans in
https://svn.jboss.org/repos/jbossas/projects/microcontainer/trunk/aop-mc-int/src/main/java/org/jboss/aop/microcontainer/beans/metadata/AspectBeanMetaDataFactory.java
depending on if the bean has dependencies
<aop xmlns="urn:jboss:aop-beans:1.0"> <aspect class="org.jboss.test.microcontainer.beans.TestAspectWithDependency"> <property name="dependency"><inject bean="Dependency"/></property> </aspect> </aop>
or not
<aop xmlns="urn:jboss:aop-beans:1.0"> <aspect class="org.jboss.test.microcontainer.beans.TestAspect"> </aspect> </aop>
This gets parsed by AspectBMDFactory
@Override public List<BeanMetaData> getBeans() { ArrayList<BeanMetaData> result = new ArrayList<BeanMetaData>(); if (this.name == null) { this.name = super.getBean(); } //Add the bean factory if (!initialisedName) { aspectName = this.name; this.name = "Factory$" + name; initialisedName = true; } List<BeanMetaData> beans = super.getBeans(); if (beans.size() != 1) { throw new RuntimeException("Wrong number of beans" + beans); } BeanMetaData factory = beans.get(0); BeanMetaDataBuilder factoryBuilder = BeanMetaDataBuilder.createBuilder(factory); factoryBuilder.setBean(ClassLoaderAwareGenericBeanFactory.class.getName()); result.add(factory); //Add the Aspect BeanMetaDataBuilder aspectBuilder = BeanMetaDataBuilder.createBuilder(aspectName, Aspect.class.getName()); aspectBuilder.addPropertyMetaData("scope", scope); aspectBuilder.addPropertyMetaData("name", aspectName); HashMap<String, String> attributes = new HashMap<String, String>(); attributes.put("name", name); if (factory != null) { attributes.put("factory", this.factory); } else { attributes.put("class", bean); } attributes.put("scope", scope); if (elements != null && elements.size() > 0) { aspectBuilder.addPropertyMetaData("element", XmlLoadableRootElementUtil.getRootElementString(elements, getTagName(), attributes)); } setAspectManagerProperty(aspectBuilder); if (this.factory != null) { aspectBuilder.addPropertyMetaData("factory", Boolean.TRUE); } result.add(aspectBuilder.getBeanMetaData()); System.out.println(factory.getRelated()); if (hasInjectedBeans(factory)) { configureWithDependencies(factoryBuilder, aspectBuilder); } else { configureNoDependencies(aspectBuilder); } return result; }
The code I had, hasInjectedBeans(), to determine whether there are any dependencies for "factory" worked properly in MC Branch_2_0, but always returns false in trunk. I've added some modifications locally to inspect what it is doing
private boolean hasInjectedBeans(BeanMetaData beanMetaData) { ArrayList<ValueMetaData> dependencies = new ArrayList<ValueMetaData>(); System.out.println("======== Getting dependencies"); getDependencies(dependencies, beanMetaData, 0); for (ValueMetaData dep : dependencies) { if(!((String)dep.getUnderlyingValue()).startsWith("jboss.kernel:service=")) { return true; } } return false; } private void getDependencies(ArrayList<ValueMetaData> dependencies, MetaDataVisitorNode node, int i) { System.out.println(indent(i) + node); Iterator<? extends MetaDataVisitorNode> children = node.getChildren(); if (children != null) { while (children.hasNext()) { MetaDataVisitorNode child = children.next(); if (child instanceof AbstractDependencyValueMetaData) { System.out.println(indent(i+1) + "DEPENDENCY: " + child); dependencies.add((AbstractDependencyValueMetaData)child); } getDependencies(dependencies, child, i + 1); } } } private String indent(int l) { String s = "-"; for (int i = 0 ; i < l ; i++) { s = s + "-"; } return s; }
The output when parsing
<aop xmlns="urn:jboss:aop-beans:1.0"> <aspect class="org.jboss.test.microcontainer.beans.TestAspectWithDependency"> <property name="dependency"><inject bean="Dependency"/></property> </aspect> </aop>
in Branch_2_0
======== Getting dependencies -AbstractBeanMetaData@c59085{name=Factory$org.jboss.test.microcontainer.beans.TestAspectWithDependency bean=org.jboss.aop.microcontainer.bea ns.ClassLoaderAwareGenericBeanFactory properties=[bean, properties] constructor=AbstractConstructorMetaData@1d0462{parameters=[org.jboss.ker nel.spi.config.KernelConfigurator]} autowireCandidate=true related=[org.jboss.test.microcontainer.beans.TestAspectWithDependency]} --AbstractPropertyMetaData@908404{name=bean value=StringValueMetaData@6cf4f9{value=org.jboss.test.microcontainer.beans.TestAspectWithDepende ncy}} ---StringValueMetaData@6cf4f9{value=org.jboss.test.microcontainer.beans.TestAspectWithDependency} --AbstractPropertyMetaData@cc2f42{name=properties value=AbstractValueMetaData@470a37{value={dependency=AbstractInjectionValueMetaData@efbbb1 {value=Dependency injectionType=BY_CLASS}}}} ---AbstractValueMetaData@470a37{value={dependency=AbstractInjectionValueMetaData@efbbb1{value=Dependency injectionType=BY_CLASS}}} ----{dependency=AbstractInjectionValueMetaData@efbbb1{value=Dependency injectionType=BY_CLASS}} -----DEPENDENCY: AbstractInjectionValueMetaData@efbbb1{value=Dependency injectionType=BY_CLASS} -----AbstractInjectionValueMetaData@efbbb1{value=Dependency injectionType=BY_CLASS} --AbstractConstructorMetaData@1d0462{parameters=[org.jboss.kernel.spi.config.KernelConfigurator]} ---AbstractParameterMetaData@b73e5{type=org.jboss.kernel.spi.config.KernelConfigurator value=AbstractDependencyValueMetaData@e5e871{value=jb oss.kernel:service=KernelConfigurator}} ----DEPENDENCY: AbstractDependencyValueMetaData@e5e871{value=jboss.kernel:service=KernelConfigurator} ----AbstractDependencyValueMetaData@e5e871{value=jboss.kernel:service=KernelConfigurator} --AbstractRelatedClassMetaData@ff6313{name=org.jboss.test.microcontainer.beans.TestAspectWithDependency, enabled=null}
You can see it properly picks out the bean called "Dependency". In trunk it does not work due to a new structure of the bean metadata
======== Getting dependencies -AbstractBeanMetaData@88f1c5{name=Factory$org.jboss.test.microcontainer.beans.TestAspectWithDependency bean=org.jboss.aop.microcontainer.bea ns.ClassLoaderAwareGenericBeanFactory properties=[properties, bean] constructor=AbstractConstructorMetaData@3291db{parameters=[org.jboss.ker nel.spi.config.KernelConfigurator]} autowireCandidate=true related=[org.jboss.test.microcontainer.beans.TestAspectWithDependency]} --AbstractPropertyMetaData@33b5db{name=properties value=AbstractValueMetaData@ad2911{value={dependency=PropertyMap$ValueInfo@6339b2{}}}} ---AbstractValueMetaData@ad2911{value={dependency=PropertyMap$ValueInfo@6339b2{}}} ----{dependency=PropertyMap$ValueInfo@6339b2{}} -----PropertyMap$ValueInfo@6339b2{} --AbstractPropertyMetaData@363bce{name=bean value=StringValueMetaData@61091e{value=org.jboss.test.microcontainer.beans.TestAspectWithDepende ncy}} ---StringValueMetaData@61091e{value=org.jboss.test.microcontainer.beans.TestAspectWithDependency} --AbstractConstructorMetaData@3291db{parameters=[org.jboss.kernel.spi.config.KernelConfigurator]} ---AbstractParameterMetaData@9dbc5c{type=org.jboss.kernel.spi.config.KernelConfigurator value=AbstractDependencyValueMetaData@b967ed{value=j boss.kernel:service=KernelConfigurator}} ----DEPENDENCY: AbstractDependencyValueMetaData@b967ed{value=jboss.kernel:service=KernelConfigurator} ----AbstractDependencyValueMetaData@b967ed{value=jboss.kernel:service=KernelConfigurator} --AbstractRelatedClassMetaData@562d4b{name=org.jboss.test.microcontainer.beans.TestAspectWithDependency, enabled=null}
That will teach me not to rely on implementation details...