如何告诉 jaxb / Maven 生成多个模式包?

Posted

技术标签:

【中文标题】如何告诉 jaxb / Maven 生成多个模式包?【英文标题】:How can I tell jaxb / Maven to generate multiple schema packages? 【发布时间】:2011-02-20 20:58:41 【问题描述】:

例子:

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

发生了什么: Maven 执行第一个插件。然后删除目标文件夹并创建第二个包,然后可见。

我尝试为第一个配置设置 target/somedir1,为第二个配置设置 target/somedir2。但行为没有改变?有任何想法吗?我不想直接在 src/main/java 文件夹中生成包,因为这些包是生成的,不应该与手动创建的类混合。

【问题讨论】:

是的,这里遇到了同样的问题,尽管 Pascal 的解决方案工作得近乎完美。我现在需要的只是让 IDE 与生成的代码配合得很好,否则就是我想要的。 【参考方案1】:

我在 Maven 中使用 jaxb 时遇到了很多问题,但我设法通过执行以下操作解决了您的问题

首先创建一个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>

包名可以是任何你想要的名字,只要它不包含Java中的任何保留关键字

接下来您必须创建 wsimport.bat 脚本以在首选位置生成打包和代码。

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

如果不想用cd,可以把wsimport.bat放到"C:\YOUR\PATH\TO\PLACE\THE\PACKAGES"

如果你在没有 -keep -verbose 的情况下运行它,它只会生成包而不是 .java 文件。

-b 将确保在生成时使用 schema.xjc

【讨论】:

【参考方案2】:

经过多次尝试,以下对我有用

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

【讨论】:

【参考方案3】:

This is fixed in version 1.6 of the plugin.

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

不过,请注意,我注意到第一次迭代输出被删除了。我通过在每个执行中添加以下内容来修复它。

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

这是我的完整工作示例,每次迭代都正确输出。顺便说一句,由于给我的 xsd 存在重复的命名空间问题,我不得不这样做。这似乎解决了我的问题。

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

【讨论】:

【参考方案4】:

您还可以使用 JAXB 绑定为每个模式指定不同的包,例如

<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.***.book" />
    </jaxb:schemaBindings>

</jaxb:bindings>

然后只需在pom.xml 中使用新的maven-jaxb2-plugin 0.8.0 &lt;schemas&gt;&lt;bindings&gt; 元素。或者在&lt;schemaDirectory&gt;&lt;bindingDirectory&gt; 中指定最顶层的目录,并通过&lt;include&gt; 指定您的架构和绑定:

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

我认为这是更方便的解决方案,因为添加新的 XSD 时不需要更改 Maven pom.xml,只需将新的 XJB 绑定文件添加到同一目录即可。 p>

【讨论】:

虽然提供语法高亮提示的编辑微不足道,但确实提高了帖子的易读性 好的,感谢您的解释。我没有得到编辑添加语法突出显示。 这对我来说是最好的答案,因为我不想在每次添加新架构时都更改 pom。 这里的一个问题是 book 和 person 在 xsd 中是否位于同一个目标命名空间中。假设他们有书籍、期刊、报纸等,所有这些都包括可发布的.xsd。它们必须与可发布的名称空间相同,因此彼此必须位于相同的名称空间中,现在这会中断,因为每个名称空间只能有一个 schemaBindings。我同意它是理想的,我希望它适用于上面的示例,但是 JAXB 不够灵活。【参考方案5】:

对此还有另一种明确的 (IMO) 解决方案 有一个名为"staleFile" 的参数用作标志以不再生成东西。只需在每次执行中更改它即可。

【讨论】:

【参考方案6】:

我已经解决了:

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

将此添加到每个配置中;)

【讨论】:

您也可以只将其添加到&lt;executions&gt; 标记中。这就足够了。 &lt;removeOldOutput&gt; 默认设置为 false。但我在static.highsource.org/mjiip/maven-jaxb2-plugin/… 找不到&lt;clearOutputDir&gt; 对我来说真正的解决方案,因为您可以在同一个文件夹中生成所有内容 &lt;clearOutputDir&gt;false&lt;/clearOutputDir&gt; 对我来说已经足够了。【参考方案7】:

