5 Replies Latest reply on Mar 15, 2006 9:56 AM by aloubyansky

    Interaction between enclosing SchemaBinding and SchemaBindin

    starksm64

      I have the xmbean 2 parsing past the point of being able to create the objects correctly, but there is a disconnect between the out xmbean schema and the custom schema. A document like this:

      <mbean xmlns="urn:jboss-test:xmbean:2.0"
       code="org.jboss.naming.JNDIBindingService"
       name="jboss.tests:service=JNDIBindingService">
      
       <descriptors>
       <interceptors>
       <custom1:javabean xmlns:custom1="urn:jboss:simplejavabean:1.0"
       class="org.jboss.test.xml.mbeanserver.interceptors.SomeBeanInterceptor"
       flag="true"
       anInt="1234"
       aLong="123456789"
       aString="string1"
       someStrings="string1,string2,string3"
       address="127.0.0.1"
       homePage="http://www.jboss.org/"
       aClass="java.lang.Integer"
       someProperties="prop1=value1\nprop2=value2\nprop3=value3"
       />
      
       <interceptor
      code="org.jboss.mx.interceptor.PersistenceInterceptor2" />
       <interceptor code="org.jboss.mx.interceptor.ModelMBeanInterceptor" />
       <interceptor code="org.jboss.mx.interceptor.ObjectReferenceInterceptor" />
       </interceptors>
       </descriptors>
      </mbean>
      
      does have interceptors from the two schemas created. However, the interceptor from the custom schema is not being added to its parent. The xmbean schema does define an add method for both the integrated interceptor, and the any wildcard:
      
      


       <xs:complexType name="interceptorsType">
       <xs:annotation>
       <xs:documentation>
       <![CDATA[
       The interceptors element specifies a customized stack of interceptors
       that will be used in place of the default stack. Currently this is only
       used when specified at the mbean level, but it could define a custom attribute
       or operation level interceptor stack in the future. Any stack should include the following
       interceptors as the last interceptors:
      
       <interceptors>
       <interceptor code="org.jboss.test.jmx.interceptors.JNDISecurity"
       securityDomain="java:/jaas/secure-jndi"/>
       <interceptor code="org.jboss.naming.interceptors.ProxyFactoryInterceptor"
       proxyName="jboss:service=proxyFactory,type=jrmp,target=Naming"/>
       <interceptor code="org.jboss.mx.interceptor.PersistenceInterceptor2" />
       <interceptor code="org.jboss.mx.interceptor.ModelMBeanInterceptor" />
       <interceptor code="org.jboss.mx.interceptor.ObjectReferenceInterceptor" />
       </interceptors>
       ]]>
       </xs:documentation>
       <xs:appinfo>
       <jbxb:class impl="org.jboss.mx.metadata.xb.InterceptorsHolder"/>
       </xs:appinfo>
       </xs:annotation>
      
       <xs:choice minOccurs="0" maxOccurs="unbounded">
       <xs:element name="interceptor" type="xmbean:interceptorType" />
       <xs:any namespace="##other" processContents="lax">
       <xs:annotation>
       <xs:appinfo>
       <jbxb:addMethod name="addInterceptor"
       valueType="org.jboss.mx.interceptor.Interceptor"/>
       </xs:appinfo>
       </xs:annotation>
       </xs:any>
       </xs:choice>
       </xs:complexType>
      
       <xs:complexType name="interceptorType">
       <xs:annotation>
       <xs:documentation>
       The interceptor element specifies a custom interceptor instance.
      
       Each interceptor must implement the org.jboss.mx.interceptor.Interceptor
       interface, and must have either a no-arg constructor, or a constructor
       that accepts a javax.management.modelmbean.ModelMBeanInfo.
       </xs:documentation>
       <xs:appinfo>
       <jbxb:class impl="org.jboss.mx.metadata.xb.InterceptorHolder"/>
       <jbxb:addMethod name="addInterceptor"
       valueType="org.jboss.mx.interceptor.Interceptor"/>
       </xs:appinfo>
       </xs:annotation>
       <xs:attribute name="code" />
       <xs:anyAttribute />
       </xs:complexType>
      


      However, the add of the any object binding is not being done. Presumably I would have to create the AddMethodMetaData to the interceptor element in the org.jboss.test.xml.mbeanserver.JavaBeanSchemaInitializer, but this is not practical as the result of the urn:jboss:simplejavabean:1.0 binding should be reusable in any enclosing schema.

      It seems like there should be a check on the enclosing schema for an addMethod binding if the SchemaBindingInitializer result does not provide this information.


        • 1. Re: Interaction between enclosing SchemaBinding and SchemaBi
          aloubyansky

          It seems like you don't have a schema for custom interceptor and unresolvedElementHandler is not set. Then the custom interceptor is parsed with jbxb:skip present.

          Currently, you have to explicitly set unresolvedElementHandler and unresolvedCharactersHandler on the WildcardBinding. Perhaps, it makes sense to add config option to use the default handlers for this.

          • 2. Re: Interaction between enclosing SchemaBinding and SchemaBi
            starksm64

             

            "alex.loubyansky@jboss.com" wrote:
            It seems like you don't have a schema for custom interceptor and unresolvedElementHandler is not set. Then the custom interceptor is parsed with jbxb:skip present.

            Currently, you have to explicitly set unresolvedElementHandler and unresolvedCharactersHandler on the WildcardBinding. Perhaps, it makes sense to add config option to use the default handlers for this.


            There are two matches for the interceptor element in terms of schemas:
            1. The urn:jboss-test:xmbean:2.0 has a wildcard match on a foreign namespace element.
            2. The custom1:javabean element matches the urn:jboss:simplejavabean:1.0 which is registered with the schema resolver, and has a SchemaBindingInitializer that is being executed. The custom1:javabean java object is correctly created, but it is not added to the parent object from the urn:jboss-test:xmbean:2.0 namespace. I had the same problem originally with the multi-spaced schemas. I could get this to work by adding a setParent override to the JavaBeanSchemaInitializer TypeBinding for the custom1:javabean:

             public SchemaBinding init(SchemaBinding schema)
             {
             // javabean binding
             TypeBinding beanType = schema.getType(JavaBeanSchemaInitializer.javabeanTypeQName);
             beanType.setHandler(new DefaultElementHandler()
             {
             public Object startElement(Object parent, QName name, ElementBinding element)
             {
             return new Holder();
             }
            
             public void attributes(Object o, QName elementName, ElementBinding element, Attributes attrs, NamespaceContext nsCtx)
             {
             Holder holder = (Holder) o;
             String className = null;
             Properties properties = holder.getProperties();
             for (int i = 0; i < attrs.getLength(); ++i)
             {
             String localName = attrs.getLocalName(i);
             String value = attrs.getValue(i);
             if ("class".equals(localName))
             {
             className = value;
             holder.setType(className);
             continue;
             }
             properties.put(localName, value);
             }
            
             if (className == null)
             throw new IllegalArgumentException("No class attribute for " + elementName);
             }
            
             public Object endElement(Object o, QName qName, ElementBinding element)
             {
             Holder holder = (Holder) o;
             Object bean;
             try
             {
             bean = holder.getBean();
             Properties props = holder.getProperties();
             System.out.println("Converting properties: "+props);
             PropertyEditors.mapJavaBeanProperties(bean, props, true);
             }
             catch (Exception e)
             {
             throw new IllegalStateException("Failed to init bean: "+qName, e);
             }
             return bean;
             }
            
             /* This is needed, but should not be as I cannot know anything
             about the containing schema in general.
             */
             public void setParent(...)
             {
             }
             });
            
            
             return schema;
             }
            ...
            


            but the problem is that this breaks the extension point relationship. We should be picking up the addMethod metadata from the {urn:jboss-test:xmbean:2.0}interceptor wildcard extension point to determine what to do with the object created by the {urn:jboss:simplejavabean:1.0}javabean element. Currently it seems that the parent/child metadata is at the wrong level. We may need to support either level taking control of relationship, but I would expect that the default would be for the parent type to have the metadata for specifying how a child element is added to the associated java object rather than having the child element specify this.

            Understanding which binding is responsible for handling parent/child relationships is one reason I'm going through the a kickstart of the docbook.


            • 3. Re: Interaction between enclosing SchemaBinding and SchemaBi

              I had a similar problem. I added support for having a wildcard
              binding on the parent schema.

              Only the parent schema knows what you want to do with the
              value created by the child schema, when it is a wildcard.

              e.g. in the Microcontainer

               factoryType.getWildcard().setWildcardHandler(new DefaultWildcardHandler()
               {
               public void setParent(Object parent, Object o, QName elementName, ElementBinding element, ElementBinding parentElement)
               {
               Holder holder = (Holder) parent;
               if (o instanceof ValueMetaData == false)
               o = new AbstractValueMetaData(o);
               holder.setValue(o);
               }
               });
              


              In this case, it will add any object to an MC factory element by wrapping it in
              AbstractValueMetaData if it is not already one.

              Something like the following where foo schema constructs an object:
              <bean>
               <factory>
               <foo xmlns="urn:foo:2:0"/>
              ...
              


              I'm not sure if this supported in the annotations? I didn't add an annotation for it.

              • 4. Re: Interaction between enclosing SchemaBinding and SchemaBi
                starksm64

                Ok. I'll work on adding annotation support for this once I get to documenting the binding layer behavior, hopefully today.

                • 5. Re: Interaction between enclosing SchemaBinding and SchemaBi
                  aloubyansky

                  There were two reasons it was not added:
                  1. AddMethodMetaData was not actually set on the WildcardBinding (in XsdBinder, not your fault). It's fixed now.
                  2. DefaultElementHandler.setParent is empty. I changed the handler to be based on the RtElementHandler.

                  The test now passes.