2 Replies Latest reply on Nov 3, 2009 4:14 PM by kabirkhan

    Dependency on non-existant bean when trying to create

    kabirkhan

      What'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));
      




        • 1. Re: Dependency on non-existant bean when trying to create
          alesj

          Yes, this is somehow expected.

          PropertyMD --> ValueMD --> BeanMD --> inner bean --> dependency

          AbstractValueMD::getChildren doesn't distinguish between plain properly value and metadata value.

          Normally MC metadata should be hidden for POJOs,
          so I wouldn't put too much effort into this --> would go with a wrapper.

          Perhaps you can add this to BMDBuilder:

          <T> T wrap(T impl, Class<T> clazz)
          {
           return new MetaDataWrapper<T>(impl, clazz);
          }
          
          public class MetaDataWrapper<T>
          {
           T impl;
           Class<T> clazz;
          
           public MetaDataWrapper(T impl, Class<T> clazz) { ... }
          
           public T unwrap() { return impl; }
          }
          

          which hides the actual metadata in generic way.


          • 2. Re: Dependency on non-existant bean when trying to create
            kabirkhan

            And users would have which setter in their bean?

            This

            void setMetaData(MetaDataWrapper<BeanMetaData> data){}
            


            or this, which would require mc to be more clever?
            void setMetaData(BeanMetaData data){}