Maven使用AnnotationProcessor构建,该解析器解析src / main / java中的文件并生成源代码以生成测试源/测试注释

时间:2013-09-17 15:14:15

标签: java unit-testing maven annotations code-generation

我正在使用maven 3.0.3和Java7。

我有一个AnnotationProcessor,它应该在src/main/java src/test/java)中解析带注释的java文件,并为JUnit-Tests生成Helper-Classes。这些Helper-Class应该存储在target/generated-test-sources/test-annotations中,因为它们使用的库只在测试范围内可用。 (注意:只要这个依赖关系不在测试范围内,一切都可以正常工作,但是编译一旦失败就会失败。它肯定只在测试范围内/单元测试和编译测试类时才需要。)

我试了好几个配置而没有任何运气:

  1. 我在maven-compiler-plugin期间将compile:compile配置为使用AnnotationProcessor。生成的HelperClass将存储在generated-sources/annotations中。根据需要在generated-test-sources/test-annotations。结果是,不会使用Test-Scoped依赖项。由于编译错误“无法找到符号”,构建失败。 故障

  2. 我使用了上面的配置并重新定义了generatedSourcesDirectory:

    <generatedSourcesDirectory>
       ${project.build.directory}/generated-test-sources/test-annotations
    </generatedSourcesDirectory>
    

    生成的类将按预期存储在generated-test-sources/test-annotations中,但构建仍然失败,因为它尝试按上述方式编译该文件并错过了测试范围的依赖项。 故障

  3. 我尝试使用上面的配置并排除了**/generated-test-sources/test-annotations/**/*.java,以防止编译器在此阶段进行编译:

    <excludes>
       <exclude>**/generated-test-sources/test-annotations/**/*.java</exclude>
    </excludes>
    
    没有运气。与上面相同的编译器错误。 故障

  4. 我在maven-compiler-plugin期间将test-compile:testCompile配置为使用AnnotationProcessor。理论上,HelperClass可能是在generated-test-sources/test-annotations中生成的,但是AnnotationProcessor不会偶然发现位于src/main/java的注释类,而不会发现src/test/java中的注释类,这是编译范围的AFAIK在test-compile:testCompile期间。因此,找不到Annotated类,HelperClass将不会生成,因此不能存储在generated-test-sources中。 故障

  5. 试图在compile:testCompiletest-compile:compile期间运行它,这在两种情况下都导致尚未编译的src / main / java类 - 因此编译错误。 故障

  6. 我真正想做的是:

    1. 将编译器配置为在compile:compile期间使用AnnotationProcessor生成我的HelperClass到${project.build.directory}/generated-test-sources/test-annotations 但不要让maven编译它
    2. 然后在test-compile:testCompile
    3. 期间编译HelperClass

      我没有这样做。我不确定我是否缺少重要的maven基础知识(概念),或者排除配置是否有问题,或者它是什么。

      非常感谢任何帮助。提前谢谢。

4 个答案:

答案 0 :(得分:4)

我使用includesexcludestestExcludes等进行了多次测试(我发现这些测试的记录非常糟糕)。似乎maven只是忽略了这些配置设置。真的不能相信它,但是虽然它表明包含和排除已经正确配置并且使用了这些配置(mvn -X clean install),但它仍然编译了排除的文件或者没有编译包含的文件。 (顺便说一下:我也是从CLI测试过的,因为我发现有些IDE仍然忽略这些设置。) 在那里发现的任何解决方案,例如添加资源目录,包括,排除,在generatedTestSourcesDirectory期间定义test-compile:testCompile以匹配generatedSourcesDirectory的{​​{1}}根本不起作用。 不管。

我找到了解决问题的方法,如下所示:

  1. 让第一个编译步骤(compile:compile)仅使用Annotation-Processors,但不编译生成的类:compile:compile。将<proc>only</proc>定义为应生成测试源的位置:generatedSourcesDirectory
  2. 使用${project.build.directory}/generated-test-sources/test-annotations在正确的阶段和目标中添加test-source-directory。 然后执行隐式build-helper-maven-plugin,并将生成的类sourcepath添加到普通源路径中。
  3. 以下是我的配置。请注意,我需要在实际问题出现之前生成其他内容,并且必须生成test-compile:testCompile,因此解决方案需要的编译步骤超过一个。

    所以,就是这样:

    generated-sources/annotations

答案 1 :(得分:1)

说实话,maven-compiler-plugin一般很糟糕。我使用第三方插件,似乎总能正常工作。我只使用<proc>none</proc>作为maven-compiler-plugin,然后:

     <plugin>
        <groupId>org.bsc.maven</groupId>
        <artifactId>maven-processor-plugin</artifactId>
        <executions>
          <execution>
            <id>annogen</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>process</goal>
            </goals>
            <inherited>false</inherited>
            <configuration>
              <processors>
                <processor>
                  xapi.dev.processor.AnnotationMirrorProcessor
                </processor>
              </processors>
              <outputDirectory>${project.build.directory}/generated-sources/annotations</outputDirectory>
              <appendSourceArtifacts>true</appendSourceArtifacts>
              <additionalSourceDirectories>
                <additionalSourceDirectory>
                  ${project.basedir}/../api/src/main/java
                </additionalSourceDirectory>
              </additionalSourceDirectories>
            </configuration>
          </execution>
        </executions>
      </plugin>

答案 2 :(得分:0)

您可以查看此博文: http://deors.wordpress.com/2011/10/08/annotation-processors/

您似乎需要在pom.xml中设置以下内容

构建&GT;插件&GT;插件&GT;结构&gt;&compilerArgument GT; -proc:无

我不确定这是否适用于您的特定情况,但我昨天正在处理注释,并认为这可能会对您有所帮助。

