TLDR: I have to generate Java classes from an XSD, and one of the fields of the "Main" object is another generated class. The field has an annotation @XmlElement, which has a property "type = Object.class " while having the field type = "SubObject". This makes it so that when I try to unmarshal the XML into a Java Object I get an error.
@XmlRootElement(name = "MainObject")
public class MainObject {
@XmlElement(name = "SubObject", required = true, type = Object.class)
protected SubObject subObject;
}
I have tried with both the JAXB2 Maven Plugin and the Apache-CXF-XJC plugin. In both cases I end up with the same result. If I manually remove the type property from the annotation it works. How can I generate the class without the type property, or make it be SubObject.class in this case?
More info
The files/configuration that worked on the old project:
pom.xml plugin configuration
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-xjc-plugin</artifactId>
<version>2.3.0</version>
<configuration>
<extensions>
<extension>org.apache.cxf.xjcplugins:cxf-xjc-dv:2.3.0</extension>
</extensions>
</configuration>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<goals>
<goal>xsdtojava</goal>
</goals>
<configuration>
<sourceRoot>${project.build.sourceDirectory}/../generated/</sourceRoot>
<xsdOptions>
<xsdOption>
<xsd>src/main/resources/xsd/subobject.xsd</xsd>
<packagename>org.acme.generated</packagename>
</xsdOption>
<xsdOption>
<xsd>src/main/resources/xsd/mainobject.xsd</xsd>
<packagename>org.acme.generated</packagename>
<bindingFile>src/main/resources/xsd/bindings.xjb</bindingFile>
</xsdOption>
</xsdOptions>
</configuration>
</execution>
</executions>
</plugin>
xjb bindings file
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.1">
<bindings schemaLocation="mainobject.xsd" version="1.0">
<bindings node="//xs:element[@name='SubObject']">
<class ref="org.acme.generated.SubObject"/>
</bindings>
</bindings>
</bindings>
generated MainObject class
@XmlRootElement(name = "MainObject")
public class MainObject {
@XmlElement(name = "MainElement1", required = true)
protected String mainElement1;
@XmlElement(name = "MaintElement2")
protected int maintElement2;
@XmlElement(name = "SubObject", required = true)
protected SubObject subObject;
Now, after researching a bit, I've ended up with the following files for the newer plugin:
pom.xml plugin configuration
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jaxb2-maven-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>xjc</id>
<goals>
<goal>xjc</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>src/main/resources/xsd</sources>
<outputDirectory>src/main/generated</outputDirectory>
<xjbSources>
<xjbSource>src/main/resources/xjb</xjbSource>
</xjbSources>
<!-- The package of your generated sources -->
<packageName>org.acme.generated</packageName>
</configuration>
</plugin>
xjb bindings file
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="https://jakarta.ee/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
version="3.0">
<jaxb:bindings schemaLocation="..\xsd\mainobject.xsd" version="1.0" node="//xsd:element[@name='SubObject']">
<jaxb:property>
<jaxb:baseType>
<jaxb:javaType name="org.acme.generated.SubObject"/>
</jaxb:baseType>
</jaxb:property>
</jaxb:bindings>
</jaxb:bindings>
generated MainObject class
@XmlRootElement(name = "MainObject")
public class MainObject {
@XmlElement(name = "MainElement1", required = true)
protected String mainElement1;
@XmlElement(name = "MaintElement2")
protected int maintElement2;
@XmlElement(name = "SubObject", required = true, type = Object.class)
protected SubObject subObject;
generated SubObject class
@XmlRootElement(name = "SubObject")
public class SubObject {
@XmlElement(name = "SubElement1", required = true)
protected String subElement1;
@XmlElement(name = "SubElement2")
protected int subElement2;
Both the xsd files stayed the same, but the generated MainObject class now has the type property on the anottation, with value Object.class. When I try to unmarshal the following XML:
<?xml version="1.0" encoding="utf-8"?>
<MainObject>
<MainElement1>test1</MainElement1>
<MainElement2>2</MainElement2>
<SubObject>
<SubElement1>test1</SubElement1>
<SubElement2>2</SubElement2>
</SubObject>
</MainObject>
I get the following error java.lang.IllegalArgumentException: Can not set org.acme.generated.SubObject field org.acme.generated.MainObject.subObject to com.sun.org.apache.xerces.internal.dom.ElementNSImpl
. However, if I manually remove the type = Object.class from the generated class the unmarshal works perfectly.
To add a little bit more info, I've also tried generating the classes with an updated version of the apache-CXF-XJC plugin (v4.0.0) but I get the same result.
Is there a way to manipulate the type attribute generated on the annotation @XmlElement? Or to ignore it at the time of unmarshalling the data into an object?