How to compile multiple xsd files in Gradle JAXB/XJC?

19,879

Solution 1

I solved it myself. Here is the working solution.

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Task : XJC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
final def packageName = "org.test.webservice.domain"
final def schemaDir = "misc/resources/schemas/employee-sda-v3/wadl"

configurations { provided }
project.ext.generatedSrcDir = file("$buildDir/generated-src")
dependencies {
    provided 'com.sun.xml.bind:jaxb-impl:2.2.6'
    provided 'com.sun.xml.bind:jaxb-xjc:2.2.6'
}
task jaxb {
    println 'Starting JAXB XJC...'
    ext {
        packagePath = packageName.replaceAll("\\.", "/")
        destDir = new File(project.ext.generatedSrcDir, packagePath)
    }

    outputs.dir destDir
    project.ext.generatedSrcDir.mkdirs()
    ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.provided.asPath)

    doLast {
        project.ext.generatedSrcDir.mkdirs()
        ant.xjc(package: packageName, destdir: project.ext.generatedSrcDir){
            schema(dir: ${schemaDir}, includes: "**/*.xsd")
        }
    }

    task generateSources() {}
    sourceSets.main.java.srcDirs += project.ext.generatedSrcDir
    generateSources.dependsOn jaxb
    compileJava.dependsOn generateSources
    eclipseClasspath.dependsOn generateSources
//    ideaClasspath.dependsOn generateSources
}

Solution 2

jacobono's gradle-jaxb-plugin compiles all schemas in the input directory. I find this plugin more stable than Ant XJC. In my project, on some machines Ant XJC does not generate classes for no reason, although the results is successful. Maybe this is matter of configuration but IMHO even setup is easier with the plugin.

Solution 3

This could be the easiest solution without any external plugin. Does it have any other impact?

task prepareXSD2Java{

    def xsdSourceDir = xsdPackageName.replace(".","/")

    FileTree xsdFilesTree = fileTree(dir: "$projectResourceDir/$xsdSourceDir")
    xsdFilesTree.include '*.xsd'


    doLast{
        xsdFilesTree.getFiles().each {
            File xsdFile -> 
            def xsdPackageExt = xsdFile.name.replace("-","_")
            xsdPackageExt = xsdPackageExt.take(xsdPackageExt.lastIndexOf("."))
            String xsdFileName = xsdFile.getAbsolutePath();

            exec {
                executable = "xjc"
                args = [ "-d", "$projectSourceDir", "-p", 
                       "$xsdPackageName.$xsdPackageExt", "$xsdFileName" ]
            }
        }
    }

}

Solution 4

Here is one more working example. I put complete version of my build.gradle file. You can setup directory and include filter on schema inside of xjc. if you have 'nested "$" element is not supported' error like above, then below my example will help

apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'idea'

sourceCompatibility = 1.8
targetCompatibility = 1.8

task genJaxb {
    ext.sourcesDir = "${buildDir}/generated-sources/jaxb"
    ext.classesDir = "${buildDir}/classes/jaxb"
    ext.schemaDir = "${projectDir}/src/main/resources"

    outputs.dir classesDir

    doLast() {
        project.ant {
            taskdef name: "xjc", classname: "com.sun.tools.xjc.XJCTask",
                    classpath: configurations.jaxb.asPath
            mkdir(dir: sourcesDir)
            mkdir(dir: classesDir)

            xjc(destdir: sourcesDir) {
                schema(dir: schemaDir, includes: "**/*.xsd")
                arg(value: "-wsdl")
                produces(dir: sourcesDir, includes: "**/*.java")
            }

            javac(destdir: classesDir, source: 1.8, target: 1.8, debug: true,
                    debugLevel: "lines,vars,source",
                    classpath: configurations.jaxb.asPath,
                    includeantruntime: "false") {
                src(path: sourcesDir)
                include(name: "**/*.java")
                include(name: "*.java")
            }

            copy(todir: classesDir) {
                fileset(dir: sourcesDir, erroronmissingdir: false) {
                    exclude(name: "**/*.java")
                }
            }
        }
    }
}

jar {
    baseName = 'myProject'
    version = '0.0.1'
    from genJaxb.classesDir
}

repositories {
    mavenLocal()
    mavenCentral()
}

configurations {
    jaxb
}

dependencies {
    compile("com.google.code.gson:gson:2.3",
            "commons-lang:commons-lang:2.6",
            "commons-collections:commons-collections:3.2.1",
            "commons-codec:commons-codec:1.10",
            "commons-io:commons-io:2.4",
            "org.springframework.ws:spring-ws-core:2.2.1.RELEASE"
            )
    compile("wsdl4j:wsdl4j:1.6.1")
    jaxb("com.sun.xml.bind:jaxb-xjc:2.2.4-1")
    compile(files(genJaxb.classesDir).builtBy(genJaxb))
    testCompile("junit:junit",
                "org.powermock:powermock-api-mockito:1.6.2",
                "org.powermock:powermock-module-junit4:1.6.2",
                )
}

task wrapper(type: Wrapper) {
    gradleVersion = '1.11'
}
Share:
19,879
MFIhsan
Author by

MFIhsan

Java Aficionado - Writing softwares for various Wall St. firms for over 13+ years

Updated on June 15, 2022

Comments

  • MFIhsan
    MFIhsan almost 2 years

    I'm fairly new to Gradle and I am facing some issues trying to compile multiple schema files using Gradle Ant XJC.

    Using the below code, I'm able to compile 1 schema successfully. However, I'm not sure how to do the same for multiple schema files.

    Any advice please?

    //  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Task : XJC ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    final def packageName = "org.test.webservice.domain"
    final def schemaFile = "misc/resources/schemas/employee-v3/wadl/employee.xsd"
    
    configurations { provided }
    project.ext.generatedSrcDir = file("$buildDir/generated-src")
    dependencies {
        provided 'com.sun.xml.bind:jaxb-impl:2.2.6'
        provided 'com.sun.xml.bind:jaxb-xjc:2.2.6'
    }
    task jaxb {
        println 'Starting JAXB XJC...'
        ext {
            packagePath = packageName.replaceAll("\\.", "/")
            srcFile = file(schemaFile)
            destDir = new File(project.ext.generatedSrcDir, packagePath)
        }
    
        inputs.file srcFile
        outputs.dir destDir
        project.ext.generatedSrcDir.mkdirs()
        ant.taskdef(name: 'xjc',
                classname: 'com.sun.tools.xjc.XJCTask',
                classpath: configurations.provided.asPath)
    
        doLast {
            project.ext.generatedSrcDir.mkdirs()
            ant.xjc(schema: srcFile, package: packageName,
                    destdir: project.ext.generatedSrcDir)
        }
    
        task generateSources() {}
        sourceSets.main.java.srcDirs += project.ext.generatedSrcDir
        generateSources.dependsOn jaxb
        compileJava.dependsOn generateSources
        eclipseClasspath.dependsOn generateSources
    //    ideaClasspath.dependsOn generateSources
    }