0

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?

Cps
  • 1
  • 2
  • Where is your SubObject class? – jdweng Aug 22 '23 at 11:44
  • @jdweng just updated the main post with it, had to delete it at first cause the system was marking my post as spam. The same class is generated with both the "new" plugins and with the older version of the CXF plugin, so it doesn't seem to be a problem. – Cps Aug 22 '23 at 12:47
  • What's the XSD like? Questions are encouraged to provide a [mcve] – LMC Aug 22 '23 at 13:28
  • Try adding get/set to all your properties : protected String subElement1 { get; set; } – jdweng Aug 22 '23 at 14:19

0 Answers0