13 Replies Latest reply on Dec 2, 2008 2:40 AM by Scott Stark

    MetaValue representation of javax.management.ObjectNames

    Ian Springer Master

      In the Topic and Queue ManagedComponents, there are a few properties, namely "DLQ", "expiryQueue", and "serverPeer", whose values represent JMX ObjectNames. In destinations-service.xml, the values of these properties are represented as simple Strings, e.g.:

       <mbean code="org.jboss.jms.server.destination.QueueService"
       name="jboss.messaging.destination:service=Queue,name=QueueWithOwnDLQAndExpiryQueue"
       xmbean-dd="xmdesc/Queue-xmbean.xml">
       <annotation>@org.jboss.system.deployers.managed.ManagementObjectClass(code=org.jboss.jms.server.destination.QueueServiceMO)</annotation>
       <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends>
       <depends>jboss.messaging:service=PostOffice</depends>
       <attribute name="DLQ">jboss.messaging.destination:service=Queue,name=PrivateDLQ</attribute>
       <attribute name="ExpiryQueue">jboss.messaging.destination:service=Queue,name=PrivateExpiryQueue</attribute>
       </mbean>
      


      However, the Profile Service represents the values using an unwieldy CompositeValue that contains several levels of nested CompositeValues and SimpleValues. Its MetaType looks like this (though this toString() representation only shows the first level of nested types):

      MutableCompositeMetaType{javax.management.ObjectName items=[name=MBeanServer type=javax.management.MBeanServer], [name=canonicalKeyPropertyListString type=java.lang.String], [name=canonicalName type=java.lang.String], [name=domain type=java.lang.String], [name=domainPattern type=java.lang.Boolean], [name=keyPropertyList type=java.util.Map],[name=keyPropertyListString type=java.lang.String], [name=pattern type=java.lang.Boolean], [name=propertyListPattern type=java.lang.Boolean],[name=propertyPattern type=java.lang.Boolean],[name=propertyValuePattern type=java.lang.Boolean]}
      


      This makes it a lot more difficult to provide the ability to edit these properties via Jopr. Is there any chance the properties' types can be changed to SimpleMetaType.STRING?


        • 1. Re: MetaValue representation of javax.management.ObjectNames
          Ian Springer Master

          On a related note, when I look at the ManagedComponent corresponding to the above "QueueWithOwnDLQAndExpiryQueue" Queue, the "DLQ" and "expiryQueue" properties have a null value, though they should not, since the Queue does define both a DLQ and an expiry queue in its config.

          • 2. Re: MetaValue representation of javax.management.ObjectNames
            Scott Stark Master

            The type on the underlying mbean is ObjectName, so either we could create a ObjectNameMetaValueHandler to simplify the building/viewing of the CompositeValue, or make use of the ManagementProperty.marshallerFactory() to map the ObjectName to/from a string MetaValue. This later bit does not seem tested, so I'll have to look at that.

            In terms of the values not being set, I'll update our JmsDestinationUnitTestCase to set these values and assert that they are not null.

            • 3. Re: MetaValue representation of javax.management.ObjectNames
              Emanuel Muckenhuber Master

               

              "scott.stark@jboss.org" wrote:
              The type on the underlying mbean is ObjectName, so either we could create a ObjectNameMetaValueHandler to simplify the building/viewing of the CompositeValue, or make use of the ManagementProperty.marshallerFactory() to map the ObjectName to/from a string MetaValue. This later bit does not seem tested, so I'll have to look at that.

              In terms of the values not being set, I'll update our JmsDestinationUnitTestCase to set these values and assert that they are not null.


              How about using a MetaMapper for transforming ObjectNames, as this already exists.
              something like:

              public class ObjectNameMetaMapper extends MetaMapper<ObjectName>
              {
              
               @Override
               public MetaType getMetaType()
               {
               return SimpleMetaType.STRING;
               }
              
               @Override
               public MetaValue createMetaValue(MetaType metaType, ObjectName object)
               {
               return SimpleValueSupport.wrap(object.getCanonicalName());
               }
              
               @Override
               public ObjectName unwrapMetaValue(MetaValue metaValue)
               {
               return internalUnwrap(metaValue);
               }
              }
              

              And add a static mapping to the MetaMapper for that, as this seems to be a common use case?

              • 4. Re: MetaValue representation of javax.management.ObjectNames
                Scott Stark Master

                Ok, sounds good. I'm going to change the current @ManagementProperty.marshallerFactory field to a MetaMapper from an InstanceClassFactory as that iface has too evolved into something beyond a simple MetaValue/value conversion iface. I'm going to create a MetaValueMapper interface that MetaMapper implements and use MetaValueMapper as the ManagementProperty.valueMapper field.

                https://jira.jboss.org/jira/browse/JBMAN-43
                https://jira.jboss.org/jira/browse/JBMAN-44

                • 5. Re: MetaValue representation of javax.management.ObjectNames
                  Scott Stark Master

                  Looking at the MetaMapper class more, its not a registry of mappers. The static getMetaMapper(TypeInfo typeInfo) method derives the MetaMapper from either an attachment on the TypeInfo, or a MetaMapping annotation on the java type (ClassInfo). I'm not sure what the hooks are for introducing an attachment or an annotation on jdk types like javax.management.ObjectName are. ?

                  • 6. Re: MetaValue representation of javax.management.ObjectNames
                    Scott Stark Master

                    Also, I guess there is no advantage to a MetaValueMapper interface, so the valueMapper would just be an extension of the MetaMapper class.

                    • 7. Re: MetaValue representation of javax.management.ObjectNames
                      Emanuel Muckenhuber Master

                       

                      "scott.stark@jboss.org" wrote:
                      Looking at the MetaMapper class more, its not a registry of mappers. The static getMetaMapper(TypeInfo typeInfo) method derives the MetaMapper from either an attachment on the TypeInfo, or a MetaMapping annotation on the java type (ClassInfo). I'm not sure what the hooks are for introducing an attachment or an annotation on jdk types like javax.management.ObjectName are. ?


                      Hmm well i was rather thinking of adding a static registry for types we cannot easily annotate ourself?
                      So that this is checked before it tries to the process the annotation.
                      I think that would be the easiest way - especially for very basic transformations like this.

                      • 8. Re: MetaValue representation of javax.management.ObjectNames
                        Scott Stark Master

                        I would add the registry to the AbstractManagedObjectFactory so that when it creates ManagedPropertys it could set the mapper if the property has a known type and does not have mapper defined at the property level.

                        • 9. Re: MetaValue representation of javax.management.ObjectNames
                          Ales Justin Master

                           

                          "scott.stark@jboss.org" wrote:
                          I'm not sure what the hooks are for introducing an attachment or an annotation on jdk types like javax.management.ObjectName are. ?

                          Something like this:
                           public <T> void registerMapper(Class<T> clazz, MetaMapper<T> metaMapper)
                           {
                           ClassInfo ci = configuration.getClassInfo(clazz);
                           ci.setAttachment(MetaMapper.class.getName(), metaMapper);
                           }
                          
                           MetaMapper<ObjectName> onMetaMapper = new ObjectNameMetaMapper();
                           registerMapper(ObjectName.class, onMetaMapper);
                          

                          You only need to be careful for transient ClassInfos,
                          since it's all weak (value) hash map in the background.

                          But for jdk classes this should stick in there forever. :-)

                          • 10. Re: MetaValue representation of javax.management.ObjectNames
                            Scott Stark Master

                            One problem with inclusion of something like a MetaMapper class in the ManagementProperty annotation is that its leaking server side types to the client since MetaMapper will reference the server side java class. If this is used by an attachment to map a non-simple deployment type to a CompostiteValue for example, this can't be marshaled to the client environment as thta type will not be available.

                            I guess we need a transient Attachments notion where server specific information could be placed, and have a convention of looking for the MetaMapper.class attachment in the AbstractManagedObjectFactory.

                            • 11. Re: MetaValue representation of javax.management.ObjectNames
                              Ales Justin Master

                               

                              "scott.stark@jboss.org" wrote:

                              I guess we need a transient Attachments notion where server specific information could be placed

                              You already have this in TypeInfo.
                              e.g.
                               /** The attachments */
                               private transient TypeInfoAttachments attachments;
                              


                              • 12. Re: MetaValue representation of javax.management.ObjectNames
                                Scott Stark Master

                                One should be able to specify the mapper at the property level such that different properties can map the same type differently. One jmx object name may want to use a string while another a Properties. I added support for associating a MetaMapper with the ManagedObject/ManagedProperty as an attachment and added a similar attachment notion to these interfaces.

                                • 13. Re: MetaValue representation of javax.management.ObjectNames
                                  Scott Stark Master

                                  There is a testcase in managed that illustrates the MetaMapper(ObjectName) implementations that were added:

                                  import javax.management.ObjectName;
                                  
                                  import org.jboss.managed.api.annotation.ManagementObject;
                                  import org.jboss.managed.api.annotation.ManagementProperty;
                                  import org.jboss.metatype.api.annotations.MetaMapping;
                                  import org.jboss.metatype.api.annotations.MetaMappingFactory;
                                  import org.jboss.metatype.plugins.values.mappers.ObjectNameMetaMapper;
                                  import org.jboss.metatype.plugins.values.mappers.ObjectNameMetaMapperFactory;
                                  import org.jboss.metatype.plugins.values.mappers.PropertiesObjectNameMetaMapper;
                                  import org.jboss.metatype.plugins.values.mappers.StringObjectNameMetaMapper;
                                  
                                  @ManagementObject
                                  public class ObjectNameBean
                                  {
                                   private ObjectName nameAsString;
                                   private ObjectName nameAsComposite;
                                   private ObjectName nameAsCompositeFixedKeys;
                                   private ObjectName nameAsProperties;
                                  
                                   @ManagementProperty()
                                   @MetaMapping(StringObjectNameMetaMapper.class)
                                   public ObjectName getNameAsString()
                                   {
                                   return nameAsString;
                                   }
                                   public void setNameAsString(ObjectName nameAsString)
                                   {
                                   this.nameAsString = nameAsString;
                                   }
                                  
                                   @ManagementProperty()
                                   @MetaMapping(ObjectNameMetaMapper.class)
                                   public ObjectName getNameAsComposite()
                                   {
                                   return nameAsComposite;
                                   }
                                   public void setNameAsComposite(ObjectName nameAsComposite)
                                   {
                                   this.nameAsComposite = nameAsComposite;
                                   }
                                  
                                   @ManagementProperty()
                                   @MetaMapping(PropertiesObjectNameMetaMapper.class)
                                   public ObjectName getNameAsProperties()
                                   {
                                   return nameAsProperties;
                                   }
                                   public void setNameAsProperties(ObjectName nameAsProperties)
                                   {
                                   this.nameAsProperties = nameAsProperties;
                                   }
                                   @ManagementProperty()
                                   @MetaMappingFactory(value=ObjectNameMetaMapperFactory.class, args={"key1", "The first key", "key2", "The second key"})
                                   public ObjectName getNameAsCompositeFixedKeys()
                                   {
                                   return nameAsCompositeFixedKeys;
                                   }
                                   public void setNameAsCompositeFixedKeys(ObjectName nameAsCompositeFixedKeys)
                                   {
                                   this.nameAsCompositeFixedKeys = nameAsCompositeFixedKeys;
                                   }
                                  }
                                  


                                  ObjectNameMetaMapper - exposes the ObjectName as a MutableCompositeMetaType
                                  PropertiesObjectNameMetaMapper - expose the ObjectName as a PropertiesMetaType
                                  StringObjectNameMetaMapper - exposes the ObjectName as a SimpleMetaType.STRING