Incompatible types, equality constraints and method not found during Java 9 Migration

匿名 (未验证) 提交于 2019-12-03 01:27:01

问题:

While migrating one of our projects to Java 9(build 9+181), I am facing a peculiar problem what looks like an incorrect implementation in some library in use related to type inference and . I am using a dropwizard-core(1.1.0) and guice(4.1.0) configurations as follows:

public class CustomService extends io.dropwizard.Application {      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);         ..     } } 

The configuration works fine for me with the following combination :

  • Java 8 + Maven 3 + Compiler Plugin 3.6.1 [Our original setup]
  • Java 9 + Maven 3 + Compiler Plugin 3.7.0 (command line and maven configs updated)

But as I switch to the module structure and then try and compile the maven module consisting of those classes, I get these errors during 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) [ERROR]     method io.dropwizard.jetty.setup.ServletEnvironment.addFilter(java.lang.String,javax.servlet.Filter) is not applicable [ERROR]       (argument mismatch; java.lang.Class cannot be converted to javax.servlet.Filter) 

I am not sure why these errors occurred and if they could be related to the module structure in use.

Q1. Is there any type-inference related change that can impact the maven compilation with module structure changes(if this is possible) keeping in mind the dependencies used?

Also while migrating, I have mostly used the automatic module names as suggested by IntelliJ to construct the module-info as :

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

Q2. If this is not a regression issue while migrating, why did this not fail with our previous setup? Does this also mandate a code change in our service or shall we wait for libraries to move to modules if that might help?

Note: Have tried to look into the usage of the dependency versions and class implementation. They are same in both the previous and current setup.

Do let me know for any further information I could help with.


Update: I was able to reproduce the same in a microservice sample created by me to isolate it from the rest of my project.

回答1:

From the sample project I was able to fix the compilation issue. There were 2 exceptions in com.SomeService#run method. There were missing modules in your module-info.java, once you add these the code should compile.

requires dropwizard.jersey; requires dropwizard.jetty; 

JerseyEnvironment comes from io.dropwizard:dropwizard-jersey:1.1.0

ServletEnvironment comes from io.dropwizard:dropwizard-jetty:1.1.0

Since they are different jars, they export different modules. Hence, the requires needs to be explicitly added. Your code works fine without module-info.java because at that time module system is not used.

I found the fix by doing the below, method mentioned in comments:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!