1 2 Previous Next 15 Replies Latest reply on Jan 27, 2006 11:49 AM by adrian.brock

    SchemaBindingResolver HACK!

      Since my work on the work for XSD annotations based parsing is taking longer than
      I originally anticipated.

      I want to discuss a "HACK" that will look like the xsd annotations are working
      when in fact it is still using hardwired classes.

      This is sort of already present in the current processing to bootstrap
      the jbxb/jaxb model:

       public static final XsdAnnotation unmarshal(String annotation)
       {
       Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
       unmarshaller.mapFactoryToNamespace(JaxbObjectModelFactory.INSTANCE, Constants.NS_JAXB);
       unmarshaller.mapFactoryToNamespace(JbxbObjectModelFactory.INSTANCE, Constants.NS_JBXB);
      


      Basically what you would be able to do is say that your schema
      uses a predefined factory in one annotation:

      <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
       targetNamespace="urn:jboss:bean-deployer"
       xmlns="urn:jboss:bean-deployer"
       xmlns:jbxb="http://www.jboss.org/xml/ns/jbxb"
       elementFormDefault="qualified"
       attributeFormDefault="unqualified"
       version="1.0"
      >
      
       <xsd:annotation>
       <xsd:documentation>
       <![CDATA[
       The xml deployer schema. The deployment document instance
       root element should reference the schema in the root
       deployment element using something like:
      
       <deployment
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_1_0.xsd"
       xmlns="urn:jboss:bean-deployer">
       ...
       ]]>
       </xsd:documentation>
      
       <xsd:appinfo>
       <jbxb:schemaBindings factory="org.jboss.kernel.plugins.deployment.xml.BeanSchemaBinding">
       </jbxb:schemaBindings>
       </xsd:appinfo>
       </xsd:annotation>
      
      


      This avoids everybody have to do their own schema binding resolvers
      across the entire codebase or trying to keep these registrations in sync.

      e.g. Bill's AOP prototype version
      
       public static SchemaBinding getSchemaBinding(SchemaFactory factory)
       {
       if (schemaBinding == null)
       {
       schemaBinding = readXsd();
       schemaBinding.setSchemaResolver(new SchemaBindingResolver()
       {
       public String getBaseURI()
       {
       throw new UnsupportedOperationException("getBaseURI is not implemented.");
       }
      
       public void setBaseURI(String baseURI)
       {
       throw new UnsupportedOperationException("setBaseURI is not implemented.");
       }
      
       public SchemaBinding resolve(String nsUri, String baseURI, String schemaLocation)
       {
       if (schemaLocation == null) return null;
       if (schemaLocation.endsWith("bean-deployer_1_0.xsd"))
       return BeanSchemaBinding.getSchemaBinding();
       return null;
       }
      
       public LSInput resolveAsLSInput(String nsUri, String baseUri, String schemaLocation)
       {
       throw new UnsupportedOperationException("resolveResource is not implemented.");
       }
       }
       );
      


      For example, I want to split up the bean xsd to separate deployment from bean
      which will obviously break Bill's code.

        • 1. Re: SchemaBindingResolver HACK!

          In my prototype work, I already did something similar except
          this is really intended to bootstrap the XSD/JBXB parsing
          with the potential to externally registerSchema() these bindings

          /*
          * JBoss, Home of Professional Open Source
          * Copyright 2005, JBoss Inc., and individual contributors as indicated
          * by the @authors tag. See the copyright.txt in the distribution for a
          * full listing of individual contributors.
          *
          * This is free software; you can redistribute it and/or modify it
          * under the terms of the GNU Lesser General Public License as
          * published by the Free Software Foundation; either version 2.1 of
          * the License, or (at your option) any later version.
          *
          * This software is distributed in the hope that it will be useful,
          * but WITHOUT ANY WARRANTY; without even the implied warranty of
          * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
          * Lesser General Public License for more details.
          *
          * You should have received a copy of the GNU Lesser General Public
          * License along with this software; if not, write to the Free
          * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
          * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
          */
          package org.jboss.xb.schema.plugins.resolver;
          
          import org.jboss.xb.model.plugins.schema.hfp.HFPSchemaBinding;
          import org.jboss.xb.model.plugins.schema.jbxb.JBossXBSchemaBinding;
          import org.jboss.xb.model.plugins.schema.xsd.XSDSchemaBinding;
          import org.jboss.xb.schema.spi.loader.helpers.DefaultSchemaBindingLoader;
          import org.jboss.xb.schema.spi.resolver.SchemaBindingResolver;
          import org.jboss.xb.schema.spi.resolver.helpers.AbstractSchemaBindingResolver;
          
          /**
           * GlobalSchemaBindingResolver.
           *
           * @author <a href="adrian@jboss.com">Adrian Brock</a>
           * @version $Revision: 1.1 $
           */
          public class GlobalSchemaBindingResolver extends AbstractSchemaBindingResolver
          {
           /** The global schema binding */
           private static GlobalSchemaBindingResolver instance;
          
           /**
           * Get the global schema binding resolver
           *
           * @return the global schema binding resolver
           */
           public synchronized static SchemaBindingResolver getGlobalSchemaBindingResolver()
           {
           if (instance != null)
           return instance;
          
           try
           {
           instance = new GlobalSchemaBindingResolver();
           instance.registerEntity("-//W3C//DTD/XMLSCHEMA 200102//EN", "XMLSchema.dtd");
           instance.registerEntity("http://www.w3.org/2001/XMLSchema", "XMLSchema.dtd");
           instance.registerEntity("http://www.w3.org/2001/XMLSchema.dtd", "XMLSchema.dtd");
           instance.registerEntity("datatypes", "datatypes.dtd"); // This dtd doesn't have a publicId - see XMLSchema.dtd
           instance.registerEntity("http://www.jboss.org/xml/ns/jbxb", "jbossxb.xsd");
          
           instance.registerSchema(XSDSchemaBinding.SCHEMA_URL, XSDSchemaBinding.getInstance(instance));
           instance.registerSchema(HFPSchemaBinding.SCHEMA_URL, HFPSchemaBinding.getInstance(instance));
           instance.registerSchema(JBossXBSchemaBinding.SCHEMA_URL, JBossXBSchemaBinding.getInstance(instance));
           }
           catch (RuntimeException e)
           {
           instance = null;
           throw e;
           }
           catch (Error e)
           {
           instance = null;
           throw e;
           }
          
           return instance;
           }
          
           /**
           * Create a new GlobalSchemaBindingResolver.
           */
           private GlobalSchemaBindingResolver()
           {
           super(new DefaultSchemaBindingLoader());
           }
          }
          


          The invocations on the resolver are handled by the Wildcard processing
          and declared schema location without any real need for a registry in general.
          Just the usual file short name -> getResource("schema/shortName.xsd");

          • 2. Re: SchemaBindingResolver HACK!
            aloubyansky

             

            "adrian@jboss.org" wrote:
            Basically what you would be able to do is say that your schema uses a predefined factory in one annotation


            Do you mean "predefined schema binding"? If so, I agree.

            "adrian@jboss.org" wrote:
            This is sort of already present in the current processing to bootstrap
            the jbxb/jaxb model:

             public static final XsdAnnotation unmarshal(String annotation)
             {
             Unmarshaller unmarshaller = UnmarshallerFactory.newInstance().newUnmarshaller();
             unmarshaller.mapFactoryToNamespace(JaxbObjectModelFactory.INSTANCE, Constants.NS_JAXB);
             unmarshaller.mapFactoryToNamespace(JbxbObjectModelFactory.INSTANCE, Constants.NS_JBXB);
            



            These are really factories.

            • 3. Re: SchemaBindingResolver HACK!
              starksm64

              There was a reference that this applied to the model group/polymorphism issue, but this really seems to be a way to allow a legacy factory to be used. I don't see how this is general though because you are marking up the schema. Without an ability to reference an external jaxb/jbossxb annotation/metadata source, some use of the schema is broken. Don't we really need this jbxb:schemaBindings annotation and the ability to have the schema reference it?

              <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               targetNamespace="urn:jboss:bean-deployer"
               xmlns="urn:jboss:bean-deployer"
               xmlns:jbxb="http://www.jboss.org/xml/ns/jbxb"
               elementFormDefault="qualified"
               attributeFormDefault="unqualified"
               version="1.0"
              >
              
               <xsd:annotation>
               <xsd:documentation>
               <![CDATA[
               The xml deployer schema. The deployment document instance
               root element should reference the schema in the root
               deployment element using something like:
              
               <deployment
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="urn:jboss:bean-deployer bean-deployer_1_0.xsd"
               xmlns="urn:jboss:bean-deployer">
               ...
               ]]>
               </xsd:documentation>
              
               <xsd:appinfo>
               <jbxb:annotation-ref ref="META-INF/jbxb-annotations.xml" />
               </xsd:appinfo>
               </xsd:annotation>
              



              • 4. Re: SchemaBindingResolver HACK!

                 

                "alex.loubyansky@jboss.com" wrote:
                "adrian@jboss.org" wrote:
                Basically what you would be able to do is say that your schema uses a predefined factory in one annotation


                Do you mean "predefined schema binding"? If so, I agree.


                Yes. Bill and I even discussed being able to reference a
                MySchemaBinding.schema file rather than a class file annotation
                that is basically a "precompiled" version
                of the java object tree created by parsing the schema and
                binding callbacks to the model.

                This avoids parsing the schema everytime you want to run a junit test.
                But some of that will be mitigated when the multiple parsing problem is fixed.


                • 5. Re: SchemaBindingResolver HACK!

                   

                  "scott.stark@jboss.org" wrote:

                   <xsd:appinfo>
                   <jbxb:annotation-ref ref="META-INF/jbxb-annotations.xml" />
                   </xsd:appinfo>
                   </xsd:annotation>
                  



                  I can see the need for supporting externalized annotations.
                  e.g. when we get around to jbxb annotating the JavaEE schemas to
                  populate our internal metadata model(s).
                  But I'm not sure how this relates to the current discussion?

                  • 6. Re: SchemaBindingResolver HACK!

                     

                    "adrian@jboss.org" wrote:

                    I can see the need for supporting externalized annotations.
                    e.g. when we get around to jbxb annotating the JavaEE schemas to
                    populate our internal metadata model(s).


                    In this case you can't add any annotations to the schema,
                    and long term the "externalized annotations" will be coming from real java
                    annotations in the metadata model itself?

                    • 7. Re: SchemaBindingResolver HACK!
                      starksm64

                       

                      "adrian@jboss.org" wrote:

                      I can see the need for supporting externalized annotations.
                      e.g. when we get around to jbxb annotating the JavaEE schemas to
                      populate our internal metadata model(s).
                      But I'm not sure how this relates to the current discussion?


                      It relates in that as far as I understand what your doing, the schema is not reusable across different binding contexts. Its no different than adding annotations to the schema, but I was thinking the usecase of this hack was to allow for a existing hand-coded object factory like definitions of the SchemaBinding to be used.

                      The point is, if there are multiple mappings of the schema we can't be hard coding the mapping in the schema. The mappings I'm talking about would be the structural representation of the schema with the annotations, or even an xml presentation of the SchemaBinding object model itself.

                      • 8. Re: SchemaBindingResolver HACK!

                        Ok.

                        The problem I'm trying to solve is for Bill and I and anybody else to be able to be
                        to refer to/embed each others schemas without knowing all the plumbing
                        of how the schema gets parsed.

                        In principle, this should work by providing the schema uri or schema location
                        from which you can determine the "unmarshalling handler"
                        but this information does not exist anywhere at the moment.

                        The long term solution is to either embed the handler mechanism in the schema(s) themselves,
                        e.g. through annotations such that the problem boils down to locating the xsd file.

                        Have some naming convention to map schema uris to handlers.

                        Or pre-registering the information in some global repository (the "HACK" I refer to here).

                        The problem with pre-registering is that it doesn't scale to many schemas
                        e.g. To run a simple JBossMC test, I should haven't to load the handlers for JavaEE,
                        EJB3, etc.

                        Maintaining the registry is a nightmare and probably requires a code change
                        to the repository to introduce a new schema or change the handler information.
                        Meaning the registry needs to know about all the projects in advance that it is
                        going to handle schemas for.

                        • 9. Re: SchemaBindingResolver HACK!
                          aloubyansky

                           

                          "scott.stark@jboss.org" wrote:
                          Don't we really need this jbxb:schemaBindings annotation and the ability to have the schema reference it?


                          Yes, we do. It's also a JAXB spec requirement.

                          • 10. Re: SchemaBindingResolver HACK!
                            starksm64

                            Ok, but isn't there a more flexible hack that essentially has this GlobalSchemaBindingResolver as a bean in the deployment with its configuration defining the schema mappings? Its configuration would have to conform to the bootstrap urn:jboss:bean-deployer schema, and the jbossxb has to support a dynamic SchemaBindingResolver.

                            • 11. Re: SchemaBindingResolver HACK!
                              starksm64

                              So what I'm talking about is being able to support dynamic resolution of a foreign namespace element such as the following based on either the namespace or schema name (urn:jboss:aop-deployer:1.1 and aop-deployer_1_1.xsd in this example):

                              <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                               targetNamespace="urn:jboss:bean-deployer:1.1"
                               xmlns="urn:jboss:bean-deployer:1.1"
                               elementFormDefault="qualified"
                               attributeFormDefault="unqualified"
                               version="1.1">
                              
                               <xsd:element name="deployment" type="deploymentType">
                               </xsd:element>
                              
                               <xsd:complexType name="deploymentType">
                               <xsd:choice minOccurs="0" maxOccurs="unbounded">
                               <xsd:element name="bean" type="beanType" minOccurs="0" maxOccurs="unbounded"/>
                               <xsd:element name="beanfactory" type="beanfactoryType" minOccurs="0" maxOccurs="unbounded"/>
                               <xsd:any id="beanOther" minOccurs="0" maxOccurs="unbounded" namespace="##other" />
                               </xsd:choice>
                               </xsd:complexType>
                              ...
                              


                              <?xml version="1.0" encoding="UTF-8"?>
                              
                              <deployment xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                               xsi:schemaLocation="urn:jboss:bean-deployer:1.1 bean-deployer_1_1.xsd"
                               xmlns="urn:jboss:bean-deployer:1.1">
                               <custom:bean xmlns:custom="urn:jboss:aop-deployer:1.1"
                               xsi:schemaLocation="urn:jboss:aop-deployer:1.1 aop-deployer_1_1.xsd">
                               name="SimpleBean" class="org.jboss.test.kernel.config.support.SimpleBean">
                               <property name="customSet">
                               <set elementClass="java.lang.String">
                               <value>string1</value>
                               <value>string2</value>
                               <value>string2</value>
                               <value>string1</value>
                               </set>
                               </property>
                               </custom:bean>
                              </deployment>
                              


                              I thought we already had this with the DefaultSchemaResolver that delegated to the JBossEntityResolver.


                              • 12. Re: SchemaBindingResolver HACK!

                                 

                                "scott.stark@jboss.org" wrote:
                                Ok, but isn't there a more flexible hack that essentially has this GlobalSchemaBindingResolver as a bean in the deployment with its configuration defining the schema mappings? Its configuration would have to conform to the bootstrap urn:jboss:bean-deployer schema, and the jbossxb has to support a dynamic SchemaBindingResolver.


                                That is another hack. But it really just moves the problem in that instead of having
                                it scattered around people's XML parsing initiation it is now scattered around
                                people's test MC configurations.

                                I think it is still useful to have such a feature, e.g. to override a binding to fix bugs.


                                • 13. Re: SchemaBindingResolver HACK!

                                   

                                  "scott.stark@jboss.org" wrote:
                                  So what I'm talking about is being able to support dynamic resolution of a foreign namespace element such as the following based on either the namespace or schema name (urn:jboss:aop-deployer:1.1 and aop-deployer_1_1.xsd in this example):

                                  snipped

                                  I thought we already had this with the DefaultSchemaResolver that delegated to the JBossEntityResolver.


                                  Yes. But it only works on schemas with appinfo to define the parsing
                                  which is why you need an appinfo that says "use this object factory".

                                  • 14. Re: SchemaBindingResolver HACK!

                                    This has been implemented:
                                    http://wiki.jboss.org/wiki/Wiki.jsp?page=SchemaBindingInitializer

                                    There is one "gotcha".

                                    If you are crossing schemas, e.g. AOP includes MC schema elements,
                                    the setParent of one schema object into another doesn't work unless
                                    you are both using the same model.

                                    See SingletonSchemaBindingResolverUnitTestCase in the testsute where the
                                    DefaultElementHandler doesn't know how to setParent() on a parent element that
                                    uses the RtElementHandler.
                                    DefaultElementHandler doesn't understand the "annotation" metadata.

                                    1 2 Previous Next