¿Cómo puedo decirle a jaxb / Maven que genere múltiples paquetes de esquema?

80

Ejemplo:

</plugin>       
       <plugin>
           <groupId>org.jvnet.jaxb2.maven2</groupId>
           <artifactId>maven-jaxb2-plugin</artifactId>
           <version>0.7.1</version>
           <executions>
             <execution>
               <goals>
                 <goal>generate</goal>
               </goals>
             </execution>
           </executions>
            <configuration>
             <schemaDirectory>src/main/resources/dir1</schemaDirectory>
              <schemaIncludes>
                  <include>schema1.xsd</include>
              </schemaIncludes>
              <generatePackage>schema1.package</generatePackage>
           </configuration>
         </plugin>
          <plugin>
           <groupId>org.jvnet.jaxb2.maven2</groupId>
           <artifactId>maven-jaxb2-plugin</artifactId>
           <version>0.7.1</version>
           <executions>
             <execution>
               <goals>
                 <goal>generate</goal>
               </goals>
             </execution>
           </executions>
            <configuration>
             <schemaDirectory>src/main/resources/dir2</schemaDirectory>
              <schemaIncludes>
                  <include>schema2.xsd</include>
              </schemaIncludes>
              <generatePackage>schema2.package</generatePackage>
           </configuration>
         </plugin>
       </plugins>

Qué sucedió: Maven ejecuta el primer complemento. Luego elimina la carpeta de destino y crea el segundo paquete, que luego es visible.

Intenté establecer target / somedir1 para la primera configuración y target / somedir2 para la segunda configuración. ¿Pero el comportamiento no cambia? ¿Algunas ideas? No quiero generar los paquetes directamente en la carpeta src / main / java, porque estos paquetes se generan y no deben mezclarse con clases creadas manualmente.

SEÑOR
fuente
sí, tengo el mismo problema aquí, aunque la solución de Pascal funciona casi a la perfección. Todo lo que necesito ahora es hacer que el IDE funcione bien con el código generado; de lo contrario, es justo lo que quería.
Newtopian

Respuestas:

119

Tuve que especificar diferente generateDirectory(sin esto, el complemento consideraba que los archivos estaban actualizados y no generaban nada durante la segunda ejecución). Y recomiendo seguir la target/generated-sources/<tool>convención para las fuentes generadas para que se importen en su IDE favorito automáticamente. También recomiendo declarar varios en executionlugar de declarar el complemento dos veces (y mover el configurationinterior de cada executionelemento):

<plugin>
  <groupId>org.jvnet.jaxb2.maven2</groupId>
  <artifactId>maven-jaxb2-plugin</artifactId>
  <version>0.7.1</version>
  <executions>
    <execution>
      <id>schema1-generate</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <schemaDirectory>src/main/resources/dir1</schemaDirectory>
        <schemaIncludes>
          <include>shiporder.xsd</include>
        </schemaIncludes>
        <generatePackage>com.stackoverflow.package1</generatePackage>
        <generateDirectory>${project.build.directory}/generated-sources/xjc1</generateDirectory>
      </configuration>
    </execution>
    <execution>
      <id>schema2-generate</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <schemaDirectory>src/main/resources/dir2</schemaDirectory>
        <schemaIncludes>
          <include>books.xsd</include>
        </schemaIncludes>
        <generatePackage>com.stackoverflow.package2</generatePackage>
        <generateDirectory>${project.build.directory}/generated-sources/xjc2</generateDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

Con esta configuración, obtengo el siguiente resultado después de una mvn clean compile

$ árbol objetivo /
objetivo/
├── clases
│ ├── com
│ │ └── stackoverflow
│ │ ├── Clase de aplicación
│ │ ├── paquete1
│ │ │ ├── ObjectFactory.class
│ │ │ ├── Shiporder.class
│ │ │ ├── Orden de envío $ Item.class
│ │ │ └── Orden de envío $ Shipto.class
│ │ └── paquete2
│ │ ├── BookForm.class
│ │ ├── BooksForm.class
│ │ ├── ObjectFactory.class
│ │ └── paquete-info.class
│ ├── dir1
│ │ └── shiporder.xsd
│ └── dir2
│ └── libros.xsd
└── fuentes-generadas
    ├── xjc
    │ └── META-INF
    │ └── sun-jaxb.episodio
    ├── xjc1
    │ └── com
    │ └── stackoverflow
    │ └── paquete1
    │ ├── ObjectFactory.java
    │ └── Shiporder.java
    └── xjc2
        └── com
            └── desbordamiento de pila
                └── paquete2
                    ├── BookForm.java
                    ├── BooksForm.java
                    ├── ObjectFactory.java
                    └── package-info.java

