2

I have an xml file which looks as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Envelope>
    <AttrA>aaa</AttrA>
    <AttrB>bbb</AttrB>
    <Element ID="1">elem1</Element>
    <Element ID="2">elem2</Element>
    ...
    <Element ID="n">elemn</Element>
</Envelope>

And a corresponding Java class:

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"attrA",
"attrB",
"elements",
})
@XmlRootElement(name = "Envelope")
public class Envelope implements Serializable, Equals, HashCode, ToString {  
    @XmlElement(name = "AttrA", required = true)
    protected AttrA attrA;
    @XmlElement(name = "AttrB", required = true)
    protected AttrB attrB;
    @XmlElement(name = "Element")
    protected List<Element> elements;

    @OneToMany(targetEntity = Element.class, cascade = {CascadeType.ALL})
    @JoinColumn(name = "ELEMENT_ID")
    public List<Element> getElements() {
        if (elements == null) {
            elements = new ArrayList<Element>();
        }
        return this.elements;
    }
}

The unmarshalling works fine and I also get my elements-list populated with the appropriate elements, but sometimes the Elements are being swapped in the list. E.q. sometimes I get a list with element 1 and 2 swapped or elements 2 and 3 swapped their places. This affects the equals-method later on during the processing of the objects. I cannot figure out what exactly influences the insert order of the elements into the list.

Is there any anotation or some other way to define the insertion order of the elements? Does anybody see any other problems with my code?

Regards, Iryna.

Update: My schema:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
           xmlns:xs="http://www.w3.org/2001/XMLSchema" 
           elementFormDefault="qualified" attributeFormDefault="unqualified" jxb:version="1.0">
<xs:element name="Envelope">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="mynamespace:AttrA"/>
            <xs:element ref="mynamespace:AttrB"/>
            <xs:sequence>
                <xs:element ref="mynamespace:Element" minOccurs="0" maxOccurs="99"/>
            </xs:sequence>
        </xs:sequence>
    </xs:complexType>
</xs:element>
...
<xs:element name="Element">
    <xs:complexType>
        <xs:sequence>
            <xs:element name="ElemAttrA" type="ElemAttrA" maxOccurs="unbounded" />
        </xs:sequence>
        <xs:attribute name="ID" use="required">
            <xs:simpleType>
                <xs:restriction base="xs:positiveInteger">
                    <xs:minInclusive value="1"/>
                    <xs:maxInclusive value="99"/>
                </xs:restriction>
            </xs:simpleType>
        </xs:attribute>
    </xs:complexType>
</xs:element>
</xs:schema>  

My bindings-xjc.xjb:

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns="http://java.sun.com/xml/ns/jaxb"
               xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
               xmlns:hj="http://hyperjaxb3.jvnet.org/ejb/schemas/customizations"
               xmlns:orm="http://java.sun.com/xml/ns/persistence/orm"
               xmlns:persistence="http://java.sun.com/xml/ns/persistence"
               xmlns:annox="http://annox.dev.java.net" 
               jaxb:extensionBindingPrefixes="hj orm annox persistence">

<jaxb:bindings schemaLocation="envelope.xsd" node="/xs:schema">

    <jaxb:bindings node="//xs:element[@name='Envelope']/xs:complexType/xs:sequence/xs:sequence/xs:element[@ref='mynamespace:Element']">
        <hj:one-to-many>
            <orm:order-by name="ID" />
        </hj:one-to-many>
    </jaxb:bindings>
    ...
</jaxb:bindings>
...
</jaxb:bindings>
Ira Re
  • 730
  • 3
  • 9
  • 25
  • Why you include the [tag:hyperjaxb] tag? – lexicore Nov 10 '14 at 18:40
  • The `List` order matches the XML order, this means what you are describing should never occur on an unmarshal. You have tagged your question with `hyperjaxb`, is it possible the difference in order is based on the results from the database instead? – bdoughan Nov 10 '14 at 19:24
  • Can you show your Element class ? I have almost same structure but Exception arose in my case com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 3 counts of IllegalAnnotationExceptions If a class has @ XmlElement property, it cannot have @ _XmlValue property. this problem is related to the following location: at private java.lang.String com.abndev.scartel.DocProperty.attrValue at com.abndev.scartel.DocProperty at private java.util.List com.abndev.scartel.XmlDoc.properties at com.abndev.scartel.XmlDoc – Andrew Niken Apr 16 '15 at 19:27

