2 Replies Latest reply on Jun 22, 2005 2:45 PM by starksm64

    Supporting non-default ctors

    starksm64

      http://jira.jboss.com/jira/browse/JBXB-28

      I created this issue to request support for non-default ctors for elements as its a common scenario for an existing object model to require that the immutable properties be passed in via the ctor. An example from the login-config.xml parsing is this ModuleOption with a read-only name:

      package org.jboss.test.xml.mbeanserver;
      
      public class ModuleOption
      {
       String name;
       Object value = "";
      
       ModuleOption(String name)
       {
       this.name = name;
       }
      
       String getName()
       {
       return name;
       }
       Object getValue()
       {
       return value;
       }
       void setValue(Object value)
       {
       this.value = value;
       }
      }
      


      The ModuleOption is mapped from a module-option element where the ctor arg is specified as an attribute on the element.
       <jaas:module-option name="unauthenticatedIdentity">
       guest
       </jaas:module-option>
      


      This is the most common usecase I have. I suppose the arguments could also be child elements, but this is likely a very detyped schema or one with multiple namespaces.

      The only real issue I see is how to convert the attribute string to the correct type for the ctor argument. Using a converter similar to the existing jbxb:value unmarshalMethod would be the simplest. If the attribute has a type mapping in the xsd that could also be used?


        • 1. Re: Supporting non-default ctors
          starksm64

          The current workaround for dealing with objects with non-default ctors is to use a container implementing org.jboss.xml.binding.GenericValueContainer. For the ModuleOption:

          package org.jboss.test.xml.mbeanserver;
          
          import javax.xml.namespace.QName;
          import org.jboss.xml.binding.GenericValueContainer;
          
          /**
           * ModuleOption declares a constructor that takes name as a parameter while the value should be set
           * with the setter. This use-case is not supported out-of-the-box. So, we use this container.
           *
           * @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
           * @version <tt>$Revision: 1.1 $</tt>
           */
          public class ModuleOptionContainer
           implements GenericValueContainer
          {
           private String name;
           private Object value;
          
           public void addChild(QName name, Object value)
           {
           if("name".equals(name.getLocalPart()))
           {
           this.name = (String)value;
           }
           else
           {
           this.value = value;
           }
           }
          
           public Object instantiate()
           {
           ModuleOption option = new ModuleOption(name);
           option.setValue(value);
           return option;
           }
          }
          
          


          I guess both attributes and elements are treated the same and passed to the addChild method. The associated xsd fragment is:

           <xs:element name="module-option">
           <xs:complexType mixed="true">
           <xsd:annotation>
           <xsd:appinfo>
           <!-- ModuleOption declares a constructor that takes name as a parameter
           while the value should be set with the setter.
           This use-case is not supported out-of-the-box. So, we use this container. -->
           <jbxb:class impl="org.jboss.test.xml.mbeanserver.ModuleOptionContainer"/>
           </xsd:appinfo>
           </xsd:annotation>
           <xs:sequence>
           <xs:any minOccurs="0" maxOccurs="1" namespace="##other" />
           </xs:sequence>
           <xs:attribute name="name" use="required" type="xs:string"/>
           </xs:complexType>
           </xs:element>
          



          • 2. Re: Supporting non-default ctors
            starksm64

            Even for the container solution, it would seem that we should support a more java centric bean approach via a jbxb:class container attribute:

             <xs:element name="module-option">
             <xs:complexType mixed="true">
             <xsd:annotation>
             <xsd:appinfo>
             <jbxb:class container="org.jboss.test.xml.mbeanserver.ModuleOptionContainer"
            accessor="instantiate"/>
             </xsd:appinfo>
             </xsd:annotation>
             <xs:sequence>
             <xs:any minOccurs="0" maxOccurs="1" namespace="##other" />
             </xs:sequence>
             <xs:attribute name="name" use="required" type="xs:string"/>
             </xs:complexType>
             </xs:element>
            


            where ModuleOptionContainer would not implement any specific interface. Its has a non-arg ctor as is treated the same as any other class except that on completion of the element its associated with, the jbossxb layer would invoke the method referenced by the accessor to retrieve the actual object binding. All this avoids is having to deal with the explicit handling of attributes and elements.