1 Reply Latest reply on Jan 11, 2010 6:52 PM by Adrian Brock

    VDF doesn't do component composition

    Carlo de Wolf Master

      I've created the new naming deployer to setup the application name spaces (https://jira.jboss.org/jira/browse/RELOADED-12), but to have a container be composed of a component I had to install it in another component.



         protected void internalDeploy(DeploymentUnit unit) throws DeploymentException
            String appName = informer.getApplicationName(unit);
            String moduleName = informer.getModulePath(unit);
            String name = informer.getComponentName(unit);
            // create JavaEEModule bean
            BeanMetaDataBuilder builder = BeanMetaDataBuilderFactory.createBuilder("java:comp", MCJavaEEComponent.class.getName())
               .addAnnotation(annotation(DeploymentScope.class, moduleName))
               .addAnnotation(annotation(InstanceScope.class, name))
               .addConstructorParameter(String.class.getName(), name);
            if(appName != null)
               builder.addAnnotation(annotation(ApplicationScope.class, appName));
            AbstractInjectionValueMetaData javaModule = new AbstractInjectionValueMetaData("java:module");
            javaModule.setSearch(new ParentsLookupStrategy());
            builder.addConstructorParameter(JavaEEModule.class.getName(), javaModule);
            builder.addPropertyMetaData("nameSpaces", builder.createInject("NameSpaces"));      
            // VDF can't do component composition, so each BMD must be in a separate component
            DeploymentUnit component = unit.getParent().addComponent(name + ".java:comp");
            component.addAttachment(BeanMetaData.class, builder.getBeanMetaData());


      This strikes me a deficiency within VDF, because in every programming paradigm can a component be a composition.

        • 1. Re: VDF doesn't do component composition
          Adrian Brock Master

          You've missed one of design assumptions of components.

          The original idea of components is that they are 1-1 mapping with the ControllerContexts inside the MC.

          There are a number of places that use that assumption, i.e. that the component unit's name is the same as what the ControllerContext is

          going to be.


          The two most obvious ones are:


          1) get*Scope() and get*MetaData()

          which will return the same MDR context that will be used by the MC for that instance.


          Of course in your example you are using the BeanMetaDataBuilder.addAnnotation() so the fact that your

          deployment component has a different ScopeKey and hence a different MDR context to what the MC will use is a hidden problem,

          you don't use it in the deployment layer - but somebody else might?


          You could in fact fix this with a setScope() call, but you couldn't if there was more than one bean instance in the component.

          2) IncompleteDeploymentException (IDE)


          In order for the IDE to print out what dependencies are missing for a deployment, it needs to know the ControllerContext names.

          It does this by collecting the Component DeploymentUnit's names in Component Deployers that specify this, e.g. BeanMetaDataDeployer

          or see setUseUnitName() in AbstractRealDeployer.


          I guess this could be changed such that instead of setUseUnitName(), the BeanMetaDataDeployer could directly invoke

          DeploymentUnit.addControllerContextName() using the ControllerContext.getName() it just created.


          There could be other places that use this assumption?




          You can see from the above, that the assumption could be removed and you get what you want.

          But it would only apply to a limited number of cases. e.g. where your component doesn't already have a BeanMetaData attachment.


          If two independent people wanted to augment a component with different BeanMetaDatas there's simply no way of doing that without

          stepping on each other toes.
          So creating a new component makes more sense, if you don't want strange things to happen when users write their own deployers that

          try to do similar things - especially if they copy your deployer as an example. :-)