5 Replies Latest reply on Apr 9, 2010 11:59 AM by jaikiran pai

    How to avoid canonical conversion of AbstractInjectionValueMetaData's value?

    jaikiran pai Master

      I have got a piece of code which deploys a MC bean into the kernel: {code:java} String beanName = "abc"; BeanMetaDataBuilder builder = BeanMetaDataBuilderFactory.createBuilder(beanName, MyClass.class.getName()); String constructorParamMCBeanName = "jboss.domain:m=xyz,c=pqr"  builder.addConstructorParameter(SomeClass.class.getName(), new AbstractInjectionValueMetaData(constructorParamMCBeanName)); {code} So effectively, it's creating a MC bean for MyClass which accepts an instance of SomeClass as its constructor param: {code:java} public class MyClass {     public MyClass(SomeClass param)     {         ...     } } {code} The SomeClass instance which itself is a MC bean with MC bean name "jboss.domain:m=xyz,c=pqr" gets deployed by some other piece of code. This is simple enough and should have worked. But it doesn't. When the "abc" MC bean is installed, it runs into: {code:java} DEPLOYMENTS MISSING DEPENDENCIES:   Deployment "abc" is missing the following dependencies:     Dependency "jboss.domain:c=pqr,m=xyz" (should be in state "Installed", but is actually in state "** NOT FOUND Depends on 'jboss.domain:c=pqr,m=xyz' **") {code}  Notice that the (injection) dependency MC bean name has been converted to a canonical name. Shouldn't have happened. But looking at the constructor of AbstractInjectionValueMetaData, a call to new AbstractInjectionValueMetaData(constructorParamMCBeanName), leads to: {code:java} public AbstractValueMetaData(Object value)    {       setValue(value);    }    public void setValue(Object value)    {       Object jmxHack = null;       if (isUseJMXObjectNameFix())          jmxHack = JMXObjectNameFix.needsAnAlias(value);       if (jmxHack != null)          this.value = jmxHack;       else          this.value = value;             flushJBossObjectCache();    }       /**     * Do we use jmx object name fix.     *     * @return do we use jmx object name fix     */    protected boolean isUseJMXObjectNameFix()    {       return true;    }    {code}   The isUseJMXObjectNameFix always returns true and then JMXObjectNameFix.needsAnAlias(value) converts the MC bean name to its canonical form. I see no way to prevent this from happening (other than create a subclass - which is a bit too much to do for this simple usecase). Am I missing something? Or is there some other way to get around this?

        • 1. Re: How to avoid canonical conversion of AbstractInjectionValueMetaData's value?
          Ales Justin Master

          Better question is how you're getting past this mechanism in the first place,

          by being able to have an ObjectName named bean which is not canonical.

           

          Perhaps add an alias with canonical name?

          • 2. Re: How to avoid canonical conversion of AbstractInjectionValueMetaData's value?
            jaikiran pai Master

            Ales Justin wrote:

             

            Better question is how you're getting past this mechanism in the first place,

            by being able to have an ObjectName named bean which is not canonical.

             

             

            I'm not sure I understood that question. Is there a constraint in MC, that MC bean names which might be of the form ObjectName, should be canonical? More specifically, can't I have a MC bean named:

             

            blah.blah:p=q,a=b
            

             

            and just be treated as a plain string name, instead of ObjectName?

            • 3. Re: How to avoid canonical conversion of AbstractInjectionValueMetaData's value?
              Ales Justin Master

              To be back compatible - JMX legacy - we check every name against ObjectName and canonicalize it.

              I was just wondering how you were able to register non-canonicalized named bean.

              • 4. Re: How to avoid canonical conversion of AbstractInjectionValueMetaData's value?
                Ales Justin Master
                I was just wondering how you were able to register non-canonicalized named bean.

                Asked too soon. :-)

                The name is un-touched, but we do add an alias if it looks like ObjectName.

                 

                /**
                    * Set the aliases<p>
                    * 
                    * Aliases in this list only take effect if they are set before installation on the controller
                    * 
                    * @param aliases the aliases
                    */
                   public void setAliases(Set<Object> aliases)
                   {
                      // WARNING: This code is hack for backwards compatiblity
                      
                      // Here we fixup the aliases to map JMX like ObjectNames to their canonical form
                      // I've made it a protected method needsAnAlias so others can subclass and
                      // change the rules (including not doing this at all)
                      // NOTE: This method should be invoked from all constructors
                      if (aliases == null)
                      {
                         // There are no explicit aliases so just see whether the name is an ObjectName.
                         Object alias = needsAnAlias(name);
                         // No alias required
                         if (alias == null)
                            this.aliases = null;
                         else
                            // Add a single alias with canonical name
                            this.aliases = Collections.singleton(alias);
                      }
                      else
                      {
                         // Always clone the aliases passed it
                         this.aliases = new HashSet<Object>();
                         // Check the main name
                         Object alias = needsAnAlias(name);
                         if (alias != null)
                            this.aliases.add(alias);
                         // Check the aliases
                         for (Object passedAlias : aliases)
                         {
                            this.aliases.add(passedAlias);
                            alias = needsAnAlias(passedAlias);
                            if (alias != null)
                               this.aliases.add(alias);
                         }
                      }
                   }

                 

                So, your injection should be able to match it no matter which form (canonical or not) you use,

                since it should always be able to hit canonicalized, either from actual name or its alias.

                • 5. Re: How to avoid canonical conversion of AbstractInjectionValueMetaData's value?
                  jaikiran pai Master

                  Ales Justin wrote:

                   

                  I was just wondering how you were able to register non-canonicalized named bean.

                  Asked too soon. :-)

                  The name is un-touched, but we do add an alias if it looks like ObjectName.

                  ...

                  So, your injection should be able to match it no matter which form (canonical or not) you use,

                  since it should always be able to hit canonicalized, either from actual name or its alias.

                  I see. So in reality, looks like the other deployer isn't deploying the  "jboss.domain:m=xyz,c=pqr" MC bean resulting in that deployment error. But what confused me (and took me on a wrong path ) was the error reported this canonical name instead of the original MC bean on which I had added that dependency. That gave me an impression that the dependency was being set on the wrong MC bean.