Pregunta Cómo generar clases de jaxb desde xsd usando gradle, jaxb y xjc, las clases deberían tener XmlRootElement


Estábamos tratando de generar clases JAXB usando gradle, xsd y xjc, y las clases JAXB deberían tener anotaciones XmlRootElement para que se pudieran usar para exponer como respuesta del servicio web. Estábamos siguiendo este enlace http://azagorneanu.blogspot.com/2011/09/configure-maven-to-generate-classes.html, nos ayudó mucho, pero no pudimos encontrar un solo ejemplo en gradle. Así que descubrimos algunas cosas que compartiremos como respuesta.


9
2018-01-26 18:33


origen


Respuestas:


build.gradle debería verse como a continuación

    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>

debajo de binding.xjb podría usarse también

<?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>

Ahora puedes ejecutar la tarea 'jaxb', Todo listo. Aclamaciones!

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>
* &lt;complexType name="user">
*   &lt;complexContent>
*     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
*       &lt;all>
*         &lt;element name="id" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
*         &lt;element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
*         &lt;element name="registrationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
*       &lt;/all>
*     &lt;/restriction>
*   &lt;/complexContent>
* &lt;/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;
    }

}

8
2018-01-26 18:33



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

3
2017-09-01 08:58



Mi versión usa la función nativa de gradle para generar jaxbclasses.

Opcionalmente, si su esquema depende de xsd externo (s), use la técnica de "Catálogo de Oasis" para resolver localmente el XSD externo. También en este caso, deshabilite las validaciones de esquema XML para evitar errores de validación.

Opcionalmente puede ajustar sus jaxbclasses con un enlace jaxb personalizado. (Jaxb-bindings.xjb)

Básicamente es una tarea personalizada de Gradle, que invoca la tarea XJCTask y disponible en Java VM, en mis bibliotecas de ejemplo son de Java 8. El nombre de la tarea es "generateSources" y debe ajustarse a la ubicación de su esquema.

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')
                }
    }
}

En caso de que necesite un catálogo, cree un archivo "catalog.xml" que se vea así:

<?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>

Para 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>

Si además de la generación de jaxb, necesita incluir esas clases para compilar. Debe ajustar el diseño de la fuente de gradle y las dependencias.

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
}

¡Eso es todo!


2
2017-12-20 10:34