Reputation: 4901
I've got an issue where for a hierarchy of classes that can contain each other and all extend a base class, one of them will not show details when added to a list of 'base' objects. I have to use JAXB because reasons, so I'm trying to track down what is missing or wrong. I've stripped it down to sample code below.
public class BaseSchema {}
@XmlRootElement(name="ObjectA")
@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectA extends BaseSchema {
private String thingA;
@XmlElementWrapper(name="listOfBs")
@XmlElement(name="b-item")
private List<ObjectB> listB = new ArrayList<>();
// getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectB extends BaseSchema {
private String thingB;
@XmlElementWrapper(name="listOfCs")
@XmlElement(name="c-item")
private List<ObjectC> listC = new ArrayList<>();
// getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectC extends BaseSchema {
private String thingC;
@XmlElementWrapper(name="listOfBases")
@XmlElement(name="base-item")
private List<BaseSchema> listBase = new ArrayList<>();
// getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
public class ObjectD extends BaseSchema {
private String thingD;
// getter and setter
}
My root is always a known element type (ObjectA
) so it is the only one with an XmlRootElement
tag. Now for a sample dataset of an A
holding a B
holding a C
holding some of each, this is the marshaled output (JAXB first, then XStream to show the data is there). You can see that JAXB is simply outputting a 'blank' element for the D
item, with none of the internal fields - but all the rest work just fine.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ObjectA>
<thingA>Base element</thingA>
<listOfBs>
<b-item>
<thingB>B1</thingB>
<listOfCs>
<c-item>
<thingC>C1</thingC>
<listOfBases>
<base-item xsi:type="objectA" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<thingA>A1</thingA>
<listOfBs/>
</base-item>
<base-item/>
<base-item xsi:type="objectA" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<thingA>A2</thingA>
<listOfBs/>
</base-item>
<base-item xsi:type="objectB" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<thingB>B2</thingB>
<listOfCs/>
</base-item>
<base-item xsi:type="objectC" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<thingC>C2</thingC>
<listOfBases/>
</base-item>
<base-item/>
</listOfBases>
</c-item>
</listOfCs>
</b-item>
</listOfBs>
</ObjectA>
===================
<test.schema.ObjectA>
<thingA>Base element</thingA>
<listB>
<test.schema.ObjectB>
<thingB>B1</thingB>
<listC>
<test.schema.ObjectC>
<thingC>C1</thingC>
<listBase>
<test.schema.ObjectA>
<thingA>A1</thingA>
<listB/>
</test.schema.ObjectA>
<test.schema.ObjectD>
<thingD>D1</thingD>
</test.schema.ObjectD>
<test.schema.ObjectA>
<thingA>A2</thingA>
<listB/>
</test.schema.ObjectA>
<test.schema.ObjectB>
<thingB>B2</thingB>
<listC/>
</test.schema.ObjectB>
<test.schema.ObjectC>
<thingC>C2</thingC>
<listBase/>
</test.schema.ObjectC>
<test.schema.ObjectD>
<thingD>D2</thingD>
</test.schema.ObjectD>
</listBase>
</test.schema.ObjectC>
</listC>
</test.schema.ObjectB>
</listB>
</test.schema.ObjectA>
===================
Code to create the output:
public class MarshalTest {
public void test() throws Exception {
ObjectA base = new ObjectA();
base.setThingA("Base element");
ObjectB b1 = new ObjectB();
b1.setThingB("B1");
base.getListB().add(b1);
ObjectC c1 = new ObjectC();
c1.setThingC("C1");
b1.getListC().add(c1);
ObjectA a1 = new ObjectA();
a1.setThingA("A1");
c1.getListBase().add(a1);
ObjectD d1 = new ObjectD();
d1.setThingD("D1");
c1.getListBase().add(d1);
ObjectA a2 = new ObjectA();
a2.setThingA("A2");
c1.getListBase().add(a2);
ObjectB b2 = new ObjectB();
b2.setThingB("B2");
c1.getListBase().add(b2);
ObjectC c2 = new ObjectC();
c2.setThingC("C2");
c1.getListBase().add(c2);
ObjectD d2 = new ObjectD();
d2.setThingD("D2");
c1.getListBase().add(d2);
JAXBContext jaxbContext = JAXBContext.newInstance(base.getClass());
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
StringWriter writer = new StringWriter();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(base, writer);
System.out.println(writer.toString());
}
Upvotes: 1
Views: 506
Reputation: 2268
I think the problem is that JAXB is not aware of your ObjectD class. Can you try to add @XmlSeeAlso({ ObjectA.class, ObjectB.class, ObjectC.class, ObjectD.class })
to your BaseSchema
class?
e.g.
@XmlSeeAlso({ ObjectA.class, ObjectB.class, ObjectC.class, ObjectD.class }
public class BaseSchema {}
Upvotes: 3