JAXB2 type restriction not working?

I installed a test block in github. Can someone please check why this does not work, although XML for unmarshal looks good?

https://github.com/jjYBdx4IL/misc-tests/blob/master/src/test/java/jjybdx4il/jaxb/bugs/Stackoverflow26618647Test.java

"<?xml version=\"1.0\" encoding=\"UTF-8\"?><message:GenericData xmlns:message=\"http://www.sdmx.org/resources/sdmxml/schemas/v2_1/message\" xmlns:common=\"http://www.sdmx.org/resources/sdmxml/schemas/v2_1/common\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:generic=\"http://www.sdmx.org/resources/sdmxml/schemas/v2_1/data/generic\" xsi:schemaLocation=\"http://www.sdmx.org/resources/sdmxml/schemas/v2_1/message https://sdw-wsrest.ecb.europa.eu/vocabulary/sdmx/2_1/SDMXMessage.xsd http://www.sdmx.org/resources/sdmxml/schemas/v2_1/common https://sdw-wsrest.ecb.europa.eu/vocabulary/sdmx/2_1/SDMXCommon.xsd http://www.sdmx.org/resources/sdmxml/schemas/v2_1/data/generic https://sdw-wsrest.ecb.europa.eu/vocabulary/sdmx/2_1/SDMXDataGeneric.xsd\">\n" + "<message:Header>\n" ... 

The outermost GenericDataType element gets the instance correctly. I checked this with a debugger and set a breakpoint in a manually created public constructor. However, the message: Header element creates an instance of the BaseHeaderType class, which is abstract.

SDMXMessage.xsd clearly states that the GenericDataType header is limited to GenericDataHeaderType:

 <xs:complexType name="GenericDataType"> <xs:annotation> <xs:documentation>GenericDataType defines the contents of a generic data message.</xs:documentation> </xs:annotation> <xs:complexContent> <xs:restriction base="MessageType"> <xs:sequence> <xs:element name="Header" type="GenericDataHeaderType"/> <xs:element name="DataSet" type="data:DataSetType" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="footer:Footer" minOccurs="0"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> 

Why does xjc ignore this during code generation?

 public abstract class MessageType { @XmlElement(name = "Header", required = true) protected BaseHeaderType header; @XmlAnyElement(lax = true) protected List<Object> any; @XmlElement(name = "Footer", namespace = "http://www.sdmx.org/resources/sdmxml/schemas/v2_1/message/footer") protected FooterType footer; public class GenericDataType extends MessageType { } 

Is there anything I can do about it? Any automatic alternative to create a Java domain model from XSD files that actually works?

+2
source share
1 answer

Ok, I will post this as an answer.

You encountered this problem due to this type of construction:

 <xs:complexType name="MessageType" abstract="true"> <xs:annotation> <xs:documentation>MessageType is an abstract type which is used by all of the messages, to allow inheritance of common features. Every message consists of a mandatory header, followed by optional payload (which may occur multiple times), and finally an optional footer section for conveying error, warning, and informational messages.</xs:documentation> </xs:annotation> <xs:sequence> <xs:element name="Header" type="BaseHeaderType"/> <xs:any namespace="##targetNamespace" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="footer:Footer" minOccurs="0"/> </xs:sequence> </xs:complexType> 

...

 <xs:complexType name="GenericDataType"> <xs:annotation> <xs:documentation>GenericDataType defines the contents of a generic data message.</xs:documentation> </xs:annotation> <xs:complexContent> <xs:restriction base="MessageType"> <xs:sequence> <xs:element name="Header" type="GenericDataHeaderType"/> <xs:element name="DataSet" type="data:DataSetType" minOccurs="0" maxOccurs="unbounded"/> <xs:element ref="footer:Footer" minOccurs="0"/> </xs:sequence> </xs:restriction> </xs:complexContent> </xs:complexType> 

One element is limited to a more specific element / type ( DataSet ). Since all properties are already defined in the superclass, XJC does not generate them in the "inheriting class"

As far as I know, there are a number of problems reported limitations in JAXB RI . Constraint derivation seems like a complicated concept for JAXB.

For example, in this case, what do you think the GenericDataType looks GenericDataType ? You need to override the header property to use a more specific type. Since XJC puts annotations on fields, not getters / setters, I wonder how you could override such a property. You can add another header property to handle your header , but override it?

Try writing such a class manually and use jaxb:class/@ref binding. If you earn, it will give an idea of ​​what should be created.

Next, if possible using the XJC plugin or not.

The issue you are reporting here is actually the core business of XJC. If something doesn’t work, then the “good” thing would be to report (or find an already reported problem) and fix the problem in XJC.

XJC plugins can do a lot. You can completely rebuild the model and customize the generation. With appropriate efforts, everything is possible.

But in this case, this can be a risky business. Writing advanced XJC plugins is not easy.

If you have a good concept of what the plugin should do and how this particular problem can be fixed in schema-based classes, post your thoughts, maybe we can give some recommendations. I personally probably wrote more XJC plugins than anyone else.

Hope this helps.

+1
source

Source: https://habr.com/ru/post/1443815/


All Articles