看起来这个参数可以让你在没有任何注释处理器的情况下进行编译。然后你可以在生命周期的后期编译它们。

答案 3 :(得分:0)

我有类似的问题,并尝试了建议的解决方案(两次执行maven-compiler-plugin,第一次使用proc:none,第二次使用proc:only)但遇到了以下问题:

1)运行mvn clean install:两个执行(proc:noneproc:only)将在运行注释处理器之前编译源代码并生成类文件:

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ foo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to <mumble>\foo\target\classes
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (process-annotations) @ foo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to <mumble>\foo\target\classes
[MyAnnotationProcessor] processing ...

2)在上一次安装之后运行mvn install:执行(proc:noneproc:only)确定类文件是最新的并且什么都不做,并且注释处理器不是运行:

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ foo ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (process-annotations) @ foo ---
[INFO] Nothing to compile - all classes are up to date

所以在第一种情况下,java文件被编译两次(我的一个模块有数千个文件,这会显着影响构建时间)。在第二种情况下,没有任何事情发生,因为类文件已经存在。这是使用maven-compiler-plugin的版本3.1和3.0。

对于maven-compiler-plugin版本2.5.1,第二次执行(proc:only)将始终确定类文件是最新的并且不运行注释处理器,无论我是否正在运行mvn clean installmvn install,所以第二次执行毫无意义。

插件配置如下:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.1</version>
  <configuration>
    <source>1.7</source>
    <target>1.7</target>
  </configuration>
  <executions>
    <execution>
      <id>default-compile</id>
      <configuration>
        <proc>none</proc>
      </configuration>
    </execution>
    <execution>
      <id>process-annotations</id>
      <goals><goal>compile</goal></goals>
      <configuration>
        <proc>only</proc>
        <annotationProcessors>
          <annotationProcessor>MyAnnotationProcessor</annotationProcessor>
        </annotationProcessors>
      </configuration>
    </execution>
  </plugin>

所以proc:only选项似乎在版本3.0和3.1中编译源代码(使其与proc:both相同,这会影响性能)或在版本2.5.1中不采取任何操作(使其成为与影响功能的proc:none相同。

不确定如何解决这个问题...

编辑#1

详细输出包括以下内容:

[INFO] --- maven-compiler-plugin:3.1:compile (process-annotations) @ foo ---
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-compiler-plugin:3.1:compile' with basic configurator -->
[DEBUG]   (f) annotationProcessors = [MyAnnotationProcessor]
[DEBUG]   (f) basedir = <mumble>\foo
[DEBUG]   (f) buildDirectory = <mumble>\foo\target
[DEBUG]   (f) classpathElements = [<mumble>\foo\target\classes, ...]
[DEBUG]   (f) compileSourceRoots = [<mumble>\foo\src\main\java]
[DEBUG]   (f) compilerId = javac
[DEBUG]   (f) debug = true
[DEBUG]   (f) failOnError = true
[DEBUG]   (f) forceJavacCompilerUse = false
[DEBUG]   (f) fork = false
[DEBUG]   (f) generatedSourcesDirectory = <mumble>\foo\target\generated-sources\annotations
[DEBUG]   (f) mojoExecution = org.apache.maven.plugins:maven-compiler-plugin:3.1:compile {execution: process-annotations}
[DEBUG]   (f) optimize = false
[DEBUG]   (f) outputDirectory = <mumble>\foo\target\classes
[DEBUG]   (f) proc = only
[DEBUG]   (f) projectArtifact = foo:jar:1.0-SNAPSHOT
[DEBUG]   (f) showDeprecation = false
[DEBUG]   (f) showWarnings = false
[DEBUG]   (f) skipMultiThreadWarning = false
[DEBUG]   (f) source = 1.7
[DEBUG]   (f) staleMillis = 0
[DEBUG]   (f) target = 1.7
[DEBUG]   (f) useIncrementalCompilation = true
[DEBUG]   (f) verbose = true
[DEBUG]   (f) mavenSession = org.apache.maven.execution.MavenSession@6fb65730
[DEBUG]   (f) session = org.apache.maven.execution.MavenSession@6fb65730
[DEBUG] -- end configuration --
[DEBUG] Using compiler 'javac'.
[DEBUG] Source directories: [<mumble>\foo\src\main\java]
[DEBUG] Classpath: [<mumble>\foo\target\classes ... ]
[DEBUG] Output directory: <mumble>\foo\target\classes
[DEBUG] CompilerReuseStrategy: reuseCreated
[DEBUG] useIncrementalCompilation enabled
[INFO] Changes detected - recompiling the module!
[DEBUG] Classpath:
[DEBUG]  <mumble>\foo\target\classes ...
[DEBUG] Source roots:
[DEBUG]  <mumble>\foo\src\main\java
[DEBUG] Command line options:
[DEBUG] -d <mumble>\foo\target\classes
    -classpath <mumble>\foo\target\classes;...;
    -sourcepath <mumble>\foo\src\main\java;
    -s <mumble>\foo\target\generated-sources\annotations
    -proc:only
    -processor MyAnnotationProcessor
    -g -verbose -nowarn -target 1.7 -source 1.7
[DEBUG] incrementalBuildHelper#beforeRebuildExecution
[INFO] Compiling 6 source files to <mumble>\foo\target\classes
[parsing started RegularFileObject[<mumble>\foo\src\main\java\Foo.java]]
[parsing completed 0ms]
...
[search path for source files: <mumble>\foo\src\main\java]
[MyAnnotationProcessor] processing ...

即使编译器选项中有proc:only,仍然有一个[parsing started RegularFileObject]条目......也许它只是记录但实际加载了类文件?