注释处理期间的 GWT RfValidator NPE

GWT RfValidator NPE during annotation processing

在使用 Java 8:

构建 GWT 1.8.2 应用程序期间,将 aspectjweaver 1.11 版与高于 1.8.5 版的 aspectjrt 一起使用会导致多个 NPE
[INFO] --- aspectj-maven-plugin:1.11:compile (compile) @ myproject ---
...
[ERROR] java.lang.NullPointerException
    at org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding.sourceField(FieldBinding.java:437)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl$SourceLocationComparator.determineSourceStart(TypeElementImpl.java:110)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl$SourceLocationComparator.getSourceStart(TypeElementImpl.java:74)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl$SourceLocationComparator.compare(TypeElementImpl.java:67)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl$SourceLocationComparator.compare(TypeElementImpl.java:1)
    at java.util.TimSort.countRunAndMakeAscending(TimSort.java:360)
    at java.util.TimSort.sort(TimSort.java:234)
    at java.util.Arrays.sort(Arrays.java:1512)
    at java.util.ArrayList.sort(ArrayList.java:1462)
    at java.util.Collections.sort(Collections.java:175)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl.getEnclosedElements(TypeElementImpl.java:168)
    at com.google.web.bindery.requestfactory.apt.DomainChecker.isDefaultInstantiable(DomainChecker.java:407)
    at com.google.web.bindery.requestfactory.apt.DomainChecker.visitType(DomainChecker.java:253)
    at com.google.web.bindery.requestfactory.apt.DomainChecker.visitType(DomainChecker.java:44)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.model.TypeElementImpl.accept(TypeElementImpl.java:139)
    at javax.lang.model.util.ElementScanner6.scan(ElementScanner6.java:146)
    at com.google.web.bindery.requestfactory.apt.ScannerBase.scan(ScannerBase.java:76)
    at com.google.web.bindery.requestfactory.apt.State.executeJobs(State.java:248)
    at com.google.web.bindery.requestfactory.apt.RfValidator.process(RfValidator.java:86)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.handleProcessor(RoundDispatcher.java:142)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.RoundDispatcher.round(RoundDispatcher.java:124)
    at org.aspectj.org.eclipse.jdt.internal.compiler.apt.dispatch.BaseAnnotationProcessorManager.processAnnotations(BaseAnnotationProcessorManager.java:171)
    at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.processAnnotations(Compiler.java:956)
    at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:451)
    at org.aspectj.org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:427)
    at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performCompilation(AjBuildManager.java:1107)
    at org.aspectj.ajdt.internal.core.builder.AjBuildManager.performBuild(AjBuildManager.java:276)
    at org.aspectj.ajdt.internal.core.builder.AjBuildManager.batchBuild(AjBuildManager.java:189)
    at org.aspectj.ajdt.ajc.AjdtCommand.doCommand(AjdtCommand.java:114)
    at org.aspectj.ajdt.ajc.AjdtCommand.runCommand(AjdtCommand.java:60)
    at org.aspectj.tools.ajc.Main.run(Main.java:371)
    at org.aspectj.tools.ajc.Main.runMain(Main.java:248)
    at org.codehaus.mojo.aspectj.AbstractAjcCompiler.execute(AbstractAjcCompiler.java:544)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
    at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:956)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:288)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:192)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)

这发生在所有@ProxyFor 类 中,它们是项目外 类 的代理(由 maven 依赖项解决)。

@ProxyFor(value = ClassOfOtherProject.class)
public interface ClassOfOtherProjectProxy extends EntityProxy { // <- NPE happens in this Line!

    ...

}

摘自pom.xml:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.8.1</version>
    <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <useIncrementalCompilation>false</useIncrementalCompilation>
        <encoding>UTF-8</encoding>
        <annotationProcessors>
            <annotationProcessor>com.google.web.bindery.requestfactory.apt.RfValidator</annotationProcessor>
        </annotationProcessors>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>com.google.web.bindery</groupId>
            <artifactId>requestfactory-apt</artifactId>
            <version>2.8.2</version>
        </dependency>
    </dependencies>
</plugin>

只有 aspectjrt 1.8.4(或更低版本)才能正常运行。我应该怎么办?从 Java 7 迁移到 8 和 GWT 1.7.x 到 1.8.2 后,这些错误仍然存​​在。如何在不获取这些 NPE 的情况下更新 aspectjrt?

这不是在 GWT 编译中失败,而是在将 java 源代码编译为字节码的过程中。 GWT 的 RequestFactory 使用注释处理器来验证您的每个代理是否正确匹配它们在服务器上映射到的 entity/value/service 类型,而且这个版本的 aspectjrt 和 jdt 似乎无法正确查找成员ClassOfOtherProject 的,因此可以过滤它们以找到构造函数。从您的堆栈跟踪中,在 com/google/web/bindery/requestfactory/apt/DomainChecker.java:407:

List<ExecutableElement> constructors = ElementFilter.constructorsIn(x.getEnclosedElements());

这是在注释处理器中执行操作的一种非常标准的方法 - 如果调用 TypeElement.getEnclosedElements() 失败并出现此注释处理器的 NPE,我也会担心此构建中的其他错误。这很可能发生在任何注释处理器上,与 GWT 无关。

通过让 maven-compiler-plugin 仅进行注释处理,我终于能够使用最新的 AspectJ-Runtime 构建我的项目。只需在插件的配置中添加 <proc>only</proc>

class 编译将由 aspectj-maven-plugin 插件完成。可以通过在配置中添加 <proc>none</proc> 来禁用此插件的注释处理。