0

When I try to run a Java Application on Eclipse, a conflict between two dependencies is causing the application to fail.

I am trying to upgrade my project Java version from OracleJDK 8 to OpenJDK 11. As a result, I also had to also needed to update a GWT dependency from 2.6.0 to 2.8.2, as well as switch from MOJO gwt-maven-plugin to the tboyer version as well. Additionally, the build is done on Maven 4.0.0 on Eclipse IDE 4.9.0.

Snippet of the 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>

So when I run the application on Eclipse, I get the following error:

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

After investigating, I discovered that two of my dependencies tomcat-embed-core-7.0.91 & apache-jsp-8.0.9.M3 both contain ExceptionUtils with several difference, hence the Exception. Furthermore, the apache-jsp is being pulled by the gwt-dev dependency which is only required during the Maven build to run the gwt-maven-plugin.

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

But for some reason, Eclipse is including gwt-dev and it's dependency as part of the runtime path even though I have the 'provided' scope tag in the pom.xml.

I have tried excluding the apache-jsp dependency, but a compile issue occurs because apparently gwt-dev is still being added which depends on apache-jsp.

Summary

  • The TBroyer GWT-Maven-Plugin requires the pom file to include gwt-dev as a dependency in order to run correctly during a build.
  • However, when running the application on Eclipse, a NoSuchMethodException occurs on org.apache.tomcat.util.ExceptionUtils.preload()V
  • The issue is there are two ExceptionUtil classes with same package from different jars and methods.
  • One of the jars is apache-jsp which is a dependency of gwt-dev. Gwt-dev and it's dependencies should not be part of the runtime classpath.

Question: Is there a way to ensure the gwt-dev is only used during the Maven build and not part of the Eclipse Java Application runtime classpath?

Chen
  • 103
  • 1
  • 9

1 Answers1

1

Yes, you can ensure isolated classpath for client and server sides. You need to apply the multimodule layout. This is also the main difference between the old MOJO gwt maven plugin and the new generation tbroyer gwt maven plugin, the new one support multimodule correctly. Check this archetype as a reference for the multimodule layout. Also, use the packaging:gwt-app to configure the gwt maven plugin executions automatically.

Making it work with eclipse run action (tomcat or gwt) is a bit more difficult. Until you correctly apply the tbroyer gwt maven plugin and the multimodule layout, you will be able to use mvn tomcat7:run and mvn gwt:codeserver in the terminal. Then, the recommended strategy to use it in your IDE is to configure this maven goal and run it using the maven tooling of your IDE. This makes it work exactly the same in all your environments (terminal, CI, eclipse, intellij, etc).

Ignacio Baca
  • 1,538
  • 14
  • 18
  • Sorry, but can you elaborate about the multimodule layout. I'm still new to GWT, so I'm unsure what you're talking about, even with your link. What should I be looking for? – Chen Jan 14 '19 at 16:45
  • Traditional GWT project only has one module (actually, a maven project without modules), this is the monolithic layout and the main problem with this layout is that the client and server classpath was mixed and when the project gets bigger it is super common to have classpath conflicts. The new layout splits the project into 3 modules, client (gwt), server (war) and shared which contains the common code for both modules. This layout completely separates the classpath avoiding any possible conflict. The old plugin does not support this (multi modules), so the new one was created to solve it. – Ignacio Baca Jan 15 '19 at 07:24
  • That's interesting, but I don't think that's my core issue. To try to simplify, the GWT-Maven-Plugin requires the pom file to include gwt-dev as a dependency in order to build correctly. However, when I run the application on Eclipse, the gwt-dev and it's dependencies are being included in the runtime classpath which causes an Incompatible Exception. Is there a way to only include gwt-dev during compile, but not during runtime. – Chen Jan 16 '19 at 21:08
  • 1
    If you use separate modules, gwt-dev will only be in the client module, so "running your application" (the server part) won't include it. That being said, I can't really comment on the Eclipse side of this issue, there might very well be bugs or limitations in Eclipse making this impossible (or way too complicated). My recommendation would then be: use only Maven (if you can, there are a number of limitations in Maven itself, or it's plugins), or possibly switch to a better build tool (e.g. Gradle) if that's a possibility, or a better IDE maybe… – Thomas Broyer Jan 17 '19 at 19:47
  • Interesting, do you have an example of running a client vs server module? – Chen Jan 18 '19 at 20:15