Cuál parece ser el resultado esperado.

Pascal Thivent
fuente
gracias, en realidad tuve el mismo problema ayer pero momentáneamente lo abandoné. Su solución funciona casi a la perfección, mi único problema ahora es que no puedo hacer que Eclipse se compile sin errores. Sin embargo, todo está bien en la línea de comandos. Mi solución actual es que declaro estas carpetas en el destino como carpetas de origen y todo está bien ... aunque no estoy seguro de que me guste mucho, prefiero crear un frasco con el código generado y usarlo directamente
Newtopian
1
El complemento de eclipse m2eclipse actualiza la ruta de construcción. Después de generar los beans con mvc clean assembly: assembly, simplemente ejecuto [clic derecho en el proyecto]> [Maven]> [Actualizar configuración del proyecto] y actualiza la ruta de construcción.
MR
@Newtopian Vea el comentario de @ MR, m2eclipse lo hará por usted si sigue la convención que mencioné.
Pascal Thivent
hmm ok entonces, resulta que hago lo mismo que hice manualmente, solo que ahora solo toma uno o dos clics. Todavía es extraño ver el destino en las carpetas de origen, pero ahora es casi gratis, así que lo guardaré :-)
Newtopian
1
Sé que es una vieja pregunta pero espero que algo me responda. Yo uso ese código y funciona. Pero cuando quiero configurar el mismo paquete, siempre genera solo un esquema. Por ejemplo, en la primera ejecución configuré com.myproject.answer y en la segunda ejecución com.myproject.request ... y después de generar la fuente solo tengo * el paquete de respuesta y falta la solicitud ... ¿alguna idea de cómo solucionarlo? Generar directorio que configuré también igual.
Denis Stephanov
14

También puede utilizar enlaces JAXB para especificar un paquete diferente para cada esquema, por ejemplo

<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" schemaLocation="book.xsd">

    <jaxb:globalBindings>
        <xjc:serializable uid="1" />
    </jaxb:globalBindings>

    <jaxb:schemaBindings>
        <jaxb:package name="com.stackoverflow.book" />
    </jaxb:schemaBindings>

</jaxb:bindings>

Luego, use el nuevo maven-jaxb2-plugin 0.8.0 <schemas>y los <bindings>elementos en el pom.xml. O especificar el directorio superior en <schemaDirectory>y <bindingDirectory>y por <include>los esquemas y los enlaces:

