【问题标题】:Incompatible types, equality constraints and method not found during Java 9 MigrationJava 9 迁移期间未找到不兼容的类型、等式约束和方法
【发布时间】:2018-03-03 06:57:00
【问题描述】:

在将我们的一个项目迁移到 Java 9(build 9+181) 时,我遇到了一个特殊的问题,在使用的某些库中看起来像是不正确的实现与type inference 相关。我正在使用 dropwizard-core(1.1.0)guice(4.1.0) 配置如下:

public class CustomService extends io.dropwizard.Application<CustomServiceConfig> {

    public static void main(String[] args) throws Exception {
        new CustomService().run(args);
    }

    // other initializations

    @Override
    public void run(CustomServiceConfig config, io.dropwizard.setup.Environment environment) throws Exception {
        com.google.inject.Injector injector = createInjector(config, environment);
        environment.jersey().register(injector.getInstance(SomeResource.class)); //line 45
        environment.healthChecks().register("DBHealth", injector.getInstance(HealthCheck.class)); 
        environment.servlets().addFilter("Filter-Name", SomeFilter.class)
                .addMappingForUrlPatterns(EnumSet.allOf(DispatcherType.class), true, "/*");
    }


    private com.google.inject.Injector createInjector(CustomServiceConfig config, Environment environment) {
        return com.google.inject.Guice.createInjector(new CustomServiceModule(config, environment));
    }

}

public class CustomServiceModule extends com.google.inject.AbstractModule {
    private final CustomServiceConfig serviceConfig;
    private final Environment environment;

    public CustomServiceModule(CustomServiceConfig serviceConfig, Environment environment) {
        this.serviceConfig = serviceConfig;
        this.environment = environment;
    }

    @Override
    protected void configure() {
        bind(SomeInterface.class).to(SomeInterfaceImpl.class);
        ..
    }
}

以下组合对我来说配置很好:

  • Java 8 + Maven 3 + Compiler Plugin 3.6.1 [我们的原始设置]
  • Java 9 + Maven 3 + Compiler Plugin 3.7.0(命令行和 maven 配置已更新)

但是当我切换到模块结构然后尝试编译由这些类组成的 maven 模块时,我在 mvn clean install 期间遇到了这些错误:

[ERROR] ../service/service/CustomService.java:[45,29] incompatible types: inference variable T has incompatible bounds
    equality constraints: base.SomeResource
    upper bounds: java.lang.Class<?>,java.lang.Object

[ERROR] ../service/service/CustomService.java:[56,31]
no suitable method found for
addFilter(java.lang.String,java.lang.Class< SomeFilter >)
[ERROR]     method io.dropwizard.jetty.setup.ServletEnvironment.addFilter(java.lang.String,javax.servlet.Filter)
is not applicable
[ERROR]       (argument mismatch; java.lang.Class< SomeFilter > cannot be
converted to javax.servlet.Filter)

我不确定为什么会出现这些错误,以及它们是否与正在使用的模块结构有关。

第一季度。是否有任何类型推断相关的更改会影响模块结构更改(如果可能的话)的 maven 编译,请记住使用的依赖项?

此外,在迁移时,我主要使用 IntelliJ 建议的自动模块名称来构建 module-info 为:

module service {
//    Internal modules  which compile successfully
    requires model;
    requires util;

//    Dependent library modules
    requires httpcore;
    requires guice;
    requires guava;
    requires dropwizard.core;
    requires mongo.java.driver;
    requires org.apache.commons.lang3;
    requires javax.servlet.api;
}

第二季度。如果这不是迁移时的回归问题,为什么我们之前的设置没有失败?这是否还要求我们更改服务中的代码,或者如果这可能有帮助,我们是否应该等待库迁移到模块?

注意:已尝试查看依赖版本和类实现的使用情况。它们在以前的设置和当前设置中是相同的。

如果有任何我能提供帮助的进一步信息,请告诉我。


更新: 我能够在我创建的 microservice sample 中重现相同的内容,以将其与我的项目的其余部分隔离开来。

【问题讨论】:

  • 我看不出模块会如何在编译器方面以任何方式影响泛型;这可能只是这里的 java-9 回归。你能通过一个更简单的测试来隔离这个问题吗?
  • @Eugene 如果这实际上可能是某个地方的回归,那将需要一些时间并提供一个孤立的项目。
  • 类型推断*不是参考。
  • 别担心,当你这样做的时候请给我加个标签。我真的不知道然后回答这个问题,但很乐意跟踪它。谢谢
  • @Eugene answer 有效。它是dropwizard-core 的传递依赖。虽然恕我直言,但该错误非常具有误导性,我不确定编译器插件是否会更好地报告。

标签: java-module java maven java-8 java-9 java-module


【解决方案1】:

从示例项目中,我能够修复编译问题。 com.SomeService#run 方法中有 2 个异常。您的 module-info.java 中缺少模块,添加这些模块后,代码应该可以编译。

requires dropwizard.jersey;
requires dropwizard.jetty;

JerseyEnvironment来自io.dropwizard:dropwizard-jersey:1.1.0

ServletEnvironment来自io.dropwizard:dropwizard-jetty:1.1.0

由于它们是不同的 jar,因此它们导出不同的模块。因此,需要明确添加需求。 您的代码在没有 module-info.java 的情况下可以正常工作,因为当时没有使用模块系统。

我通过执行以下 cmets 中提到的方法找到了解决方法:

@Override
public void run(SomeServiceConfig config, Environment environment) throws Exception {
    Injector injector = Guice.createInjector(new SomeServiceModule());
    // Fix: Extract to variable to find Type of jersey and then find the module to add under requires
    JerseyEnvironment jersey = environment.jersey(); 
    jersey.register(injector.getInstance(SomeResource.class));
    // Fix 2: Same method as Fix 1
    ServletEnvironment servlets = environment.servlets();
    servlets.addFilter("Some-Filter", SomeFilter.class);
}

【讨论】:

  • 为什么需要这些要求?我已经使用名为dropwizard.core 的自动模块来获得对dropwizard-core:1.1.0 的相应maven 依赖。
  • JerseyEnvironment 来自io.dropwizard:dropwizard-jersey:1.1.0 ServletEnvironment 来自io.dropwizard:dropwizard-jetty:1.1.0 由于它们是不同的jar,因此它们导出不同的模块。因此,需要明确添加需求。请记住,在 Java 9 中,您无法推断模块依赖关系,您已明确提及它。
  • 你明白了。传递依赖,在模块化结构中不会类似地工作。此外,编译错误不会报告这一点。当它说 incompatible types 而不是因为找不到而失败时,它有点误导。对此有什么想法吗?
  • 该错误确实具有误导性。然而,在我过去使 [Eclipse Collections][1] Java 9 兼容的经验中,异常和错误经常会产生误导,当时我需要进行一些尝试和错误。所以,现在有点知道调试时要采取的几个第一步是什么。注意:我是 Eclipse Collections [1] 的提交者:github.com/eclipse/eclipse-collections
  • 谢谢。尽管您的答案(会接受这个答案)解决了编译的一部分。或者,您可以更新答案中传递依赖的详细信息,以使其更有价值。对于此类错误消息,我仍然会等待解释(如果)。可能来自 apache-maven 团队的人可能会在那里提供帮助。暂缓赏金。 :)
猜你喜欢
  • 1970-01-01
  • 2017-11-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多