【问题标题】:Generating sources by running a project's java class in Maven通过在 Maven 中运行项目的 java 类来生成源代码
【发布时间】:2011-01-09 23:11:34
【问题描述】:

我正在将一个较大的 Ant 构建转换为 Maven。作为 Ant 构建的一部分,我们有几个步骤通过调用项目的一个类来创建 Java 类,简化为:

javac SomeGenerator.java
java  SomeGenerator  generated # generate classes in generated/
javac generated/*.java

我已将每个生成器拆分到其自己的 Maven 模块中,但我遇到了无法运行生成器的问题,因为它尚未在 generate-sources 阶段编译。

我尝试过类似的方法

        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>1.1.1</version>
            <executions>
                <execution>
                    <id>generate-model</id>
                    <goals>
                        <goal>java</goal>
                    </goals>
                    <phase>generate-sources</phase>

                    <configuration>
                        <mainClass>DTOGenerator</mainClass>
                        <arguments>
                            <argument>${model.generated.dir}</argument>
                        </arguments>
                    </configuration>
                </execution>
            </executions>
        </plugin>

很遗憾,由于上述原因,这不起作用。将代码生成器分别拆分为两个项目,一个用于编译生成器,另一个用于生成 DTO,这似乎有点过头了。

还有哪些选择?


使用 Maven 2.2.1。

【问题讨论】:

    标签: java maven-2 code-generation


    【解决方案1】:

    您可以在 generate-sources 阶段执行 maven-compile-plugin。只需在现有执行之前添加另一个执行并对其进行配置,以便它只为生成器拾取源代码。

    或者将项目一分为二:使用单独的 POM 构建生成器,并将生成器库作为对生成源的 POM 的依赖项。

    我个人会拆分项目。使构建文件更整洁,更易于维护。

    【讨论】:

    • 然后是两个项目。谢谢。
    • 采纳 Andreas 的第二个建议。将生成代码拆分到另一个项目中,将它们与第三个父项目绑定在一起。起初这可能看起来有点矫枉过正,但相信我,KLE 的解决方案真的矫枉过正。在父项目和子项目之间创建一个奇怪的依赖项(使用 sourceDirectory),并试图硬塞一个 POM 项目来创建一个 JAR 是矫枉过正的定义。
    【解决方案2】:

    我不想有 2 个不同的项目,所以我尝试设置 Maven 以将生成的编译代码添加到最终的 jar 包中。

    这是我使用过的有效解决方案:

    • process-classes 阶段(在compile 阶段之后执行):
      • exec-maven-plugin 用于执行能够在target/generated-sources/java 文件夹中生成我的源文件的主类(在我的具体情况下,我使用Roaster library 来生成源代码);
      • build-helper-maven-plugin 将生成的源添加到正确的位置
    • prepare-package 阶段:
      • maven-compiler-plugin,为了检测变化并重新编译模块
      • maven-jar-plugin制作jar包

    这是我的 pom.xml:

    <build>
        <plugins>
    
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>java</goal>
                        </goals>
                        <configuration>
                            <mainClass>com.example.MyClassWriter</mainClass>
                            <arguments>
                                <argument>${project.basedir}</argument>
                                <argument>${project.build.directory}</argument>
                            </arguments>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
    
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>build-helper-maven-plugin</artifactId>
                <version>3.0.0</version>
                <executions>
                    <execution>
                        <phase>process-classes</phase>
                        <goals>
                            <goal>add-source</goal>
                        </goals>
                        <configuration>
                            <sources>
                                <source>${project.build.directory}/generated-sources/java</source>
                            </sources>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
    
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.6.1</version>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
    
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.0.2</version>
                <executions>
                    <execution>
                        <phase>prepare-package</phase>
                    </execution>
                </executions>
            </plugin>
    
        </plugins>
    </build>
    

    【讨论】:

      【解决方案3】:

      为了在一个项目中做到这一点,有 3 个步骤:

      1. 编译生成器代码

        我们可以在generate-sources 阶段使用maven-compiler-plugin。您还可以排除其他源文件。

      2. 运行生成器生成代码

        我们可以在process-sources 阶段使用exec-maven-plugin

      3. 编译项目

      下面是pom.xml的关键部分

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>3.8.0</version>
          <configuration>
            <source>1.8</source>
            <target>1.8</target>
          </configuration>
          <executions>
              <execution>
                  <id>compile-generator</id>
                  <phase>generate-sources</phase>
                  <goals>
                    <goal>compile</goal>
                  </goals>
                  <configuration>
                    <includes>
                      <include>source/file/of/generator/*.java</include>
                    </includes>
                    <excludes>
                      <exclude>other/source/files/*.java</exclude>
                    </excludes>
                  </configuration>
              </execution>
          </executions>
        </plugin>   
        <plugin>
          <groupId>org.codehaus.mojo</groupId>
          <artifactId>exec-maven-plugin</artifactId>
          <version>1.6.0</version>
          <executions>
              <execution>
                  <id>generate-codes</id>
                  <goals>
                      <goal>java</goal>
                  </goals>
                  <phase>process-sources</phase>
                  <configuration>
                      <mainClass>your.main.class.of.generator</mainClass>
                  </configuration>
              </execution>
          </executions>
        </plugin>
      

      【讨论】:

        【解决方案4】:

        我们遇到了同样的问题。我们希望尽可能地尊重 Maven 的行为,让插件没有问题等等……对抗 Maven 太昂贵了!

        我们意识到生成代码的更新频率通常与我们手动编写的代码有很大不同,因此分离代码对于构建具有非常好的性能特征。所以我们接受将我们生成的类作为手动编写的依赖项。

        我们采用了以下结构,与常规的 maven 配置相比只有一点点变化,即源目录的变化。

        父项目:世代

        我们为所有世代​​创建了一个父项目

        • 如果包含要编译的代码,则为 JAR 类型,否则为 POM。
        • 在 /src 中有我们的生成代码。
        • 它可以像往常一样在 /target 中编译。
        • 它运行生成,每个生成器在 /target 的子目录中生成代码。

        注意:如果你想在同一个 jar 中生成多个生成的结果,只需将它们放在同一个子目录中即可。

        子 jar 项目:生成

        • 它是 Generations 项目的子目录。

        • 它有一个 JAR 类型。

        • 源目录指向父目标中的子目录。

          &lt;sourceDirectory&gt;../target/generated1&lt;/sourceDirectory&gt;

        • 它在自己的 /target 目录中正常编译。


        这种结构允许我们:

        • 尽可能少地修改标准 maven 布局,因此每个 maven 命令和插件都能正常运行。
        • 如果您有多个生成器,可以很好地扩展,
        • 如果你想生成几个 jars 可以很好地扩展(我们有一个案例 wsdl2java,其中一个生成器生成的代码应该被分成几个 jars ;每个子生成的项目都将具有相同的源目录,但将配置为 @987654322 @ 只处理部分类)。

        【讨论】:

        • 这个答案违反了 Maven 的许多核心假设。以这种方式实施解决方案会给您一个不支持的 Maven 项目。添加一个“隧道”到父项目的目标目录的源目录是灾难的秘诀。对于初学者,您的父项目具有包装“pom”。 “POM”项目中没有编译,因此您必须在父项目中手动配置编译插件目标。您正在创建两个项目(父子)之间的依赖关系,该依赖关系不是使用真实依赖关系定义的。你正在围绕 Maven 做一个终结。
        • @tobrien 您在父级中编译是对的,我忘记了这一点。这是我们发现的侵入性较小的解决方案,并且没有发生灾难,这与我们尝试的其他几种配置发生的情况相反。不过,我们对更好的想法持开放态度,因为您必须比我们更了解 maven。
        • @tobrien 其实我们的父项目没有要编译的代码,它只通过wsdl2java等触发生成...所以它有POM类型。
        【解决方案5】:

        我在这里发布了一个最小的工作设置https://github.com/baloise/inlinesourcecodegenerator 它使用 build-helper 编译器和 exec 插件,并且所有代码都在同一个项目中。

        【讨论】:

          猜你喜欢
          • 2012-05-03
          • 2017-11-14
          • 2010-12-26
          • 2020-02-07
          • 2020-08-19
          • 1970-01-01
          • 1970-01-01
          • 2019-12-02
          • 1970-01-01
          相关资源
          最近更新 更多