[JAXB] Generar xsd mediante schemagen

Iniciado por K-YreX, 18 Diciembre 2020, 12:53 PM

0 Miembros y 1 Visitante están viendo este tema.

K-YreX

He tenido problemas para generar un schema xsd a partir de unas clases .java mediante el comando schemagen.

Tenía las siguientes clases (todas ellas en el mismo directorio . para simplificar):

ConjuntoVehiculos
Vehiculo
Furgoneta extends Vehiculo
Coche extends Vehiculo

Entonces al ejecutar:
schemagen -d . -cp *.java -encoding utf-8
Se me generaba el schema xsd pero me aparecía el siguiente mensaje y no se incluía el elemento Coche en el schema.
Citar
ConjuntoVehiculos.java:14: error: cannot find symbol
                        @XmlElementRef(name = "Coche", type = Coche.class),
                                                                                             ^
    symbol:   class Coche
    location: class ConjuntoVehiculos
Esa anotación @XmlElementRef la tengo junto a otras dos que hacen referencia a Vehiculo y Furgoneta y estas otras no producen ningún problema. He comprobado los nombres y está todo bien escrito.

He hecho varias pruebas incluyendo los ficheros .java uno por uno y compilándolos primero (aunque por lo que he visto, schemagen debe llamar internamente a javac para compilar los ficheros fuente) pero obtenía más errores y no me generaba el schema.

Al final después de mucho probar me ha dado por compilar los ficheros .java (en el mismo directorio) y ejecutar:
schemagen -d . -cp . ConjuntoVehiculos.java -encoding utf-8
Con esto sí he conseguido generar el schema correctamente, sin errores e incluyendo todos los elementos pero no entiendo por qué ha funcionado. Es decir, no entiendo cómo funciona schemagen. He buscado en muchas webs y en todas aparece un ejemplo sencillo que funciona con el primer comando que he probado y no se explica nada más.

Espero que alguien conozca esta herramienta y pueda ayudarme. :-X

PD: Estoy utilizando schemagen 3.0.0 (recientemente descargado junto con las otras herramientas de JAXB).
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

rub'n

#1
Cita de: K-YreX en 18 Diciembre 2020, 12:53 PM
He tenido problemas para generar un schema xsd a partir de unas clases .java mediante el comando schemagen.

Tenía las siguientes clases (todas ellas en el mismo directorio . para simplificar):

ConjuntoVehiculos
Vehiculo
Furgoneta extends Vehiculo
Coche extends Vehiculo

Entonces al ejecutar:
schemagen -d . -cp *.java -encoding utf-8

El el mismo directorio cual? original del proyecto? o en otra carpeta ?

Cita de: K-YreX en 18 Diciembre 2020, 12:53 PM
He hecho varias pruebas incluyendo los ficheros .java uno por uno y compilándolos primero (aunque por lo que he visto, schemagen debe llamar internamente a javac para compilar los ficheros fuente) pero obtenía más errores y no me generaba el schema.

Tal cual doc asi mismo, es, cuando se compilan los .java estos pasan a ser .class que serán usados luego para crear los .xsd



rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen

K-YreX

Cita de: rub'n en 18 Diciembre 2020, 19:54 PM
El el mismo directorio cual? original del proyecto? o en otra carpeta ?
Para simplificarlo y no tener que lidiar con los paquetes originales del proyecto lo que hice fue copiar todos los .java en un directorio llamémoslo CodigoFuente/ y modifiqué la sentencia package y los imports de los .java (es decir, los eliminé). El directorio en el que estaba trabajando tenía la siguiente estructura:

CodigoFuente/
|_ ConjuntoVehiculos.java
|_ Vehiculo.java
|_ Coche.java
|_ Furgoneta.java

Entonces desde línea de comandos al ejecutar

C:\...\CodigoFuente>schemagen -d . -cp *.java -encoding utf-8

me generaba el fichero schema1.xsd en el directorio CodigoFuente/ pero salía en el cmd el error que cité en el otro mensaje de que no se reconocía el símbolo Coche.class y en el xsd me incluía correctamente todas las clases (como xs:element) menos la clase Coche que no aparecía.
Lo que me parece raro pues la clase Coche.java tiene prácticamente la misma estructura que Furgoneta.java (solo cambia algún atributo) y las anotaciones de ambas clases también son iguales. Me dio que pensar que quizás al pasar como argumento *.java se estuviesen compilando los ficheros en este orden:
1. Vehiculo.java -> Vehiculo.class
2. Furgoneta.java -> Furgoneta.class
3. ConjuntoVehiculos.java -> ConjuntoVehiculos.class
4. Coche.java -> Coche.class
Y quizás por eso al compilar ConjuntoVehiculos.java no se reconoce el símbolo Coche.class (porque todavía no existe).

Cita de: rub'n en 18 Diciembre 2020, 19:54 PM
Tal cual doc asi mismo, es, cuando compila los .java estos pasan a ser .class que sera usados luego para crear los .xsd
Respecto a esto, noté que aunque schemagen compile los .java en .class, estos no aparecen en el directorio en el que se está trabajando (CodigoFuente/ en este supuesto). Por eso intenté compilarlos yo y tras varios intentos vi que la única forma en que funcionaba es teniendo todos los ficheros compilados ya y pasar a schemagen únicamente el .java que contiene a los demás. Es decir, teniendo:

