Search code examples
xsdjaxbbazel

Bazel Build: Generate java classes from XSD using JAXB2


I am new to Bazel. I want to generate Java classes from an XSD document using JaxB2. I could not find any Java_Rule to auto-generate the classes. Looking at this google group discussion, a genrule with explicit command seems to generate java classes for the author.

I tried using the github repository suggested in the discussion but failed with no such target '@local_jdk//:jdk-default': target 'jdk-default' not declared in package ' error.

➜  bazel-xjc-master bazel build //...
ERROR: /Users/<user>/bazel-xjc-master/BUILD.bazel:1:8: no such target '@local_jdk//:jdk-default': target 'jdk-default' not declared in package '' (did you mean 'jre-default'?) defined by /private/var/tmp/.../local_jdk/BUILD.bazel and referenced by '//:sample-messages'
ERROR: Analysis of target '//:sample-messages' failed; build aborted: Analysis failed
INFO: Elapsed time: 0.152s
INFO: 0 processes.
FAILED: Build did NOT complete successfully (1 packages loaded, 6 targets configured)

I tried searchingjava_toolchain options to handle the above error but without any success.

Is there a Bazel build example file somewhere I can look at on how to generate java classes based on an XSD file?


Solution

  • The examples in the google group discussion were correct at the time, but Java toolchain integration with Bazel has changed over time, and indeed the target @local_jdk//:jdk-default no longer exists, and @local_jdk//:jar is deprecated.

    But the bigger issue is that jaxb and xjc have been deprecated/removed from the jdk starting with jdk 9: http://openjdk.java.net/jeps/320

    You'll need to get jaxb separately, something like this:

    BUILD.bazel:

    load("@rules_jvm_external//:defs.bzl", "artifact")
    
    genrule(
        name = "sample-messages",
        srcs = [
            "src/main/xsd/sample.xsd",
            "src/main/xjb/sample.xjb",
        ],
        outs = ["sample-messages.srcjar"],
        cmd = """
            mkdir sample-messages
            $(location :xjc) -quiet -d sample-messages -b $(location src/main/xjb/sample.xjb) -verbose $(location src/main/xsd/sample.xsd)
            jar cf $@ sample-messages
        """,
        exec_tools = [
            ":xjc",
        ],
    )
    
    java_binary(
        name = "xjc",
        # See bin/xjc.sh in
        # https://repo1.maven.org/maven2/com/sun/xml/bind/jaxb-ri/3.0.2/jaxb-ri-3.0.2.zip 
        main_class = "com.sun.tools.xjc.XJCFacade",
        runtime_deps = [
            artifact("com.sun.xml.bind:jaxb-ri:3.0.2"),
        ],
    )
    
    java_library(
        name = "sample-lib",
        srcs = [":sample-messages"],
        deps = [
            artifact("jakarta.xml.bind:jakarta.xml.bind-api:3.0.1"),
        ]
    )
    

    WORKSPACE:

    load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
    
    RULES_JVM_EXTERNAL_TAG = "4.2"
    RULES_JVM_EXTERNAL_SHA = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca"
    
    http_archive(
        name = "rules_jvm_external",
        strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG,
        sha256 = RULES_JVM_EXTERNAL_SHA,
        url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG,
    )
    load("@rules_jvm_external//:repositories.bzl", "rules_jvm_external_deps")
    rules_jvm_external_deps()
    load("@rules_jvm_external//:setup.bzl", "rules_jvm_external_setup")
    rules_jvm_external_setup()
    
    load("@rules_jvm_external//:defs.bzl", "maven_install")
    
    maven_install(
        artifacts = [
            "com.sun.xml.bind:jaxb-ri:3.0.2",
            "jakarta.xml.bind:jakarta.xml.bind-api:3.0.1",
        ],
        # rules_jvm_external doesn't handle zip dependencies correctly, see
        # https://github.com/bazelbuild/rules_jvm_external/issues/671
        excluded_artifacts = [
            "com.sun.xml.bind:jaxb-samples",
            "com.sun.xml.bind:jaxb-release-documentation",
        ],
        repositories = [
            "https://repo1.maven.org/maven2",
        ],
    )
    

    src/main/xjb/sample.xjb:

    <?xml version='1.0' encoding='UTF-8'?>
    <jxb:bindings version="3.0"
                  xmlns:jxb="https://jakarta.ee/xml/ns/jaxb"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:xs="http://www.w3.org/2001/XMLSchema"
                  xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd">
        <jxb:bindings schemaLocation="../xsd/sample.xsd" node="/xs:schema">
            <jxb:schemaBindings>
                <jxb:package name="org.acme.sample"/>
            </jxb:schemaBindings>
        </jxb:bindings>
    </jxb:bindings>
    

    src/main/xsd/sample.xsd:

    <?xml version="1.0" encoding="UTF-8" ?>
    <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    
    <xs:element name="Sample">
      <xs:complexType>
        <xs:sequence>
          <xs:element name="Date" type="xs:date"/>
          <xs:element name="Content">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Title" type="xs:string"/>
                <xs:element name="Note" type="xs:string" minOccurs="0"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
        <xs:attribute name="color" type="xs:string" use="required"/>
      </xs:complexType>
    </xs:element>
    
    </xs:schema>