8 Replies Latest reply: Jul 3, 2009 8:08 AM by Thomas Diesler RSS

JBossXB does not assign schema defined attribute defaults

Thomas Diesler Master

 

[tdiesler@tdvaio blueprint]$ mvn -Dtest=BasicRootParserTestCase install

-------------------------------------------------------------------------------
Test set: org.jboss.test.osgi.blueprint.parser.BasicRootParserTestCase
-------------------------------------------------------------------------------
Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.001 sec <<< FAILURE!
testBlueprintDefaultAttributes(org.jboss.test.osgi.blueprint.parser.BasicRootParserTestCase) Time elapsed: 0.935 sec <<< FAILURE!
java.lang.AssertionError: default-lazy-init: FALSE expected:<false> but was:<null>
 at org.junit.Assert.fail(Assert.java:92)
 at org.junit.Assert.failNotEquals(Assert.java:689)
 at org.junit.Assert.assertEquals(Assert.java:127)
 at org.jboss.test.osgi.blueprint.parser.BasicRootParserTestCase.testBlueprintDefaultAttributes(BasicRootParserTestCase.java:56)


on TBlueprint I have an attribute declaration like this

 @XmlAttribute(name = "default-lazy-init")
 public Boolean isDefaultLazyInit()
 {
 return defaultLazyInit;
 }


which should probably not even be necessary.

