在 Java 9 迁移期间未找到不兼容的类型、相等约束和方法

2022-09-04 03:30:47

在将我们的一个项目迁移到Java 9(build 9 + 181)时,我遇到了一个特殊的问题,在一些与类型推断相关的库中,这似乎是一个不正确的实现。我正在使用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 + 编译器插件 3.6.1 [我们的原始设置]
  • Java 9 + Maven 3 + Compiler Plugin 3.7.0 (命令行和 maven 配置已更新)

但是当我切换到模块结构,然后尝试编译由这些类组成的maven模块时,我在mvn全新安装期间收到这些错误:

[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)

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

问题 1.是否有任何与类型推断相关的更改会影响 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;
}

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

注意:已尝试研究依赖项版本和类实现的用法。它们在以前的设置和当前设置中都是相同的。

请让我知道任何进一步的信息,我可以提供帮助。


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


答案 1

从示例项目中,我能够解决编译问题。方法中有 2 个例外。模块信息中缺少模块.java,一旦添加这些模块,代码就应该编译。com.SomeService#run

requires dropwizard.jersey;
requires dropwizard.jetty;

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

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

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

我通过执行以下操作找到了修复程序,评论中提到的方法:

@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);
}

答案 2

推荐