13 Replies Latest reply: Feb 11, 2010 4:48 AM by Alexey Loubyansky RSS

Using generics info in CollectionPropertyHandler

Ales Justin Master

Checking how KernelDeployment handles BeanMetaDataFactorys I came with the following issue:
- http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4191432#4191432

I guess CollectionPropertyHandler could include this check

 if (child != null)
 {
 TypeInfo typeInfo = propertyInfo.getType();
 if (typeInfo instanceof ClassInfo)
 {
 ClassInfo classInfo = (ClassInfo)typeInfo;
 TypeInfo componentType = classInfo.getComponentType();
 if (componentType != null)
 {
 TypeInfoFactory tif = componentType.getTypeInfoFactory();
 TypeInfo childTypeInfo = tif.getTypeInfo(child.getClass());
 if (componentType.isAssignableFrom(childTypeInfo) == false)
 throw new IllegalArgumentException("Illegal child type");
 }
 }
 }

probably in a bit more optimized way - not checking for component type every time.

  • 2. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master

    I've added TypeInfo::isInstance(Object) to JBoss Reflect,
    so check if it is already available when you implement this:

    if (componentType != null)
     {
     TypeInfoFactory tif = componentType.getTypeInfoFactory();
     TypeInfo childTypeInfo = tif.getTypeInfo(child.getClass());
     if (componentType.isAssignableFrom(childTypeInfo) == false)
     throw new IllegalArgumentException("Illegal child type");
     }
    

    vs.
    if (componentType != null && componentType.isInstance(child) == false)
     {
     throw new IllegalArgumentException("Illegal child type");
     }
    


  • 3. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master

    I'm getting this exception:

    testRepeatedElements(org.jboss.test.xml.RepeatedElementsUnitTestCase) Time elapsed: 0.546 sec <<< ERROR!
    org.jboss.xb.binding.JBossXBException: Failed to parse source: file:/C:/projects/jbossxb/target/test-classes/org/jboss/test/xml/RepeatedElementsUnitTestCase_testRepeatedElements.xml@5,11
     at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.parse(SaxJBossXBParser.java:177)
     at org.jboss.xb.binding.UnmarshallerImpl.unmarshal(UnmarshallerImpl.java:119)
     at org.jboss.test.xml.JBossXBTestDelegate.unmarshal(JBossXBTestDelegate.java:146)
     at org.jboss.test.xml.AbstractJBossXBTest.unmarshal(AbstractJBossXBTest.java:227)
     at org.jboss.test.xml.AbstractJBossXBTest.unmarshal(AbstractJBossXBTest.java:193)
     at org.jboss.test.xml.RepeatedElementsUnitTestCase.testRepeatedElements(RepeatedElementsUnitTestCase.java:46)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     at java.lang.reflect.Method.invoke(Method.java:585)
     at junit.framework.TestCase.runTest(TestCase.java:168)
     at junit.framework.TestCase.runBare(TestCase.java:134)
     at junit.framework.TestResult$1.protect(TestResult.java:110)
     at junit.framework.TestResult.runProtected(TestResult.java:128)
     at junit.framework.TestResult.run(TestResult.java:113)
     at junit.framework.TestCase.run(TestCase.java:124)
     at junit.framework.TestSuite.runTest(TestSuite.java:232)
     at junit.framework.TestSuite.run(TestSuite.java:227)
     at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:81)
     at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
     at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
     at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:165)
     at org.apache.maven.surefire.Surefire.run(Surefire.java:107)
     at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
     at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
     at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
     at java.lang.reflect.Method.invoke(Method.java:585)
     at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:289)
     at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:993)
    Caused by: org.jboss.xb.binding.JBossXBRuntimeException: Failed to start {http://www.jboss.org/test/xml/repeatedElements}child: the element is not repeatable, repeatable parent expected to be a model group but got element {http://www.jboss.org/test/xml/repeatedElements}top
     at org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.endRepeatableParent(SundayContentHandler.java:703)
     at org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.startElement(SundayContentHandler.java:341)
     at org.jboss.xb.binding.parser.sax.SaxJBossXBParser$DelegatingContentHandler.startElement(SaxJBossXBParser.java:401)
     at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
     at org.apache.xerces.xinclude.XIncludeHandler.startElement(Unknown Source)
     at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanStartElement(Unknown Source)
     at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
     at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
     at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
     at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
     at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
     at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
     at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
     at org.jboss.xb.binding.parser.sax.SaxJBossXBParser.parse(SaxJBossXBParser.java:173)
     ... 28 more
    
    

    After reverting my changes it's still there.

  • 4. Re: Using generics info in CollectionPropertyHandler
    Alexey Loubyansky Master

    Yes, it's a known issue. Not your fault.

  • 5. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master

    I'm having problems creating Map test case,
    where it would fail when key or value are not instance of.

    I have this 'metadata' class:

    @XmlRootElement
    @JBossXmlSchema(namespace="ns", elementFormDefault=XmlNsForm.QUALIFIED)
    public class RootWrongKey
    {
     private Map<KeyIface, ValueIface> tester;
    
     public Map<KeyIface, ValueIface> getTester()
     {
     return tester;
     }
    
     @JBossXmlMapKeyElement(name = "key")
     @JBossXmlMapValueElement(name = "value")
     public void setTester(Map<KeyIface, ValueIface> tester)
     {
     this.tester = tester;
     }
    }
    

    where KeyIface and ValueIface are empty interfaces.

    I'm trying to find where I can assign actual (but wrong) type, but w/o success.
    I'm then getting this exception:
    java.lang.IllegalArgumentException: No such property for bean org.jboss.test.xb.builder.object.type.map.support.KeyIface available []
     at org.jboss.beans.info.plugins.AbstractBeanInfo.getProperty(AbstractBeanInfo.java:147)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateType(JBossXBNoSchemaBuilder.java:1127)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:731)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:719)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateTypeBinding(JBossXBNoSchemaBuilder.java:475)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.resolveTypeBinding(JBossXBNoSchemaBuilder.java:434)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.bindMapProperty(JBossXBNoSchemaBuilder.java:2182)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.bindProperty(JBossXBNoSchemaBuilder.java:1778)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateType(JBossXBNoSchemaBuilder.java:1128)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:731)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateBean(JBossXBNoSchemaBuilder.java:719)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.generateTypeBinding(JBossXBNoSchemaBuilder.java:475)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.resolveTypeBinding(JBossXBNoSchemaBuilder.java:434)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createElementBinding(JBossXBNoSchemaBuilder.java:313)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createRootElementBinding(JBossXBNoSchemaBuilder.java:293)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.createRootElements(JBossXBNoSchemaBuilder.java:273)
     at org.jboss.xb.builder.JBossXBNoSchemaBuilder.build(JBossXBNoSchemaBuilder.java:197)
     at org.jboss.xb.builder.JBossXBBuilder.build(JBossXBBuilder.java:118)
     at org.jboss.test.xb.builder.AbstractBuilderTest.unmarshalObject(AbstractBuilderTest.java:125)
     at org.jboss.test.xb.builder.AbstractBuilderTest.unmarshalObject(AbstractBuilderTest.java:172)
     at org.jboss.test.xb.builder.object.type.map.test.KeyValueTypeUnitTestCase.testFailure(KeyValueTypeUnitTestCase.java:68)
     at org.jboss.test.xb.builder.object.type.map.test.KeyValueTypeUnitTestCase.testWrongKey(KeyValueTypeUnitTestCase.java:50)
    


    Any hint on how to produce such failing test? ;-)

    ps: I managed to do it for Collection. :-)

  • 6. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master

     

    "alesj" wrote:

    I'm trying to find where I can assign actual (but wrong) type, but w/o success.

    This is what I did for collection:
     @XmlElements
     ({
     @XmlElement(name="iface", type=SomeImpl.class),
     @XmlElement(name="impl", type=WrongImpl.class)
     })
     @XmlAnyElement
     public void setIface(List<SomeInterface> iface)
     {
     this.iface = iface;
     }
    

    where WrongImpl is not SomeInterface instance.

  • 7. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master

    I've committed the code as all previous tests + few new ones pass.
    It's only KeyValueTypeUnitTestCase that doesn't test things properly.
    I'll look some more tomorrow on how to make it legally fail. :-)

  • 8. Re: Using generics info in CollectionPropertyHandler
    Alexey Loubyansky Master

    Binding options for maps are not as sophisticated. Which is why this bug is not possible for maps :P
    I mean:
    - there is no support for multiple different names for key and value elements/attributes
    - the Java types for the key and value are determined by the Map type arguments or key and value properties in the entry class. Which is a very weak support.

    So, you can open Jira issues to enhance support in this area. If you do, please, specify how critical this is. So I can prioritize. Thanks.

  • 9. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master

     

    "alex.loubyansky@jboss.com" wrote:

    So, you can open Jira issues to enhance support in this area.

    Not really. :-)
    As all this Map stuff was a mystery for me from the beginning -
    see my MC attempts at AbstractMapMetaData. ;-)

    "alex.loubyansky@jboss.com" wrote:

    If you do, please, specify how critical this is. So I can prioritize. Thanks.

    Not really critical, it's just an enhancement (hence feature),
    to prevent future metadata developers from wildcard-ing wrong types.
    e.g. throwing exception at parse time, rather than at usage time

  • 10. Re: Using generics info in CollectionPropertyHandler
    Alexey Loubyansky Master

    Now that I'm profiling I see the componentType.convertValue(child) is taking quite a lot of time. Looking at the impl http://fisheye.jboss.org/browse/~raw,r=98934/JBossAS/projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/ValueConvertor.java it doesn't seem to be useful here.

    Note, string normalization and property replacement is done by XB anyway. I want to remove it.

    Or what am I missing?

    Thanks.

  • 12. Re: Using generics info in CollectionPropertyHandler
    Ales Justin Master
    Now that I'm profiling I see the componentType.convertValue(child) is taking quite a lot of time. Looking at the impl http://fisheye.jboss.org/browse/~raw,r=98934/JBossAS/projects/jboss-reflect/trunk/src/main/java/org/jboss/reflect/plugins/ValueConvertor.java it doesn't seem to be useful here.

    Note, string normalization and property replacement is done by XB anyway. I want to remove it.

    Or what am I missing?

    Yeah, it could be that this conversion is not needed.

    I didn't look too much into details when I dropped it in there, sorry.

     

    The goal of this change was to check the child type, which was missing before.

    Leaving that check and removing the convert should be fine then.