This works with the SchemaBindingParser, which gets the binding annotation from the schema.


  • 1. Re: JBossXB does not assign schema defined attribute default
    Alexey Loubyansky Master

    The problem comes from the XML parser. Since binding is based on Java annotations, we don't parse the XSD and don't know anything about it, even whether it exists.

    So, in this case, XML parser (e.g. xerces in our case) should include default attribute values and make them available through SAX API.

    For that, XSD schema must be resolvable by the XML parser. Which means EntityResolver should know the schema location. And also validation should be enabled.

  • 2. Re: JBossXB does not assign schema defined attribute default
    Thomas Diesler Master

    I think I provide this information here

    http://anonsvn.jboss.org/repos/jbossas/projects/jboss-osgi/trunk/blueprint/impl/src/main/java/org/jboss/osgi/blueprint/parser/SchemaResolverParser.java

     static class BlueprintSchemaResolver extends DefaultSchemaResolver
     {
     private LogService log;
    
     public BlueprintSchemaResolver(BlueprintContext context)
     {
     this.log = context.getLog();
    
     try
     {
     addSchemaLocation(XMLNS_BLUEPRINT, "blueprint.xsd");
     addClassBinding(BlueprintContext.XMLNS_BLUEPRINT, TBlueprint.class);
     }
     catch (RuntimeException rte)
     {
     throw rte;
     }
     catch (Exception ex)
     {
     log.log(LogService.LOG_ERROR, "Cannot create schema resolver", ex);
     }
     }
     }
    


    The DefaultSchemaResolver sais

     /**
     * Uses the JBossEntityResolver.resolveEntity by:
     *
     * 1. Using the nsUri as the systemID
     * 2. Using the schemaLocation as the systemID
     * 3. If that fails, the baseURI is not null, the xsd is located using URL(baseURL, schemaLocation)
     * 4. If the baseURI is null, the xsd is located using URL(schemaLocation)
     */
     public SchemaBinding resolve(String nsURI, String baseURI, String schemaLocation)
    


    but (in my case) it actually generates the schema from a binding class

    schema = JBossXBBuilder.build(bindingClass);
    


    AFAICS, it generates the schema rather than use the one that I provide.

  • 3. Re: JBossXB does not assign schema defined attribute default
    Alexey Loubyansky Master

    The SchemaBinding is generated from the class, yes. But the attribute value should come from the schema during parsing of the XML. I am going to add a testcase for that (tomorrow probably).

  • 4. Re: JBossXB does not assign schema defined attribute default
    Alexey Loubyansky Master

    I've committed the testcase here
    http://anonsvn.jboss.org/repos/common/jbossxb/trunk/src/test/java/org/jboss/test/xb/builder/object/attribute/test/SchemaDefaultAttributeValueUnitTestCase.java
    and the xml and xsd are here
    http://anonsvn.jboss.org/repos/common/jbossxb/trunk/src/test/resources/org/jboss/test/xb/builder/object/attribute/test/

    As mentioned above, the problem is the XML parser cannot resolve the XSD.

    addSchemaLocation(XMLNS_BLUEPRINT, "blueprint.xsd");
    won't help. This will configure XsdBinder to resolve schema to class mapping (i.e. this is binding layer) but it has nothing to do with the XML parser.
    So, here is the testcase I committed
    UnmarshallerFactory unmarshallerFactory = UnmarshallerFactory.newInstance();
     Unmarshaller unmarshaller = unmarshallerFactory.newUnmarshaller();
    
     // this is to make the SAX parser parse the XSD as well and include default attribute values in the startElement
     unmarshaller.setSchemaValidation(true);
    
     // this is EntityResolver that SAX parser (xerces) will use to resolve XSD location for the XML being parsed
     JBossEntityResolver xmlResolver = new JBossEntityResolver();
     // Here we map schema location specified in the XML file to the local schema location,
     // which is a path relative to the resources directory visible in the classpath.
     // Note, we have to specify here and XML the complete URL including the protocol part into the schemaLocation.
     // The reason is that if we specify schemaLocation in XML as just a filename,
     // the SAX parser will compose its schemaLocation by adding the protocol, baseURI (which will depend on the
     // environment the code is run in) and the schemaLocation we specified in the XML and then
     // will pass this new schemaLocation to the resolver.
     xmlResolver.registerLocalEntity("http://www.hostame.org/SchemaDefaultAttributeValue.xsd", "org/jboss/test/xb/builder/object/attribute/test/SchemaDefaultAttributeValue.xsd");
     unmarshaller.setEntityResolver(xmlResolver);
    
     // this is to resolve namespace to class mapping and build the SchemaBinding from the class
     MultiClassSchemaResolver schemaBindingResolver = new MultiClassSchemaResolver();
     schemaBindingResolver.mapURIToClass("xb:test:default-attribute", DefaultAttribute.class);
     // the reason we configured a separate EntityResolver for unmarshaller above instead of
     // calling schemaBindingResolver.mapSchemaLocation(nsURI, location) is that
     // entity resolution inside schemaBindingResolver is used only for nsURI to class resolution (by XsdBinder)
     // and is not related to SAX parser entity resolution and XML validation.
    
     String xml = findXML("SchemaDefaultAttributeValue.xml");
     Object result = unmarshaller.unmarshal(xml, schemaBindingResolver);


    XSD
    <xsd:schema
     targetNamespace="xb:test:default-attribute"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
     elementFormDefault="qualified"
     attributeFormDefault="unqualified">
    
     <xsd:element name="default-attribute">
     <xsd:complexType>
     <xsd:attribute name="attribute" type="xsd:int" default="123" />
     </xsd:complexType>
     </xsd:element>
    </xsd:schema>


    XML
    <default-attribute xmlns="xb:test:default-attribute"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="xb:test:default-attribute http://www.hostame.org/SchemaDefaultAttributeValue.xsd"/>


    I agree, XSD resolution and its configuration is confusing. That's something we could work on and make simpler.

  • 5. Re: JBossXB does not assign schema defined attribute default
    Thomas Diesler Master

    I updated to jbossxb-2.0.1.GA

    It seems that the 'default-lazy-init' attribute does not get bound

    [tdiesler@tdvaio blueprint]$ cat testsuite/target/test.log | grep default
    2009-07-03 09:58:10,649 TRACE [org.jboss.xb.builder.JBossXBBuilder:885] Checking property defaultLazyInit for org.jboss.osgi.blueprint.parser.xb.TBlueprint type=java.lang.Boolean
    2009-07-03 09:58:10,651 TRACE [org.jboss.xb.builder.JBossXBBuilder:885] Checking property defaultDestroyMethod for org.jboss.osgi.blueprint.parser.xb.TBlueprint type=java.lang.String
    2009-07-03 09:58:10,660 TRACE [org.jboss.xb.builder.JBossXBBuilder:938] Bound attribute default-destroy-method type=org.jboss.osgi.blueprint.parser.xb.TBlueprint property=defaultDestroyMethod propertyType=ReflectClassInfoImpl@a9255c{name=java.lang.String}, normalizeSpace=false
    2009-07-03 09:58:10,661 TRACE [org.jboss.xb.builder.JBossXBBuilder:885] Checking property defaultAvailability for org.jboss.osgi.blueprint.parser.xb.TBlueprint type=org.jboss.osgi.blueprint.parser.xb.TAvailability
    2009-07-03 09:58:10,673 TRACE [org.jboss.xb.builder.JBossXBBuilder:938] Bound attribute default-availability type=org.jboss.osgi.blueprint.parser.xb.TBlueprint property=defaultAvailability propertyType=EnumInfoImpl@16d2702{name=org.jboss.osgi.blueprint.parser.xb.TAvailability}, normalizeSpace=false
    2009-07-03 09:58:10,674 TRACE [org.jboss.xb.builder.JBossXBBuilder:885] Checking property defaultInitMethod for org.jboss.osgi.blueprint.parser.xb.TBlueprint type=java.lang.String
    2009-07-03 09:58:10,676 TRACE [org.jboss.xb.builder.JBossXBBuilder:938] Bound attribute default-init-method type=org.jboss.osgi.blueprint.parser.xb.TBlueprint property=defaultInitMethod propertyType=ReflectClassInfoImpl@a9255c{name=java.lang.String}, normalizeSpace=false
    2009-07-03 09:58:10,677 TRACE [org.jboss.xb.builder.JBossXBBuilder:885] Checking property defaultTimeout for org.jboss.osgi.blueprint.parser.xb.TBlueprint type=java.math.BigInteger
    2009-07-03 09:58:10,679 TRACE [org.jboss.xb.builder.JBossXBBuilder:938] Bound attribute default-timeout type=org.jboss.osgi.blueprint.parser.xb.TBlueprint property=defaultTimeout propertyType=ReflectClassInfoImpl@659db7{name=java.math.BigInteger}, normalizeSpace=false
    2009-07-03 09:58:10,756 TRACE [org.jboss.xb.binding.sunday.unmarshalling.AttributesHandler:73] Attribute is not bound: element owner {http://www.osgi.org/xmlns/blueprint/v1.0.0}blueprint, attribute default-lazy-init
    2009-07-03 09:58:10,769 TRACE [org.jboss.xb.builder.runtime.PropertyHandler:94] QName default-timeout handle java.math.BigInteger@edf730 to org.jboss.osgi.blueprint.parser.xb.TBlueprint@16749745 property=defaultTimeout
    2009-07-03 09:58:10,770 TRACE [org.jboss.xb.builder.runtime.PropertyHandler:94] QName default-availability handle org.jboss.osgi.blueprint.parser.xb.TAvailability@17b0998 to org.jboss.osgi.blueprint.parser.xb.TBlueprint@16749745 property=defaultAvailability
    2009-07-03 09:58:10,874 TRACE [org.jboss.xb.binding.sunday.unmarshalling.AttributesHandler:73] Attribute is not bound: element owner {http://www.osgi.org/xmlns/blueprint/v1.0.0}blueprint, attribute default-lazy-init
    2009-07-03 09:58:10,874 TRACE [org.jboss.xb.builder.runtime.PropertyHandler:94] QName default-timeout handle java.math.BigInteger@faa550 to org.jboss.osgi.blueprint.parser.xb.TBlueprint@24864323 property=defaultTimeout
    2009-07-03 09:58:10,875 TRACE [org.jboss.xb.builder.runtime.PropertyHandler:94] QName default-availability handle org.jboss.osgi.blueprint.parser.xb.TAvailability@17b0998 to org.jboss.osgi.blueprint.parser.xb.TBlueprint@24864323 property=defaultAvailability
    


     @XmlAttribute
     public Boolean isDefaultLazyInit()
     {
     return defaultLazyInit;
     }
    


    I also tried

    @XmlAttribute(name = "default-lazy-init")
    @XmlAttribute(name = "default-lazy-init", namespace = BlueprintContext.XMLNS_BLUEPRINT)
    


  • 6. Re: JBossXB does not assign schema defined attribute default
    Alexey Loubyansky Master

    The attribute shouldn't be bound into the blueprint namespace of course.

    The issue is actually with jboss-reflect. Apparently, propertyInfo.getUnderlyingAnnotation(annotationType) doesn't work for 'is'-methods (i.e. it returns null even if the method is annotated). If you move @XmlAttribute to setDefaultLazyInit(...) it'll work.

  • 7. Re: JBossXB does not assign schema defined attribute default
    Ales Justin Master

     

    "alex.loubyansky@jboss.com" wrote:

    The issue is actually with jboss-reflect. Apparently, propertyInfo.getUnderlyingAnnotation(annotationType) doesn't work for 'is'-methods (i.e. it returns null even if the method is annotated).

    Nope, not a Reflect issue.

    It's by the spec, that only primitive boolean' getter should be isX,
    where as in this case - with Boolean - it should be getX.
    public class AbstractBeanInfoFactory implements BeanInfoFactory
    {
     /** The cache */
     protected Map<ClassLoader, Map<ClassInfo, Map<BeanAccessMode, BeanInfo>>> cache = new WeakHashMap<ClassLoader, Map<ClassInfo, Map<BeanAccessMode, BeanInfo>>>();
    
     protected static boolean isGetter(MethodInfo minfo)
     {
     String name = minfo.getName();
     TypeInfo returnType = minfo.getReturnType();
     TypeInfo[] parameters = minfo.getParameterTypes();
     if ((name.length() > 3 && name.startsWith("get")) || (name.length() > 2 && name.startsWith("is")))
     {
     // isBoolean() is not a getter for java.lang.Boolean
     if (name.startsWith("is") && PrimitiveInfo.BOOLEAN.equals(returnType) == false)
     return false;
     if (parameters.length == 0 && PrimitiveInfo.VOID.equals(returnType) == false)
     return true;
     }
     return false;
     }
    


  • 8. Re: JBossXB does not assign schema defined attribute default
    Thomas Diesler Master

    This works

     @XmlAttribute
     public Boolean getDefaultLazyInit()
    


    many thanks ;-)

    Ales, you might want to issue a warning with respect to

     @XmlAttribute
     public Boolean isFoo()