这也可以通过为模式指定陈旧的文件名而不清除输出目录来实现。默认的输出目录自动包含在类路径中,不太方便。如果我们指定不同的输出目录,则必须注意类路径才能在 IDE 中使用此代码。比如——

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

来源:Generating Code with JAXB Plugin

【讨论】:

【参考方案8】:

您应该将其更改为仅定义一次插件并执行两次执行区域...如下所示...并且应该设置 generateDirectory(基于文档)..

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

在我看来,您正在与 maven 的单一工件规则作斗争......也许您应该考虑一下。

【讨论】:

每个模块规则一个工件是真的,但是...... OP 没有生成两个工件。【参考方案9】:

我必须指定不同的generateDirectory(没有这个,插件认为文件是最新的,并且在第二次执行期间没有生成任何东西)。我建议对生成的源遵循target/generated-sources/&lt;tool&gt; 约定,以便将它们自动导入您喜欢的IDE。我还建议声明几个 execution 而不是两次声明插件(并在每个 execution 元素中移动 configuration):

<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.***.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.***.package2</generatePackage>
        <generateDirectory>$project.build.directory/generated-sources/xjc2</generateDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

使用此设置,我在mvn clean compile 之后得到以下结果

$树目标/ 目标/ ├── 班级 │   ├── com │   │   └── *** │   │   ├── App.class │   │   ├── package1 │   │   │   ├── ObjectFactory.class │   │   │   ├── Shiporder.class │   │   │   ├── Shiporder$Item.class │   │   │   └── Shiporder$Shipto.class │   │   └── package2 │   │   ├── BookForm.class │   │   ├── BooksForm.class │   │   ├── ObjectFactory.class │   │   └── package-info.class │   ├── dir1 │   │   └── shiporder.xsd │   └── dir2 │   └── books.xsd └── 生成源 ├── xjc │   └── META-INF │   └── sun-jaxb.episode ├── xjc1 │   └── com │   └── *** │   └── package1 │   ├── ObjectFactory.java │   └── Shiporder.java └── xjc2 └── com └── 堆栈溢出 └── 包2 ├── BookForm.java ├── BooksForm.java ├── ObjectFactory.java └── 包信息.java

这似乎是预期的结果。

【讨论】:

谢谢,我昨天确实遇到了同样的问题,但暂时放弃了。您的解决方案几乎可以完美运行,我现在唯一的问题是我无法让 Eclipse 无错误地编译。不过,在命令行上一切都很好。我目前的解决方法是我将目标中的这些文件夹声明为源文件夹,一切都很好。虽然我不确定我是否喜欢它,但我宁愿用生成的代码创建一个 jar 并直接使用它 eclipse 插件 m2eclipse 确实更新了构建路径。使用 mvc clean assembly:assembly 生成 bean 后,我只需运行 [右键单击项目] > [Maven] > [更新项目配置],它会更新构建路径。 @Newtopian 请参阅@M.R. 的评论,如果您遵循我提到的约定,m2eclipse 将为您执行此操作。 我知道这是个老问题,但我希望能回答我。我使用该代码并且它有效。但是当我想设置相同的包时,它总是只生成一个模式。例如,在第一次执行中我设置了 com.myproject.answer 并在第二次执行中设置了 com.myproject.request .. 并且在源生成之后我只有 *answer 包并且请求丢失了......知道如何解决它吗?生成我设置的目录也一样。 谢谢,我遇到了同样的问题,这对我来说非常有效:)

以上是关于如何告诉 jaxb / Maven 生成多个模式包?的主要内容,如果未能解决你的问题,请参考以下文章

在另一个 maven 项目中使用 JAXB2 生成 java 类

JAXB 3.0(Jakarta EE 9)是不是有任何 maven 插件?

如何使用 jaxb2-maven-plugin 2.x 从 WSDL 生成 Java 类?

如何使用 gradle 从 WSDL 和 XSD 生成类,相当于 maven-jaxb2-plugin

如何配置 IntelliJ IDEA 和/或 Maven 以使用 jaxb2-maven-plugin 生成的 Java 源代码自动添加目录?

从 xsd 生成 maven-jaxb2-plugin 类(版本错误)