1 Reply Latest reply on Oct 8, 2007 7:00 PM by Ales Justin

    Lazy bean behaviour

    Ales Justin Master

      I'm doing (apart from AS5_PS ... no worries ;-)) some GUI example console for MC and was missing the following feature - lazy 'instantiation/install' of the bean.

      e.g. I have some service that has many dependencies - many injected beans. One of them is rarely used and/or is fully installed in some later-on deployment unit. But I would still like to have that first service up and running.

      So, I hacked a lazy notion to our beans - lazy proxies.

      What you can do now is the following XML

       <bean name="bean" class="org.jboss.test.kernel.lazy.support.RareBean"/>
      
       <lazy name="proxy" bean="bean" exposeClass="true">
       <interface>org.jboss.test.kernel.lazy.support.IRare</interface>
       </lazy>
      


      or the straight API

       AbstractLazyMetaData lazy = new AbstractLazyMetaData("bean");
       lazy.setInterfaces(Collections.singleton(IRare.class.getName()));
      


      And the test to show that lazyness :-)
       AbstractBeanMetaData bean = new AbstractBeanMetaData("bean", RareBean.class.getName());
       bean.setMode(ControllerMode.MANUAL);
      
       KernelControllerContext beanContext = controller.install(bean);
       controller.change(beanContext, ControllerState.NOT_INSTALLED);
      
       ModifiedLazyMetaData lazy = new ModifiedLazyMetaData("bean", getFactoryClassName());
       lazy.setInterfaces(Collections.singleton(IRare.class.getName()));
       KernelControllerContext lazyContext = controller.install(lazy);
      
       assertNotNull(lazyContext);
       assertEquals(ControllerState.DESCRIBED, lazyContext.getState());
      
       controller.change(beanContext, ControllerState.DESCRIBED);
       controller.change(lazyContext, ControllerState.INSTALLED);
      
       IRare lazyRare = (IRare)lazyContext.getTarget();
       assertNotNull(lazyRare);
      
       try
       {
       lazyRare.getHits();
       throw new RuntimeException("Should not be here.");
       }
       catch(Throwable t)
       {
       assertInstanceOf(t, IllegalArgumentException.class);
       }
      
       controller.change(beanContext, ControllerState.INSTALLED);
      
       assertEquals(0, lazyRare.getHits());
       lazyRare.setHits(10);
       assertEquals(5, lazyRare.checkHits(15));
      


      The code checks for the first available proxy generator - Javassist, JBossAOP (wip), JDK, ... (possible additions CGLIB, ASM, ...)
       static
       {
       initializerMap = new LinkedHashMap<String, String>();
       // test class name, actual LazyInitializer implementation
       initializerMap.put("javassist.util.proxy.ProxyObject", "org.jboss.kernel.plugins.lazy.JavassistLazyInitializer");
       initializerMap.put("org.jboss.aop.proxy.container.AOPProxyFactoryParameters", "org.jboss.aop.microcontainer.lazy.JBossAOPLazyInitializer");
       initializerMap.put("java.lang.reflect.Proxy", "org.jboss.kernel.plugins.lazy.JDKLazyInitializer");
       }
      
       /**
       * Get the LazyInitializater instance.
       *
       * @param configurator the configurator
       * @return initializer instance
       */
       protected static LazyInitializer getInitializer(KernelConfigurator configurator)
       {
       if (initializer == null)
       {
       for(Map.Entry<String, String> entry : initializerMap.entrySet())
       {
       if (testLibExists(entry.getKey()))
       {
       initializer = createInitializer(configurator, entry.getValue());
       if (initializer != null)
       break;
       }
       }
       }
       if (initializer == null)
       throw new IllegalArgumentException("Cannot initialize LazyInitializater, check classpath for missing classes.");
       return initializer;
       }
      


      The proxies use KernelBus to do the invocation.

      Currently you need to specify which interfaces are exposed.
      Perhaps this can be done automa(g|t)ically?