I'm trying to migrate to a newer version of an API we use and therefore had to exchange some XSDs. The main difference is that most simple types are now encapsulated within xsd:element
s.
Now, with the change, my JAXB XSD to Java class generator is somehow not creating classes from simple types containing enums like it did before. I'll give a full before/after example to clear out misunderstandings:
Before, we had a normal xsd:simpleType
:
<xsd:simpleType name="PriorityEnum" final="restriction">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="NORMAL" />
<xsd:enumeration value="LOW" />
<xsd:enumeration value="HIGH" />
</xsd:restriction>
</xsd:simpleType>
... which was then referenced by type
:
<xsd:complexType name="SecurityType">
<xsd:sequence>
...
<xsd:element name="PriorityEnum" type="dt:PriorityEnum" minOccurs="0" />
...
</xsd:sequence>
</xsd:complexType>
The generated output had the class SecurityType
with a field of enum PriorityEnum
.
Now, for the newer XSD, they put the xsd:simpleType
into a xsd:element
:
<xsd:element name="PriorityEnum">
<xsd:simpleType final="restriction">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="NORMAL" />
<xsd:enumeration value="LOW" />
<xsd:enumeration value="HIGH" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
... and reference it with ref
:
<xsd:complexType name="SecurityType">
<xsd:sequence>
...
<xsd:element ref="dt:PriorityEnum" minOccurs="0" />
...
</xsd:sequence>
</xsd:complexType>
The generated output still has the class SecurityType
, but the field is now of type String
...
My build.gradle
contains the following task for generating classes:
def myXsd = "myxsd-v5.xsd"
def myOutput = "$buildDir/generated/jaxb/model/src/main/java"
tasks.register('generateSources') {
doLast {
def jaxbTargetDir = file("$myOutput")
if (!jaxbTargetDir.exists()) {
jaxbTargetDir.mkdirs()
}
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.jaxb.asPath)
ant.xjc(
destdir: "${jaxbTargetDir}",
schema: "${rootDir}/src/main/resources/xsd/${myXsd}",
removeOldOutput: 'yes', extension: 'true'
) {
arg(line: '-nv -disableXmlSecurity')
}
}
}
tasks.compileJava.dependsOn tasks.openApiGenerate, tasks.generateSources
I'm using the newest version for all JAXB dependencies, 2.3.1
. Is this maybe an issue with xjc
?
I resolved this with a bindings.xjb
:
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="apiXsd.xsd" node="/xs:schema">
<jxb:bindings node="//xs:element[@name='MyEnum']//xs:simpleType">
<jxb:typesafeEnumClass name="MyEnum" />
</jxb:bindings>
<jxb:bindings node="//xs:element[@name='AnotherEnum']//xs:simpleType">
<jxb:typesafeEnumClass name="AnotherEnum" />
</jxb:bindings>
<jxb:bindings node="//xs:element[@name='ThirdEnum']//xs:simpleType">
<jxb:typesafeEnumClass name="ThirdEnum" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
This needs one entry per class to generate, but it's better than manually adjusting the XSD whenever the API partner releases a new version with a new XSD.
The bindings.xjb
is included in the ant.xjc
:
ant.xjc(
destdir: "${targetDir}",
schema: "${xsdDir}/${xsdName}",
removeOldOutput: 'yes', extension: 'true'
) {
arg(line: '-nv -disableXmlSecurity')
binding(dir: "${xsdDir}", includes: 'bindings.xjb')
}