I know, that it might seem that this question is a duplicate of this one: InstantiationException during JAXB Unmarshalling (abstract base class, with @XmlSeeAlso concrete sub class)
However, it is slightly different: We are using the maven-jaxb2-plugin
to generate our Java-classes from xsd-files. You can find them here.
In our pom we are using the following configuration (we are using the jaxb-api in the version 2.3.1):
<plugin> <groupId>org.jvnet.jaxb2.maven2</groupId> <artifactId>maven-jaxb2-plugin</artifactId> <executions> <execution> <id>schema2-generate</id> <goals> <goal>generate</goal> </goals> <configuration> <args> <arg>-Xnamespace-prefix</arg> </args> <useActiveProxyAsHttpproxy>true</useActiveProxyAsHttpproxy> <proxyHost>your.host</proxyHost> <proxyPort>your.port</proxyPort> <strict>false</strict> <encoding>UTF-8</encoding> <catalog>src/main/resources/xsd/xbau/v22/catalog.cat</catalog> <schemaDirectory>src/main/resources/xsd/xbau/v22</schemaDirectory> <schemaIncludes> <include>*.xsd</include> </schemaIncludes> <bindingDirectory>src/main/resources/xsd/xbau/v22/xjb</bindingDirectory> <bindingIncludes> <bindingInclude>externalBindings.xjb</bindingInclude> </bindingIncludes> <generatePackage>our.generated.package.xbau.v22</generatePackage> <generateDirectory>${project.build.directory}/generated-sources/xbau/v22</generateDirectory> </configuration> </execution> </executions> </plugin>
JAXB is generating the following classes:
Nachrichtenkopf.G2G2 (subclass):
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Nachrichtenkopf.G2G") public class NachrichtenkopfG2G2 extends NachrichtenkopfG2G { }
Nachrichtenkopf.G2G (superclass):
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Nachrichtenkopf.G2G", namespace = "http://www.osci.de/xinneres/basisnachricht/4", propOrder = { "identifikationNachricht", "leser", "autor" }) @XmlSeeAlso({ NachrichtenkopfG2G2 .class }) public abstract class NachrichtenkopfG2G { @XmlElement(name = "identifikation.nachricht", namespace = "", required = true) protected IdentifikationNachricht2 identifikationNachricht; @XmlElement(namespace = "", required = true) protected Behoerde leser; @XmlElement(namespace = "", required = true) protected BehoerdeErreichbar autor; ... }
Now, if we receive a XML without an xsi-type (see below) for the “Nachrichtenkopf” we get an InstantiationException since the unmarshaller is not able to create a concrete instance because of the missing type information:
<?xml version="1.0" encoding="utf-8"?> <xbau:beteiligung.aufforderung.0300 xmlns="http://www.xleitstelle.de/xbau/2/2/" produkt="Produkt" produkthersteller="Hersteller" produktversion="Version1" standard="XBau" version="2.2" xmlns:xbau="http://www.xleitstelle.de/xbau/2/2"> <nachrichtenkopf xmlns=""> <!-- Missing Type information: xsi:type="xbau:Nachrichtenkopf.G2G" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"--> ... </nachrichtenkopf> ...
So basically, I have 2 questions:
- Is there a way to tell the Unmarshaller how to unmarshal the message without the beforementioned type information?
- Is the xsi-type-information mandatory? Or in other words: is the XML from above valid according to the schemes (xsds)?
For the sake of completeness, the content of the externalBindings.xjb
<?xml version="1.0" encoding="UTF-8"?> <jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:annox="http://annox.dev.java.net" xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix" jaxb:version="2.1"> <!-- Bemerkung: Die Schemagenerierung hat hier dazu geführt, dass es in der Factory zwei gleichnamige Methoden gibt, daher werden die Methoden hier explizit benannt --> <jaxb:globalBindings fixedAttributeAsConstantProperty="true"/> <jaxb:bindings schemaLocation="http://www.w3.org/1999/xlink.xsd"> <jaxb:bindings node="xs:group[@name='arcModel']"> <jaxb:bindings node=".//xs:element[@ref='xlink:title']"> <jaxb:property name="arcModelTitle"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings node="xs:group[@name='locatorModel']"> <jaxb:bindings node=".//xs:element[@ref='xlink:title']"> <jaxb:property name="locatorModelTitle"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings node="xs:element[@name='arc']"> <jaxb:factoryMethod name="arc42"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="../xbau-baukasten.xsd"> <jaxb:bindings node="xs:complexType[@name='Nachrichtenkopf.G2G']"> <jaxb:class name="NachrichtenkopfG2G2"/> </jaxb:bindings> <jaxb:bindings> <namespace:prefix name="xbau" /> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="http://www.osci.de/xinneres/basisnachricht/4/xinneres-basisnachricht.xsd"> <jaxb:bindings node="xs:complexType[@name='Nachricht.G2G']"> <jaxb:class name="NachrichtG2G2"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="http://www.osci.de/xinneres/basisnachricht/4/xinneres-basisnachricht.xsd"> <jaxb:bindings node="xs:complexType[@name='Identifikation.Nachricht']"> <jaxb:class name="IdentifikationNachricht2"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="http://www.osci.de/xinneres/kommunikation/3/xinneres-kommunikation.xsd"> <jaxb:bindings node="xs:complexType[@name='Code.Erreichbarkeit']"> <jaxb:class name="CodeErreichbarkeit2"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="http://www.osci.de/xinneres/kommunikation/3/xinneres-kommunikation.xsd"> <jaxb:bindings node="xs:complexType[@name='Kommunikation']"> <jaxb:class name="Kommunikation2"/> </jaxb:bindings> </jaxb:bindings> <jaxb:bindings schemaLocation="http://www.w3.org/1999/xlink.xsd"> <jaxb:bindings node="xs:complexType[@name='arcType']"> <jaxb:class name="ArcType2"/> </jaxb:bindings> </jaxb:bindings> </jaxb:bindings>
Advertisement
Answer
Solved the issue by using a catalog-file. The catalog.cat-file (have a look at the first code-block in my original question) contains an entry, to advise the schema parser to look for the scheme that causes the problem in my local file-system rather than looking it up online. You can have a look at this post, if you are interested in rewriting online resources to local resources in the context of xsd-parsing (jaxb – how to map xsd files to URL to find them).
This way I can change the scheme which now resides in my src/main/resources
folder. The scheme in question is http://www.osci.de/xinneres/basisnachricht/4/xinneres-basisnachricht.xsd. I changed name="Nachrichtenkopf.G2G" abstract="true"
to name="Nachrichtenkopf.G2G" abstract="false"
so that the class Nachrichtenkopf.G2G
is no longer abstract and therefore, can be instantiated.