We were trying to generate JAXB classes using gradle, xsd and xjc, and JAXB classes should have XmlRootElement annotations so it could be used to expose as web service reponse. We were following this link http://azagorneanu.blogspot.com/2011/09/configure-maven-to-generate-classes.html, it helped in great deal but we were unable to find one particular example with gradle only. So we figured out few things what we will share as an answer.
How to generate jaxb classes from xsd using gradle, jaxb and xjc, classes should have XmlRootElement
8 Answers
build.gradle should look like below
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "net.saliman:gradle-cobertura-plugin:2.2.4"
classpath 'com.github.jacobono:gradle-jaxb-plugin:1.3.5'
}
}
apply plugin: 'com.github.jacobono.jaxb'
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.7'
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics-ant:0.6.5"
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics:0.6.4"
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics-annotate:0.6.4"
}
configurations {
jaxb
}
task jaxb(){
description 'Converts xsds to classes'
def jaxbTargetDir = file("generated")
doLast {
jaxbTargetDir.mkdirs()
ant.taskdef(name: 'xjc', classname: 'org.jvnet.jaxb2_commons.xjc.XJC2Task', classpath: configurations.jaxb.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(destdir: '${jaxbTargetDir}', package: 'com.sample.jaxbclasses', schema:'generated/schema.xsd', binding:'generated/binding.xjb', extension:'true'){
arg(value: "-Xannotate")
}
}
}
schema.xsd
<xs:element name="user" type="user" />
<xs:element name="userList" type="userList" />
<xs:complexType name="user">
<xs:all>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="name" type="xs:string" />
<xs:element name="registrationDate" type="xs:dateTime" />
</xs:all>
</xs:complexType>
<xs:complexType name="userList">
<xs:sequence>
<xs:element name="user" type="user" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:schema>
binding.xjb
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jaxb:globalBindings>
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
<!-- Force all classes implements Serializable -->
<xjc:serializable uid="1" />
</jaxb:globalBindings>
<!-- Annotate the following classes with XmlRootElement -->
<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[@name='user']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="user" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="xs:complexType[@name='userList']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="userList" />
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
below binding.xjb could be used as well
<?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="schema.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple />
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>
Now you can run the task 'jaxb', All set. Cheers!
User.java
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.7
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2017.01.26 at 11:59:18 AM EST
//
package com.sample.jaxbclasses;
import java.io.Serializable;
import java.util.Calendar;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* <p>Java class for user complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <all>
* <element name="id" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
* <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="registrationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
* </all>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {
})
@XmlRootElement(name = "user")
public class User
implements Serializable
{
private final static long serialVersionUID = 1L;
protected Long id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected Calendar registrationDate;
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link Long }
*
*/
public Long getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link Long }
*
*/
public void setId(Long value) {
this.id = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
/**
* Gets the value of the registrationDate property.
*
* @return
* possible object is
* {@link String }
*
*/
public Calendar getRegistrationDate() {
return registrationDate;
}
/**
* Sets the value of the registrationDate property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRegistrationDate(Calendar value) {
this.registrationDate = value;
}
}

- 655
- 1
- 8
- 27
All of the other answers are outdated as of the time of this writing.
- Since Java EE was rebranded to Jakarta EE, JAXB is now provided by new artifact
jakarta.xml.bind:jakarta.xml.bind-api
. - JAXB runtime is given by
org.glassfish.jaxb:jaxb-runtime
. - XJC compiler is given by
org.glassfish.jaxb:jaxb-xjc
.
Jakarta XML Binding (previously called JAXB) Reference Implementation.
Putting it all together, a complete working example using Kotlin DSL:
val jaxb: Configuration by configurations.creating
val jaxbVersion: String by project
val schemaDir = "src/main/resources"
val xjcOutputDir = "$buildDir/generated/source/xjc/main"
dependencies {
jaxb("org.glassfish.jaxb:jaxb-xjc:$jaxbVersion")
implementation("jakarta.xml.bind:jakarta.xml.bind-api:$jaxbVersion")
runtimeOnly("org.glassfish.jaxb:jaxb-runtime:$jaxbVersion")
}
val createXjcOutputDir by tasks.register("createXjcOutputDir") {
doLast {
mkdir(xjcOutputDir)
}
}
val xjc by tasks.registering(JavaExec::class) {
// Directory needs to exist
dependsOn(createXjcOutputDir)
classpath = jaxb
mainClass.set("com.sun.tools.xjc.XJCFacade")
args = listOf(
"-d",
xjcOutputDir,
"-p",
project.group.toString(),
"-encoding",
"UTF-8",
"-no-header",
"-quiet",
schemaDir
)
}
tasks.withType<JavaCompile>().configureEach {
dependsOn(xjc)
}
sourceSets {
main {
java {
srcDirs(
files(xjcOutputDir) {
builtBy(xjc)
}
)
}
}
}

- 3,253
- 2
- 33
- 55

- 21,927
- 20
- 110
- 219
-
With Gradle 8.1.1 i had to change the scope of all dependencies to `jaxb` – leonardkraemer Jun 22 '23 at 16:09
-
@leonardkraemer Can you elaborate on that? What error did you get using the dependency scope as shown? – Abhijit Sarkar Jun 22 '23 at 17:38
-
I get `Exception in thread "main" java.lang.AssertionError: jakarta.xml.bind.JAXBException: Implementation of Jakarta XML Binding-API has not been found on module path or classpath.` Probably you have some plugin that prepares jaxb in your build. Also `val jaxbVersion: String by project` did not work for me. I had to set it to `4.0.0`. Also I within a spring-boot project. – leonardkraemer Jun 23 '23 at 08:03
-
@leonardkraemer I didn't use any plugin, if I did, there'd be no point in trying to generate the classes myself. As for `jaxbVersion`, it, of course, has to be defined in your `gradle.properties` to work. I suspect your problem is not really related to this answer. If you wish, you can provide a [minimum, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) for me to look into, otherwise, we will leave it here. – Abhijit Sarkar Jun 23 '23 at 08:07
-
I dont have a problem that needs solving. I just wanted to add to the answer. Maybe so runs into the same problem and my comment helps. Thank you for being so responsive. – leonardkraemer Jun 23 '23 at 08:14
-
Hey @leonardkraemer, I actually run into this problem. I am not familiar with Kotlin DSL, so can you tell me, what you mean by "I had to change the scope of all dependencies to jaxb"? Thanks! – Teneko Jul 07 '23 at 16:26
-
in the `dependencies`-block I had to change both `implementation` and `runtimeOnly` to `jaxb` to make the job work. – leonardkraemer Jul 10 '23 at 06:30
group 'com.example'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
project.ext {
jaxbTargetDir = file("src/generated/java")
}
configurations {
xsd2java
}
dependencies {
xsd2java "com.sun.xml.bind:jaxb-xjc:2.2.6"
xsd2java "com.sun.xml.bind:jaxb-impl:2.2.6"
}
task xsd2java() {
doLast {
jaxbTargetDir.mkdirs()
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.xsd2java.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(
destdir: '${jaxbTargetDir}',
package: 'com.example.request',
schema: 'src/main/resources/XMLreq.xsd'
)
ant.xjc(
destdir: '${jaxbTargetDir}',
package: 'com.example.response',
schema: 'src/main/resources/XMLres.xsd'
)
}
}
compileJava.dependsOn xsd2java

- 5,465
- 12
- 60
- 112
-
In case you have multple .xsd files, one reference to these other, you need to add this `System.setProperty('javax.xml.accessExternalSchema', 'all')` to your `doLast()` – tuan.dinh Aug 19 '20 at 02:37
My version use gradle native feature to generate jaxbclasses.
Optionally, if case your schema depends on external xsd(s), use "Oasis Catalog" technique to resolve external XSD locally. Also in this case disable XML schema validations to prevent validation errors.
Optionally you can adjust your jaxbclasses with a custom jaxb binding. (Jaxb-bindings.xjb)
Basically is a gradle custom task, which invoke the XJCTask ant task available in Java VM, in my example libraries are from Java 8. Task name is "generateSources", and need to be adjusted to your schema location.
configurations {
jaxb // Only for generation purpose
}
dependencies {
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-osgi:2.2.11'
}
task generateSources() {
doLast {
def jaxbTargetDir = file("$buildDir/generated/src/main/java")
if (!jaxbTargetDir.exists()) {
jaxbTargetDir.mkdirs()
}
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.jaxb.asPath)
ant.xjc(
destdir: "${jaxbTargetDir}",
schema: "${projectDir}/src/main/resources/MySchema.xsd",
binding: "${projectDir}/src/main/resources/jaxb-bindings.xjb",
catalog: "${projectDir}/src/main/resources/catalog.xml",
removeOldOutput: 'yes', extension: 'true'
)
{
arg(line: '-nv -disableXmlSecurity')
}
}
}
In case you need catalog create a file "catalog.xml" which might look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd" uri="xenc-schema.xsd" />
<system systemId="http://www.w3.org/TR/xmlenc-core/xenc-schema.xsd" uri="xenc-schema.xsd" />
<system systemId="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd" uri="xmldsig-core-schema.xsd" />
</catalog>
For jaxbinding
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<xjc:javaType
adapter="org.gazpachoquest.sample.JodaLocalDateTimeConverter"
name="org.joda.time.LocalDateTime" xmlType="xs:dateTime" />
</globalBindings>
</bindings>
If in addition to jaxb generation, you need to include those classes to build. You need to adjust gradle source layout, and dependencies.
apply plugin: 'java'
def generatedSourcesOutput = "$buildDir/generated/main/java"
sourceSets {
main {
java.srcDirs "$generatedSourcesOutput"
}
}
configurations {
jaxb
}
dependencies {
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-osgi:2.2.11'
compile 'com.sun.xml.bind:jaxb-xjc:2.2.11'
compile 'com.sun.xml.bind:jaxb-impl:2.2.11'
compile 'javax.xml.bind:jaxb-api:2.2.11'
}
compileJava {
dependsOn generateSources
}
That's all!

- 1,713
- 15
- 15
Gradle configuration for using gradle-jaxb-plugin
The commented out values in the xjc configuration are the default values - change if required.
buildscript {
repositories gradle.repos
dependencies {
}
}
plugins {
id "org.openrepose.gradle.plugins.jaxb" version "2.5.0"
id 'groovy'
id 'java'
id "org.springframework.boot" version "2.1.2.RELEASE"
id 'checkstyle'
}
apply plugin: 'io.spring.dependency-management'
apply plugin: "org.openrepose.gradle.plugins.jaxb"
apply plugin: 'idea'
apply plugin: 'maven-publish'
repositories gradle.repos
configurations {
jaxb
codeq
compile.exclude module: "spring-boot-starter-tomcat"
}
jaxb {
xjc {
//taskClassname = 'com.sun.tools.xjc.XJC2Task'
//xsdDir = "${project.projectDir}/src/main/resources/schema"
generateEpisodeFiles = false
generatePackage = 'com.mycompany.mypackage'
destinationDir = "${buildDir}/generated/src/main/java"
args = ["-Xannotate"]
}
}
compileJava.dependsOn {
'xjc'
}
sourceSets {
main {
java {
srcDirs jaxb.xjc.destinationDir
}
resources {
srcDirs 'src/main/resources'
}
}
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudDependenciesVersion}"
}
}
dependencies {
// Jaxb dependencies
jaxb group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: jaxbxjcVersion
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.0.4'
jaxb 'org.slf4j:slf4j-log4j12:1.7.25'
implementation group: 'javax.xml.bind', name: 'jaxb-api', version: jaxbApiVersion
}
and gradle.properties file
# JAXB Processing Properties
jaxbPluginVersion = 2.5.0
jaxbxjcVersion = 2.3.2
jaxbApiVersion = 2.3.1
and to link it with Intellij add the following to your build.gradle file
idea.module.iml {
whenMerged {
dependsOn jaxb
}
}

- 5,457
- 2
- 48
- 62
I've been using the Spring Boot Producing a SOAP web service guide for reference. Here's the link to the build.gradle file in GitHub.
https://github.com/spring-guides/gs-producing-web-service/blob/master/complete/build.gradle

- 4,118
- 1
- 25
- 16
Here is a solution that works for me with Java 11 / Gradle 6. After updating the build system on one of my projects recently I found some issues using XJC via Ant tasks in Gradle - this approach just uses plain Gradle, without Ant.
UPDATE: Using the GlassFish implementation avoids issues with Sun internal dependencies, as per this question
sourceSets {
generated {
java.srcDir "$generated_dir"
}
}
dependencies {
compile sourceSets.generated.output
// Generated code depends on the JAXB API, which is removed from base Java in JDK 11
compile "org.glassfish.jaxb:jaxb-runtime:2.3.3"
generatedCompile "org.glassfish.jaxb:jaxb-runtime:2.3.3"
}
// XJC tasks
// JAXB configuration holds classpath for running the JAXB XJC compiler
configurations {
jaxb
}
dependencies {
jaxb "org.glassfish.jaxb:jaxb-xjc:2.3.3"
}
// Cookie cutter function for defining multiple XJC tasks
// (not necessary if you only have a single task)!
def addXjcTask(taskName, schema, pkg, dest) {
// If you haven't already, create the generated output dir before running XJC or it will fail
file(dest).mkdirs()
// The main XJC task, calls XJCFacade which is the entry point of the XJC JAR
tasks.create(name: taskName, type: JavaExec) {
classpath configurations.jaxb
main 'com.sun.tools.xjc.XJCFacade'
// To explore available args, download the XJC JAR manually and run java -jar jaxb-xjc.jar --help
args schema, "-p", pkg, "-d", dest
}
// Add a dependency on the new task so it gets invoked
compileGeneratedJava.dependsOn tasks.getByName(taskName)
}
// Add all the XJC tasks you need
addXjcTask("xjcSchema1",
"path/to/schema1.xsd",
'com.example.generated.schema1',
"$generated_dir")
addXjcTask("xjcSchema2",
"path/to/schema2.xsd",
'com.example.generated.schema2',
"$generated_dir")

- 61
- 3
-
Hello @Martin Traverse do you have git repo for this issue ? Since i'm facing same issue on JDK 11 and Gradle 6 – donny Aug 31 '20 at 02:51
-
That's what worked for me with Java 14 and Gradle 6.7 My build.gradle file looks like this:
buildscript {
repositories {
jcenter()
mavenCentral()
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'gradle.plugin.org.openrepose:gradle-jaxb-plugin:2.5.0'
}
}
apply plugin: 'org.openrepose.gradle.plugins.jaxb'
dependencies {
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics:1.11.1'
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-ant:1.11.1'
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.0.4'
jaxb 'org.slf4j:slf4j-log4j12:1.7.25'
jaxb 'org.glassfish.jaxb:jaxb-xjc:2.2.11'
jaxb 'org.glassfish.jaxb:jaxb-runtime:2.2.11'
jaxb 'javax.activation:activation:1.1.1'
}
jaxb {
println 'Starting JAXB XJC...'
xsdDir = "${projectDir}/src/main/resources/schemas/xsd"
xjc {
generateEpisodeFiles = false
destinationDir = "$buildDir/generated/sources/jaxb"
taskClassname = "org.jvnet.jaxb2_commons.xjc.XJC2Task"
generatePackage = "your.own.package.name"
args = ["-Xinheritance", "-Xannotate"]
}
}
// allow schemas with empty namespace
tasks.named("xsd-dependency-tree").configure {
outputs.upToDateWhen { false }
}
compileJava.dependsOn xjc

- 31
- 1
- 4