<schemaDirectory>src/main/resources/xsd</schemaDirectory>
<schemaIncludes>
    <include>book/*.xsd</include>
    <include>person/*.xsd</include>
</schemaIncludes>
<bindingDirectory>src/main/resources</bindingDirectory>
<bindingIncludes>
    <include>book/*.xjb</include>
    <include>person/*.xjb</include>
</bindingIncludes>

Creo que esta es una solución más conveniente , porque cuando agrega un nuevo XSD no necesita cambiar Maven pom.xml, simplemente agregue un nuevo archivo de enlace XJB al mismo directorio.

xmedeko
fuente
Si bien es trivial, la edición para proporcionar una pista de resaltado de sintaxis mejora la legibilidad de la publicación
Kev
OK, gracias por la explicación. No he entendido que la edición agregó resaltado de sintaxis.
xmedeko
2
Esta es la mejor respuesta para mí, ya que no me gustaría seguir cambiando el pom cada vez que se agrega un nuevo esquema.
Ben Thurley
El único problema aquí es si el libro y la persona están en el mismo espacio de nombres de destino en el xsd. Digamos que en su lugar tenían un libro, un diario, un periódico, etc., todos los cuales incluían Publishable.xsd. Tendrían que estar en el mismo espacio de nombres que se pueden publicar y, por lo tanto, entre sí, y ahora esto se rompe porque solo puede tener un esquemaBindings por espacio de nombres. Estoy de acuerdo en que es ideal y desearía que funcionara para el ejemplo anterior, pero JAXB no es lo suficientemente flexible.
TurnipEntropy
8

debe cambiar eso para definir el complemento solo una vez y hacer dos áreas de ejecución ... como la siguiente ... y el generateDirectory debe establecerse (según los documentos) ...

<plugin>
  <groupId>org.jvnet.jaxb2.maven2</groupId>
  <artifactId>maven-jaxb2-plugin</artifactId>
  <version>0.7.1</version>
  <executions>
    <execution>
      <id>firstrun</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <generateDirectory>target/gen1</generateDirectory>
        <schemaDirectory>src/main/resources/dir1</schemaDirectory>
        <schemaIncludes>
          <include>schema1.xsd</include>
        </schemaIncludes>
        <generatePackage>schema1.package</generatePackage>
      </configuration>
    </execution>
    <execution>
      <id>secondrun</id>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <generateDirectory>target/gen2</generateDirectory>
        <schemaDirectory>src/main/resources/dir2</schemaDirectory>
        <schemaIncludes>
          <include>schema2.xsd</include>
        </schemaIncludes>
        <generatePackage>schema2.package</generatePackage>
      </configuration>
    </execution>
  </executions>
</plugin>

Me pareció que estás luchando contra la regla de un solo artefacto de maven ... quizás deberías pensar en esto.

Khmarbaise
fuente
La regla de un artefacto por módulo es cierta, pero ... el OP no genera dos artefactos.
Pascal Thivent
5

Esto también se puede lograr especificando un nombre de archivo obsoleto para los esquemas y no borrando el directorio de salida. El directorio de salida predeterminado se incluye automáticamente en classpath, lo cual es poco conveniente. Si especificamos un directorio de salida diferente, uno tiene que cuidar la ruta de clase para usar este código en IDE. Por ejemplo -

<plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.3.1</version>
            <configuration>
                <quiet>true</quiet>
                <verbose>false</verbose>
                <clearOutputDir>false</clearOutputDir>
                <readOnly>true</readOnly>
                <arguments>-mark-generated</arguments>
            </configuration>
            <executions>
                <execution>
                    <id>reportingSchema</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <schemaDirectory>src/main/resources/schema/r17/schemaReporting</schemaDirectory>
                        <schemaIncludes>
                            <include>OCISchemaReporting.xsd</include>
                        </schemaIncludes>
                        <packageName>com.broadsoft.oci.r17.reporting</packageName>
                        <staleFile>${build.directory}/generated-sources/.jaxb-staleFlag-reporting</staleFile>
                    </configuration>
                </execution>
                <execution>
                    <id>schemaAS</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <schemaDirectory>src/main/resources/schema/r17/schemaAS</schemaDirectory>
                        <schemaIncludes>
                            <include>OCISchemaAS.xsd</include>
                        </schemaIncludes>
                        <packageName>com.broadsoft.oci.r17.as</packageName>
                        <staleFile>${build.directory}/generated-sources/.jaxb-staleFlag-as</staleFile>
                    </configuration>
                </execution>
            </executions>
        </plugin>
</plugins>

Fuente: Generación de código con el complemento JAXB

Prashant C Chaturvedi
fuente
5

he resuelto con:

                        <removeOldOutput>false</removeOldOutput>
                        <clearOutputDir>false</clearOutputDir>
                        <forceRegenerate>true</forceRegenerate>

agregue esto a cada configuración;)

Davide Consonni
fuente
2
También puede agregarlo solo a la <executions>etiqueta. Eso es suficiente. <removeOldOutput>se establece en falso de forma predeterminada. Pero no puedo encontrarlo <clearOutputDir>en static.highsource.org/mjiip/maven-jaxb2-plugin/…
Para mí, la solución real, porque puede generar todo en la misma carpeta
MilacH
<clearOutputDir>false</clearOutputDir>fue suficiente para mí en mi caso.
Ruwanka Madhushan
3

Esto se corrige en la versión 1.6 del complemento .

            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.6</version>

Sin embargo, una nota rápida, noté que se estaba eliminando la salida de la primera iteración. Lo arreglé agregando lo siguiente a cada una de las ejecuciones.

                        <removeOldOutput>false</removeOldOutput>
                        <clearOutputDir>false</clearOutputDir>

Aquí está mi ejemplo de trabajo completo con cada iteración produciendo correctamente. Por cierto, tuve que hacer esto debido a un problema de espacio de nombres duplicado con el xsd que me dieron. Esto parece resolver mi problema.

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>jaxb2-maven-plugin</artifactId>
            <version>1.6</version>
            <executions>
                <execution>
                    <id>submitOrderRequest</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <extension>true</extension>
                        <schemaDirectory>src/main/resources/xsd/</schemaDirectory>
                        <!-- <schemaFiles>getOrderStatusResponse.xsd,quoteShippingRequest.xsd,quoteShippingResponse.xsd,submitOrderRequest.xsd,submitOrderResponse.xsd</schemaFiles> -->
                        <schemaFiles>submitOrderRequest.xsd</schemaFiles>
                        <bindingDirectory>${project.basedir}/src/main/resources/xjb</bindingDirectory>
                        <bindingFiles>submitOrderRequest.xjb</bindingFiles>
                        <removeOldOutput>false</removeOldOutput>
                        <clearOutputDir>false</clearOutputDir>
                    </configuration>
                </execution>
                <execution>
                    <id>submitOrderResponse</id>
                    <goals>
                        <goal>xjc</goal>
                    </goals>
                    <configuration>
                        <extension>true</extension>
                        <schemaDirectory>src/main/resources/xsd/</schemaDirectory>
                        <!-- <schemaFiles>getOrderStatusResponse.xsd,quoteShippingRequest.xsd,quoteShippingResponse.xsd,submitOrderRequest.xsd,submitOrderResponse.xsd</schemaFiles> -->
                        <schemaFiles>submitOrderResponse.xsd</schemaFiles>
                        <bindingDirectory>${project.basedir}/src/main/resources/xjb</bindingDirectory>
                        <bindingFiles>submitOrderResponse.xjb</bindingFiles>
                        <removeOldOutput>false</removeOldOutput>
                        <clearOutputDir>false</clearOutputDir>
                    </configuration>
                </execution>
            </executions>

        </plugin>
Chris Hinshaw
fuente
2

Lo siguiente funciona para mí, después de mucha prueba.

<plugin>
         <groupId>org.codehaus.mojo</groupId>
         <artifactId>jaxb2-maven-plugin</artifactId>
         <version>2.1</version>
         <executions>
            <execution>
              <id>xjc1</id>
              <goals>
                  <goal>xjc</goal>
              </goals>
             <configuration>
                <packageName>com.mycompany.clientSummary</packageName>
               <sourceType>wsdl</sourceType>
                <sources>
                <source>src/main/resources/wsdl/GetClientSummary.wsdl</source>
                </sources>
                <outputDirectory>target/generated-sources/xjb</outputDirectory>
                 <clearOutputDir>false</clearOutputDir>
            </configuration>
          </execution>

          <execution>
             <id>xjc2</id>
             <goals>
                 <goal>xjc</goal>
             </goals>
             <configuration>
                <packageName>com.mycompany.wsclient.employerProfile</packageName>
                <sourceType>wsdl</sourceType>
                <sources>
                <source>src/main/resources/wsdl/GetEmployerProfile.wsdl</source>
                </sources>
                <outputDirectory>target/generated-sources/xjb</outputDirectory>
                <clearOutputDir>false</clearOutputDir>
         </configuration>
         </execution>

         <execution>
            <id>xjc3</id>
            <goals>
                <goal>xjc</goal>
            </goals>
            <configuration>
                <packageName>com.mycompany.wsclient.producersLicenseData</packageName>
                <sourceType>wsdl</sourceType>
                <sources>
                <source>src/main/resources/wsdl/GetProducersLicenseData.wsdl</source>
                </sources>
                <outputDirectory>target/generated-sources/xjb</outputDirectory>
                <clearOutputDir>false</clearOutputDir>
            </configuration>
        </execution>


     </executions>
  </plugin>
Brian teggart
fuente
2

Encontré muchos problemas al usar jaxb en Maven, pero logré resolver su problema haciendo lo siguiente

Primero crea un archivo schema.xjc

<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               jaxb:version="2.0">
    <jaxb:bindings schemaLocation="YOUR_URL?wsdl#types?schema1">
        <jaxb:schemaBindings>
            <jaxb:package name="your.package.name.schema1"/>
        </jaxb:schemaBindings>
    </jaxb:bindings>
    <jaxb:bindings schemaLocation="YOUR_URL??wsdl#types?schema2">
        <jaxb:schemaBindings>
            <jaxb:package name="your.package.name.schema2"/>
        </jaxb:schemaBindings>
    </jaxb:bindings>
</jaxb:bindings>

El nombre del paquete puede ser cualquier cosa que desee, siempre que no contenga ninguna palabra clave reservada en Java

A continuación, debe crear el script wsimport.bat para generar su paquete y código en la ubicación preferida.

cd C:\YOUR\PATH\TO\PLACE\THE\PACKAGES
wsimport -keep -verbose -b "C:\YOUR\PATH\TO\schema.xjb" YOUR_URL?wsdl
pause

Si no desea utilizar el cd, puede poner wsimport.bat en "C: \ YOUR \ PATH \ TO \ PLACE \ THE \ PACKAGES"

Si lo ejecuta sin -keep -verbose, solo generará los paquetes, pero no los archivos .java.

-B se asegurará de que se use el schema.xjc al generar

Glenn Van Schil
fuente
0

Hay otra solución clara (IMO) para esto. Hay un parámetro llamado "staleFile" que se usa como bandera para no generar cosas nuevamente. Simplemente modifíquelo en cada ejecución.

Eugen-frito
fuente