CodigoFuente/
|_ ConjuntoVehiculos.java
|_ ConjuntoVehiculos.class
|_ Vehiculo.java
|_ Vehiculo.class
|_ Coche.java
|_ Coche.class
|_ Furgoneta.java
|_ Furgoneta.class

Y ejecutando:
C:\...\CodigoFuente>schemagen -d . -cp ConjuntoVehiculos.java -encoding utf-8
Por lo tanto no entiendo cuándo es necesario compilar los .java a .class antes de ejecutar schemagen y qué argumentos hay que pasarle a schemagen con la opción -cp. :huh:

PD: Gracias por responder. Siendo un tema tan raro ya pensaba que no iba a tener respuestas.  :-X
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

rub'n

Y tu clases java como están?

Como usas la anotacion @XmlRootElement ?


rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen

K-YreX

Fichero ConjuntoVehiculos.java
Código (java) [Seleccionar]

@XmlRootElement(name = "vehiculos")
@XmlAccessorType(XmlAccessType.FIELD)
public class ConjuntoVehiculos {
  @XmlElementRefs({
    @XmlElementRef(name = "Vehiculo", type = Vehiculo.class),
    @XmlElementRef(name = "Coche", type = Coche.class),
    @XmlElementRef(name = "Furgoneta", type = Furgoneta.class)
  })
  private ArrayList<Vehiculo> vehiculos;
  //...
}


Fichero Vehiculo.java
Código (java) [Seleccionar]

@XmlRootElement(name = "Vehiculo")
@XmlAccessorType(XmlAccessType.FIELD)
public class Vehiculo implements Serializable {
  //...
}


Fichero Coche.java
Código (java) [Seleccionar]

@XmlRootElement(name = "Coche")
@XmlAccessorType(XmlAccessType.FIELD)
public class Coche extends Vehiculo {
  //...
}


Fichero Furgoneta.java
Código (java) [Seleccionar]

@XmlRootElement(name = "Furgoneta")
@XmlAccessorType(XmlAccessType.FIELD)
public class Furgoneta extends Vehiculo {
  //...
}


Y el schema xsd que quiero obtener es:
Código (xml) [Seleccionar]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="Coche" type="coche"/>

  <xs:element name="Furgoneta" type="furgoneta"/>

  <xs:element name="Vehiculo" type="vehiculo"/>

  <xs:element name="Vehiculos" type="conjuntoVehiculos"/>

  <xs:complexType name="conjuntoVehiculos">
    <xs:sequence>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="Vehiculo"/>
        <xs:element ref="Coche"/>
        <xs:element ref="Furgoneta"/>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="vehiculo"><!-- ... --></xs:complexType>
 
  <xs:complexType name="coche"><!-- ... --></xs:complexType>

  <xs:complexType name="furgoneta"><!-- ... --></xs:complexType>
</xs:schema>


Pero como no reconoce la clase Coche.class, me genera el siguiente xsd:
Código (xml) [Seleccionar]

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="Furgoneta" type="furgoneta"/>

  <xs:element name="Vehiculo" type="vehiculo"/>

  <xs:element name="Vehiculos" type="conjuntoVehiculos"/>

  <xs:complexType name="conjuntoVehiculos">
    <xs:sequence>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="Vehiculo"/>
        <xs:element ref="Furgoneta"/>
      </xs:choice>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="vehiculo"><!-- ... --></xs:complexType>

  <xs:complexType name="furgoneta"><!-- ... --></xs:complexType>
</xs:schema>
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

rub'n

que tal doc? que es la que hay?

quitale el
Código (java) [Seleccionar]
@XmlRootElement a las superclases y avisa que tal... o sea a la superclase Vehiculo


rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen

K-YreX

Cita de: rub'n en 21 Diciembre 2020, 18:02 PM
que tal doc? que es la que hay?

quitale el
Código (java) [Seleccionar]
@XmlRootElement a las superclases y avisa que tal... o sea a la superclase Vehiculo
He probado el cambio que comentas y el resultado sigue sin ser satisfactorio. El error que aparecía sigue apareciendo y además ahora tampoco aparece el elemento Vehiculo en el xsd.
El resultado es el siguiente:
Código (xml) [Seleccionar]

  <xs:element name="Furgoneta" type="furgoneta"/>

  <xs:element name="Vehiculos" type="conjuntoVehiculos"/>

  <xs:complexType name="conjuntoVehiculos">
    <xs:sequence>
        <xs:element ref="Furgoneta" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <!-- ... -->
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

rub'n

Cita de: K-YreX en 22 Diciembre 2020, 01:17 AM
He probado el cambio que comentas y el resultado sigue sin ser satisfactorio. El error que aparecía sigue apareciendo y además ahora tampoco aparece el elemento Vehiculo en el xsd.
El resultado es el siguiente:
Código (xml) [Seleccionar]

  <xs:element name="Furgoneta" type="furgoneta"/>

  <xs:element name="Vehiculos" type="conjuntoVehiculos"/>

  <xs:complexType name="conjuntoVehiculos">
    <xs:sequence>
        <xs:element ref="Furgoneta" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
  </xs:complexType>

  <!-- ... -->


Mmmm, bueno, mejor probare eso tambien, sin hablar tanto, ando con chamba bastante. si logras resolver antes genial.


rubn0x52.com KNOWLEDGE  SHOULD BE FREE!!!
If you don't have time to read, you don't have the time (or the tools) to write, Simple as that. Stephen