在测试 - 编译阶段而不是编译阶段进行Maven注释处理?

时间:2014-09-20 13:56:17

标签: maven annotations

我编写了一个简单的java注释处理器,用于生成java文件和资源文件。

我已将注释处理器打包到一个jar文件中,我的maven项目可以在maven生命周期的编译阶段加载它并处理注释。生成的代码按预期显示在 target / generated-sources / annotations target / classes 中生成的资源文件中。

但是我只想在测试期间使用生成的java文件和资源文件,因此我希望生成的文件出现在 target / generated-test-sources / test-annotations 中和目标/测试类分别。简而言之,我需要在测试 - 编译阶段而不是编译阶段进行注释处理。

更重要的是:注释处理器在生产代码上运行,但生成的文件随后包含在 target \ foo-test.jar 中,而不是 target \ foo.jar < / em>的

我不确定如何使用maven,除非在 process-test-resources 阶段移动生成的文件,这似乎是一个丑陋的黑客。

有什么建议吗?

编辑:我尝试将<scope>test</scope>添加到注释处理器的依赖项中,我可以看到处理器是在 testCompile 阶段创建的,但处理器是不调用process()方法,也没有任何反应。

编辑#1 :注释处理器包含以下代码,用于在 META-INF / services 下编写.java文件和资源文件:

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  List<String> declarations = generateDeclarationsForAnnotation(roundEnv);
  generateServiceImplFile(declarations);
  generateResourceFile();
  return true;
}

private void generateResourceFile() throws Exception {
  JavaFileManager.Location location = StandardLocation.CLASS_OUTPUT;
  FileObject file= processingEnv.getFiler().createResource(location,
    "", "META-INF/services/x.y.z.FooService");
  BufferedWriter writer = new BufferedWriter(file.openWriter());
  ... write resource file ...
}

private void generateServiceImplFile(List<String> declarations) throws Exception {
  JavaFileObject file = processingEnv.getFiler().createSourceFile("x.y.z.FooServiceImpl");
  BufferedWriter writer = new BufferedWriter(file.openWriter());
  ... write source code ...
}

我目前在pom.xml文件中声明依赖项,如下所示:

<!-- Dependency for the @Foo annotation -->
<dependency>
  <groupId>x.y.z</groupId>
  <artifactId>foo-annotations</artifactId>
  <scope>compile</scope>
</dependency>
<!-- Dependency for the @Foo annotation processor -->
<dependency>
  <groupId>x.y.z</groupId>
  <artifactId>foo-annotations-processor</artifactId>
  <scope>compile</scope>
</dependency>

我使用JDK 1.7,maven-compiler-plugin版本3.1。注释处理器由于它存在于类路径上而被调用。我没有添加任何处理器插件等,或者调整了编译器插件等,以使其正常工作。

编辑#2 :我对maven-compiler-plugin进行了以下更改:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.1</version>
  <executions>
    <!-- Disable annotation processing for default compile execution -->
    <execution>
      <id>default-compile</id>
      <goals>
        <goal>compile</goal>
      </goals>
      <configuration>
        <proc>none</proc>
      </configuration>
    </execution>
    <!-- Only annotation process in this execution, with generated code 
         going to generated-test-sources directory. -->
    <execution>
      <id>compile-with-annotations-processor</id>
      <goals>
        <goal>compile</goal>
      </goals>
      <configuration>
        <proc>only</proc>
        <generatedSourcesDirectory>
          ${project.build.directory}/generated-test-sources/test-annotations
        </generatedSourcesDirectory>
      </configuration>
    </execution>
  </executions>
</plugin>

这将禁用default-compile执行的注释处理,compile-with-annotations-processing执行仅执行注释处理,将生成的源放入 target \ generated-test-sources \ test-annotations 目录。

当我运行它时,我在 target / generated-test-sources / test-annotations 目录中看到生成的java文件,尽管资源文件仍然出现在 target / classes < / em>目录。我猜测我可以通过更改generateResourceFile()方法来使用StandardLocation.SOURCE_OUTPUT代替StandardLocation.CLASS_OUTPUT来解决这个问题。

此外,此修复程序不能优雅地处理多个注释处理器。我真的只希望在default-compile执行期间禁用这一个特定的注释处理器,并且只在compile-with-annotations-processing执行中启用了该处理器(具有不同的源目录)。否则,如果我添加另一个(不相关的)注释处理器,它生成的代码将不会出现在预期的位置。

编辑#3 :也许更简单的解决方案是允许编译器正常运行注释处理器,然后从 target \ generated-sources 例如,使用maven-antrun-plugin target \ generated-test-sources

编辑#4 :我想我已经使用上面提到的maven-antrun-plugin解决了这个问题:

  • 配置maven-antrun-plugin将文件从 target / generated-sources / annotations 移动到 target / generated-test-sources / test-annotations ,以及从<在编译阶段,em> target / classes / META-INF / services target / test-classes / META-INF / services
  • 配置build-helper-maven-plugin以将 target / generated-test-sources 添加到 generate-test-sources 阶段。

我的 foo.jar foo-test.jar 似乎构造正确: - )

编辑#5 :我发现了一个名为maven-processor-plugin的插件,我已将其配置为在 generate-test-sources 阶段运行生产代码,并将输出目录设置为 target / generated-test-sources / annotations target / test-classes 。奇迹般有效。所以现在根本不需要maven_antrun_plugin

2 个答案:

答案 0 :(得分:1)

我发现了一个名为maven-processor-plugin的插件,我将其配置为在生产代码的generate-test-sources阶段运行,并将输出目录设置为 target / generated-test-sources / annotations target / test-classes 。奇迹般有效。所以现在根本不需要maven_antrun_plugin

我提出的另一个解决方案(因为有时使用maven-compiler-plugin而不是maven-processor-plugin可能更好)是使用compile阶段的注释处理器生成代码,以便代码最终位于通常的 target / generated-sources / annotations 目录中。同一模块中的测试代码可以访问此位置,并且测试运行正常。然后我配置maven-jar-plugin以从 artifactId。jar 中排除生成的代码,并将生成的代码包含在名为 artifactId的新工件中 - test -libs.jar 。然后,其他模块在 artifactId - test-libs 上添加测试依赖项。

答案 1 :(得分:0)

从maven-compiler-plugin 3.5开始,您可以使用QtWidgets.QApplication.setQuitOnLastWindowClosed(True) app.exec_() app.quit() 配置注释处理器。然后,您可以将此配置应用于默认的测试编译执行​​:

sys.exit()