I have model generated by xjc based on the dtd. The model looks as follows:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"a",
"b"
})
@XmlRootElement(name = "parent")
public class Parent {
@XmlAttribute(name = "id")
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlID
protected String id;
@XmlElement(required = true)
protected A a;
@XmlElement(required = true)
protected B b;
//getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"value"
})
@XmlRootElement(name = "a")
public class A {
@XmlAttribute(name = "id")
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlID
protected String id;
@XmlValue
protected String value;
//getters and setters
}
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"value"
})
@XmlRootElement(name = "b")
public class B {
@XmlAttribute(name = "id")
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
@XmlID
protected String id;
@XmlValue
protected String value;
//getters and setters
}
All classes contains id which is annotated with @XmlID
. To give whole context my parser looks as follows:
XMLInputFactory inputFactory = new WstxInputFactory();
inputFactory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.FALSE);
inputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
XmlFactory xmlFactory = new XmlFactory(inputFactory, new WstxOutputFactory());
JacksonXmlModule jacksonXmlModule = new JacksonXmlModule();
jacksonXmlModule.setDefaultUseWrapper(false);
XmlMapper xmlMapper = new XmlMapper(xmlFactory, jacksonXmlModule);
xmlMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
xmlMapper.registerModule(new JakartaXmlBindAnnotationModule());
The problem occurs when the xml does not contain the id
attribute for tag a
or b
. Example xml:
<?xml version="1.0" encoding="UTF-8" ?>
<parent>
<a id="ex">some content</a>
<b>another content</b>
</parent>
I get the following error during mapping:
Exception in thread “main”
com.fasterxml.jackson.databind.deser.UnresolvedForwardReference:
Unresolved forward references for: at [Source: (StringReader); line:
5, column: 1]Object id [another content] (formapping.B
) at [Source:
(StringReader); line: 4, column: 27]. at
com.fasterxml.jackson.databind.deser.UnresolvedForwardReference.withStackTrace(UnresolvedForwardReference.java:104)
at
com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.checkUnresolvedObjectId(DefaultDeserializationContext.java:184)
at
com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4907)
at
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3848)
at
com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3816)
at mapping.Parser.main(Parser.java:36)
However, when the parent
tag does not have the id
attribute, everything maps correctly. So this xml will be mappe correctly:
<?xml version="1.0" encoding="UTF-8" ?>
<parent>
<a id="ex">some content</a>
<b id="bl">another content</b>
</parent>
I know that @XmlID
helps to identify object across object graph during serialization and deserialization. And it allows to reference given object by id with the usage of @XmlIDREF
.
I’m a little bit confused, so I would like to understand, how does this @XmlID
annotation work? Why does the error only appear when the missing attribute is at the lowest level of the hierarchy? Can I configure Jackson to not throw this exception?