У меня есть абстрактный класс A с двумя подклассами B и C . A выглядит следующим образом:
@XmlTransient
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "A", propOrder = {
"operation",
"origin",
})
@XmlSeeAlso({B.class, C.class})
public abstract class A {
@XmlElement(required = true)
protected Operation operation;
@XmlElement(required = true)
protected Origin origin;
// getters and setters
}
B :
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "A") // root element is A for all subclasses
@XmlType(name = "B", propOrder = {
"operation",
"origin",
"b",
})
public class B extends A {
@XmlElement(required = true)
protected String b;
// getter and setter
}
C :
@XmlAccessorType(XmlAccessType.FIELD)
@XmlRootElement(name = "A") // root element is A for all subclasses.
@XmlType(name = "C", propOrder = {
"operation",
"origin",
"c",
})
public class C extends A {
@XmlElement(required = true)
protected String c;
// getter and setter
}
Как создать контекст JAXB:
private static JAXBContext createJaxbContext() throws JAXBException {
if(jaxbContext == null) {
final ClassLoader classLoader = A.class.getClassLoader();
final String contextPath = A.class.getPackage().getName();
jaxbContext = JAXBContext.newInstance(contextPath, classLoader);
}
return jaxbContext;
}
Когда я передаю XML, соответствующий абстрактному классу A , но обладающий свойством b , яожидайте, что JAXB сможет разархивировать его в объект типа B (и то же самое для C , если свойство c существует).В настоящее время происходит то, что он пытается разархивировать все строки XML до C и только C , что приводит к исключению ClassCastException.
Я попытался указать подклассы как типы на корневом узле, то есть что-то вроде:
<A xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="C">
<operation id="123" action="insert"/>
<origin>
<environment>DEV</environment>
<instance>root</instance>
</origin>
<c>c value</c>
</A>
, но это не решает проблему.
Что я могу делать не так?Был бы признателен за любую помощь :)
РЕДАКТИРОВАТЬ: если это помогает, это метод, используемый для unmarshalling
public static A toA(String xml) throws Exception{
try {
final Unmarshaller jaxbUnmarshaller = getJaxbContext().createUnmarshaller();
final StringReader reader = new StringReader(xml);
return (A) jaxbUnmarshaller.unmarshal(reader);
} catch (JAXBException e) {
throw new Exception("Failed to unmarshal A " + "[" + e.toString() + "].");
}
}
И это моя ObjectFactory:
@XmlRegistry
public class ObjectFactory {
private final static QName A_QNAME = new QName("", "A");
public ObjectFactory() {}
public B createB() {
return new B();
}
public C createC() {
return new C();
}
public Operation createOperation() {
return new Operation();
}
public Origin createOrigin() {
return new Origin();
}
public A createA(A value) {
return new JAXBElement<>(A_QNAME, A.class, null, value).getValue();
}
}