1 Answers1

2

This is not an answer, just a few hints too large for the comment.

Knowing JAXB RI code I don't think there's a chance of getting undeterministic order of items in the list. What happens there is quite straightforward, last come - last added.

You tagged the question with and your class implements interfaces from JAXB2 Basics runtime, this is an indication that you may be using Hyperjaxb.

If this is the case then Blaise has offered a very good theory on what may be happening. Your List may be mapped to the database without the ordering column so the order may not be guaranteed. Check if you have something with @OrderColumn generated. I think this is not generated by default.

Anyway, posting full code of your class and an accompanying test case would be helpful. For Hyperjaxb, use GitHub to post issues:

Update

The problem is indeed in the missing @OrderColumn, just as Blaise predicted (good shot!).

In short, you can add this column using the following customization:

<hj:one-to-many>
    <orm:order-column/>
</hj:one-to-many>

Please see the relevant part of the customization guide.

You can also customize it globally:

<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
    <hj:persistence>
        <hj:default-one-to-many>
            <orm:join-column/>
        </hj:default-one-to-many>
    </hj:persistence>
</jaxb:bindings>

Now all the generated @OneToMany will have a @JoinColumn.

Update 2

Customization for @OrderBy (as you have figured out yourself):

<hj:one-to-many>
    <orm:order-by>ID</orm:order-by>
</hj:one-to-many>

A few more references:

Disclaimer: I am the author of Hyperjaxb.

lexicore
  • 42,748
  • 17
  • 132
  • 221
  • You were right - it's not a JAXB unmarsheller which is causing the problem. And yes, hyperjaxb is used for code generation. I added the code generated by hyperjaxb for elements-getter. The annotation @OrderColumn is missing in fact. I couldn't find out how to tell hyperjaxb to add it. An issue regarding this problem can be found here [link](http://stackoverflow.com/questions/9382760/order-column-does-not-seem-to-work) but I don't really understand were to make the changes discribed in this topic. Could anybody help me? – Ira Re Nov 11 '14 at 11:05
  • 1
    @IraRe I am the author of Hyperjaxb, so yes, of course. First of all see the [customization guide](http://confluence.highsource.org/display/HJ3/Customization+Guide), there is even [an example](http://confluence.highsource.org/display/HJ3/Customization+Guide#CustomizationGuide-Customizingtheone-to-manyproperty) for adding the `@OrderColumn`. But I'd suggest that you ask a separate question on that and provide a small relevant schema fragment. I'll provide a full example then. – lexicore Nov 11 '14 at 12:12
  • Hello @lexicore! Thanks a lot for your comment. I found out that the `@OrderBy` would be more appropriate for my use case as we already have a lot of data saved (unordered) in the database. I would like to order the list by Element ID. I have added the column as suggested by you (see my update), the `@OrderBy` annotation is added at getElements() but unfortunately without column name defined. What have I missed to add in my hyperjaxb customization? – Ira Re Nov 11 '14 at 14:36
  • 1
    Ok, I found my error: ` ID ` would be the proper syntax. – Ira Re Nov 11 '14 at 15:03
  • @IraRe Please try `ID`. The [customization schema](https://github.com/highsource/hyperjaxb3/blob/master/ejb/schemas/customizations/src/main/resources/customizations.xsd) is actually based on the standard [JPA 2.0 ORM mappings schema](https://github.com/highsource/hyperjaxb3/blob/master/ejb/schemas/persistence/orm_2_0.xsd). – lexicore Nov 11 '14 at 15:04