【问题标题】:Exclude Maven Dependency during Eclipse Application Runtime在 Eclipse 应用程序运行时排除 Maven 依赖项
【发布时间】:2019-06-06 19:21:55
【问题描述】:

当我尝试在 Eclipse 上运行 Java 应用程序时,两个依赖项之间的冲突导致应用程序失败。

我正在尝试将我的项目 Java 版本从 OracleJDK 8 升级到 OpenJDK 11。因此,我还必须将 GWT 依赖项从 2.6.0 更新到 2.8.2,以及从 MOJO gwt 切换-maven-plugin 也适用于 tboyer 版本。此外,构建是在 Eclipse IDE 4.9.0 上的 Maven 4.0.0 上完成的。

pom.xml 的片段

<properties>
  <gwt.version>2.8.2</gwt.version>
  ...
</properties>

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.gwt</groupId>
      <artifactId>gwt</artifactId>
      <version>${gwt.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.gwt</groupId>
    <artifactId>gwt-dev</artifactId>
    <scope>provided</scope>
  </dependency>    
  ...

<build>
  <plugins>
    <plugin>
      <groupId>net.ltgt.gwt.maven</groupId>
      <artifactId>gwt-maven-plugin</artifactId>
      <version>1.0-rc-10</version>
      <executions>
        <execution>
          <id>compile-common</id>
          <goals>
            <goal>compile</goal>
            <goal>test</goal>
          </goals>
          <configuration>
            <moduleName>XXXXModule</moduleName>
          </configuration>
       </execution>
       <execution>
         <id>XXXX</id>
         <goals>
           <goal>compile</goal>
           <goal>test</goal>
         </goals>
         <configuration>
           <moduleName>XXXXModule</moduleName>
         </configuration>
       </execution>
       <execution>
         <id>XXXX</id>
         <goals>
           <goal>compile</goal>
           <goal>test</goal>
         </goals>
         <configuration>
           <moduleName>XXXXModule</moduleName>
         </configuration>
       </execution>
       <execution>
          <id>XXXX</id>
          <goals>
            <goal>compile</goal>
            <goal>test</goal>
          </goals>
          <configuration>
            <moduleName>XXXXModule</moduleName>
          </configuration>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

所以当我在 Eclipse 上运行应用程序时,我收到以下错误:

SEVERE: Application encountered an exception during Start.
XXXX.ApplicationException: Failed to reflect on start method.
at XXXX.ApplicationLauncher.startApplication(ApplicationLauncher.java:471)
    at XXXX.ApplicationLauncher.doRun(ApplicationLauncher.java:185)
    at XXXX.ApplicationLauncher.main(ApplicationLauncher.java:67)
Caused by: java.lang.reflect.InvocationTargetException
    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 XXXX.ApplicationLauncher.startApplication(ApplicationLauncher.java:469)
    ... 2 more
Caused by: java.lang.NoSuchMethodError: org.apache.tomcat.util.ExceptionUtils.preload()V
    at org.apache.catalina.startup.Tomcat.<init>(Tomcat.java:181)
....

经过调查,我发现我的两个依赖项 tomcat-embed-core-7.0.91 和 apache-jsp-8.0.9.M3 都包含有几个不同的 ExceptionUtils,因此是 Exception。此外,gwt-dev 依赖项正在提取 apache-jsp,该依赖项仅在 Maven 构建期间需要运行 gwt-maven-plugin。

gwt-dev:2.8.2
    apache-jsp:9.2.14.v20151106
         apache-jsp:8.0.9.M3

但由于某种原因,Eclipse 将 gwt-dev 及其依赖项包含在运行时路径中,即使我在 pom.xml 中有“提供”范围标记。

我已尝试排除 apache-jsp 依赖项,但出现编译问题,因为显然仍在添加依赖于 apache-jsp 的 gwt-dev。

总结

  • Tbroyer GWT-Maven-Plugin 要求 pom 文件包含 gwt-dev 作为依赖项,以便在构建期间正确运行。
  • 但是,在 Eclipse 上运行应用程序时,在 org.apache.tomcat.util.ExceptionUtils.preload()V 上发生 NoSuchMethodException
  • 问题是两个 ExceptionUtil 类具有来自不同 jar 和方法的相同包。
  • 其中一个 jar 是 apache-jsp,它是 gwt-dev 的依赖项。 Gwt-dev 及其依赖项不应成为运行时类路径的一部分。

问题:有没有办法确保 gwt-dev 仅在 Maven 构建期间使用,而不是 Eclipse Java 应用程序运行时类路径的一部分?

【问题讨论】:

    标签: eclipse maven tomcat gwt gwt-maven-plugin


    【解决方案1】:

    是的,您可以确保客户端和服务器端的类路径隔离。您需要应用多模块布局。这也是旧的 MOJO gwt maven 插件和新一代 tbroyer gwt maven 插件的主要区别,新的正确支持多模块。检查this archetype 作为多模块布局的参考。另外,使用 packaging:gwt-app 自动配置 gwt maven 插件执行。

    使其与 eclipse 运行操作(tomcat 或 gwt)一起工作有点困难。在您正确应用 tbroyer gwt maven 插件和多模块布局之前,您将能够在终端中使用 mvn tomcat7:runmvn gwt:codeserver。然后,在 IDE 中使用它的推荐策略是配置这个 maven 目标并使用 IDE 的 maven 工具运行它。这使它在您的所有环境(终端、CI、eclipse、intellij 等)中的工作方式完全相同。

    【讨论】:

    • 抱歉,您能详细说明一下多模块布局吗?我还是 GWT 的新手,所以我不确定你在说什么,即使有你的链接。我应该寻找什么?
    • 传统 GWT 项目只有一个模块(实际上是一个没有模块的 maven 项目),这是单体布局,这种布局的主要问题是客户端和服务器类路径混合在一起,当项目变得更大时,发生类路径冲突是非常普遍的。新布局将项目分为 3 个模块,客户端 (gwt)、服务器 (war) 和共享,其中包含两个模块的公共代码。这种布局完全分离了类路径,避免了任何可能的冲突。旧插件不支持这个(多模块),所以创建了新插件来解决它。
    • 这很有趣,但我不认为这是我的核心问题。为了简化,GWT-Maven-Plugin 要求 pom 文件包含 gwt-dev 作为依赖项才能正确构建。但是,当我在 Eclipse 上运行应用程序时,gwt-dev 及其依赖项被包含在运行时类路径中,这会导致不兼容的异常。有没有办法只在编译期间包含 gwt-dev 而在运行时不包含。
    • 如果您使用单独的模块,gwt-dev 将仅在客户端模块中,因此“运行您的应用程序”(服务器部分)不会包含它。话虽如此,我不能真正评论这个问题的 Eclipse 方面,Eclipse 中很可能存在错误或限制,这使得这不可能(或过于复杂)。我的建议是:只使用 Maven(如果可以的话,Maven 本身或它的插件有许多限制),或者如果可能的话,可能切换到更好的构建工具(例如 Gradle),或者更好的 IDE也许……
    • 有趣,你有运行客户端与服务器模块的例子吗?
    猜你喜欢
    • 1970-01-01
    • 2011-04-18
    • 2020-04-19
    • 2012-02-25
    • 1970-01-01
    • 1970-01-01
    • 2012-05-23
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多