I am having some issues with generating Java Classes with appropriate JAXB annotations from an XSD using XJC.
I have a relatively simple XSD file defining my XML schema. The complex types within the XSD take advantage of inheritance using the <xs:extension>
tags. The problem I having is that I need all complex types to generate Java Classes with the @XmlRootElement
.
Unfortunately, the way in which XJC generates the classes means that only derived class gets the @XmlRootElement
(not the base class). I am using the simple global binding directive to ensure that it solves many of the other issues that I have faced with XJC.
Here is an example snippet of the XSD:
<xs:schema version="1.0" targetNamespace="http://www.knowledgemill.com/kmcs" xmlns:kmcs="http://www.knowledgemill.com/kmcs" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jaxb:extensionBindingPrefixes="xjc" elementFormDefault="qualified"> <xs:annotation> <xs:appinfo> <jaxb:globalBindings> <xjc:simple /> </jaxb:globalBindings> </xs:appinfo> </xs:annotation> <xs:element name="Artifact" type="kmcs:Artifact"/> <xs:element name="EmailArtifact" type="kmcs:EmailArtifact"/> <xs:complexType name="Artifact"> <xs:sequence> <xs:element name="artifactId" type="xs:string" minOccurs="0"/> <xs:element name="artifactType" type="xs:string" minOccurs="0"/> <xs:element name="contentHash" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="EmailArtifact"> <xs:complexContent> <xs:extension base="kmcs:Artifact"> <xs:sequence> <xs:element name="subject" type="xs:string" minOccurs="0"/> <xs:element name="threadSubject" type="xs:string" minOccurs="0"/> <xs:element name="from" type="xs:string" minOccurs="0"/> <xs:element name="to" type="xs:string" minOccurs="0"/> <xs:element name="cc" type="xs:string" minOccurs="0"/> <xs:element name="bcc" type="xs:string" minOccurs="0"/> <xs:element name="messageId" type="xs:string" minOccurs="0"/> <xs:element name="date" type="xs:date" minOccurs="0"/> <xs:element name="size" type="xs:long" minOccurs="0"/> <xs:element name="hasAttachment" type="xs:boolean" minOccurs="0"/> <xs:element name="sensitivity" type="xs:string" minOccurs="0"/> <xs:element name="headerHash" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:extension> </xs:complexContent> </xs:complexType> </xs:schema>
As we can see from the above snippet, EmailArtifact
extends Artifact
.
The java class code for EmailArtifact
contains the following:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "EmailArtifact", propOrder = { "subject", "threadSubject", "from", "to", "cc", "bcc", "messageId", "date", "size", "hasAttachment", "sensitivity", "headerHash" }) @XmlSeeAlso({ ExtendedEmail.class }) @XmlRootElement(name = "EmailArtifact") public class EmailArtifact extends Artifact { protected String subject; protected String threadSubject; protected String from; protected String to; protected String cc; protected String bcc; protected String messageId; @XmlSchemaType(name = "date") protected XMLGregorianCalendar date; protected Long size; protected Boolean hasAttachment; protected String sensitivity; protected String headerHash;
The java class code for Artifact
contains the following:
@XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "Artifact", propOrder = { "artifactId", "artifactType", "contentHash" }) @XmlSeeAlso({ ManagedDocArtifact.class, EmailArtifact.class }) public class Artifact { protected String artifactId; protected String artifactType; protected String contentHash;
In the EmailArtifact
we can see that it contains the @XmlRootElement
but the base type Artifact
does not contain @XmlRootElement
.
How can you force XJC to generate @XmlRootElement
for all classes including the base types.
Open a command prompt. Run the JAXB schema compiler, xjc command from the directory where the schema file is located. The xjc schema compiler tool is located in the app_server_root \bin\ directory. Use the generated JAXB objects within a Java application to manipulate XML content through the generated JAXB classes.
Generate a Java class from an XML Schema using JAXB In the active editor tab, open the desired Schema . xsd file or an XML document, which contains the desired Schema. In the main menu, go to Tools | XML Actions | Generate Java Code From XML Schema Using JAXB.
XJC is a Java SE tool that compiles an XML schema file into fully annotated Java classes. It is distributed within the JDK package and is located at /bin/xjc path.
Just bind using xjb-file:
<?xml version="1.0"?> <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema"> <jxb:bindings schemaLocation="path/to/myschema.xsd" node="/xs:schema"> <jxb:globalBindings> <xjc:simple /> </jxb:globalBindings> </jxb:bindings> </jxb:bindings>
And don't forget to define element of the same type:
<xs:complexType name="Artifact" /> <xs:element name="artifact" type="Artifact">
This question references a blog post by Kohsuke Kawaguchi, formerly worked on the JAX-B or JAX-WS RI, that talks about the RI's decision making process and lack of clarity on this issue in the spec.
The blog post mentions that the simple binding feature is part of the RI. Are you using the RI to generate your code?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With