2 Replies Latest reply: Mar 10, 2010 7:25 AM by jaikiran pai RSS

CollectionPropertyHandler's algorithm to set a collection

jaikiran pai Master

While trying out a few things for EJB3.1 metadata, i noticed an issue with JBossXB, the way it handles binding of collection properties. Let's assume we have a xml element with minOccur=0 and maxOccur=unbounded i.e. a collection:

<xsd:complexType name="parentType">
    <xsd:sequence>
        <xsd:element name="child"
                   type="childType"
                   minOccurs="0"
                   maxOccurs="unbounded"/>
...

So typically it would map to:

 

@XmlType (...propOrder={... "children"})
public class Parent
{
    private Set<Child> children;
    
    @XmlElement(name="child")
    public void setChildren(Set<Child> children)
    {
        this.children = children;
    }
    
    public Set<Children> getChildren()
    {
        if (this.children == null)
        {
            return Collections.EMPTY_SET;
        }
        return this.children;
    }
}

 

So the getter method returns a empty set if the collection of children is null. But doing this, causes JBossXB to run into problems:

 

Caused by: java.lang.RuntimeException: QName {http://blah.com/xml/ns/myapp}child error adding org.jboss.metadata.ejb.spec.ConcurrentMethodMetaData@105b08c to collection java.util.Collections$EmptySet@1c95553
    at org.jboss.xb.builder.runtime.CollectionPropertyHandler.handle(CollectionPropertyHandler.java:166)
    at org.jboss.xb.builder.runtime.AbstractPropertyHandler.doHandle(AbstractPropertyHandler.java:98)
    at org.jboss.xb.builder.runtime.BeanHandler.setParent(BeanHandler.java:197)
    at org.jboss.xb.binding.group.ValueListHandler$FACTORY$1.newInstance(ValueListHandler.java:401)
    at org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.endRepeatableParticle(SundayContentHandler.java:854)
    at org.jboss.xb.binding.sunday.unmarshalling.SundayContentHandler.endElement(SundayContentHandler.java:191)
    at org.jboss.xb.binding.parser.sax.SaxJBossXBParser$DelegatingContentHandler.endElement(SaxJBossXBParser.java:373)
    at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
    at org.apache.xerces.xinclude.XIncludeHandler.endElement(Unknown Source)
    at org.apache.xerces.impl.XMLNSDocumentScannerImpl.scanEndElement(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)
    ... 29 more
Caused by: java.lang.UnsupportedOperationException
    at java.util.AbstractCollection.add(AbstractCollection.java:221)
    at org.jboss.xb.builder.runtime.CollectionPropertyHandler.handle(CollectionPropertyHandler.java:160)
    ... 46 more 

 

 

Looked a bit into JBossXB code and it appears that the CollectionPropertyHandler has this algorithm for "setting" the collection:

 

1) Find an appropriate "getter" for the element being set. So in this case it gets hold of getChildren()

2) Invoke the "getter" on the binding object to obtain a collection. In this case the invocation results in a EMPTY unmodifiable collection to be returned

3) The JBossXB CollectionPropertyHandler then starts "adding" the elements to this returned collection. And fails because the getter returned an unmodifiable collection.

 

Any specific reason why the "setting" of the property goes through a getter instead of doing:

 

1) Create a collection of elements.

2) Call the "setter" on  the binding object and pass it this collection.

 

This latter approach would appear more natural.