简体   繁体   中英

Eclipse uses wrong maven dependency in launch configuration

I'm working on a project that uses Maven for dependency / building / whatever (project life cycle management or sth), and I'm using Eclipse to develop and test.

The project uses Vert.x (latest) and I'm trying to use Hazelcast for some cluster management, but I encountered a bug with the Hazelcast version that Vert.x declares as a dependency (3.6.3) and the solution apparently is to upgrade to a more recent version.

I've added an updated Hazelcast dependency in my pom.xml as such:

<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast</artifactId>
    <version>[3.7,)</version>
</dependency>

And maven indeed updates the dependency (actually Eclipse called maven to update as soon as I save the pom.xml file - pretty neat), and so I get the dependency tree:

$ mvn dependency:tree
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building project 3.8.4
[INFO] ------------------------------------------------------------------------
[WARNING] The POM for jfree:jfreechart:jar:1.0.8 is missing, no dependency information available
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ project ---
[INFO] my.group:project:jar:3.8.4
[INFO] +- some.private.dep ...
[INFO] |  +- org.junit:junit4-engine:jar:5.0.0-ALPHA:compile (version selected from constraint [4,))
[INFO] |  |  \- org.junit:junit-engine-api:jar:5.0.0-ALPHA:compile
[INFO] |  |     +- org.junit:junit-commons:jar:5.0.0-ALPHA:compile
[INFO] |  |     \- org.opentest4j:opentest4j:jar:1.0.0-ALPHA:compile
[INFO] |  +- io.vertx:vertx-hazelcast:jar:3.3.3:compile (version selected from constraint [3.0.0,))
[INFO] |  \- io.vertx:vertx-web:jar:3.4.0.Beta1:compile (version selected from constraint [3.0.0,))
[INFO] |     \- io.vertx:vertx-auth-common:jar:3.4.0.Beta1:compile
[INFO] +- io.vertx:vertx-core:jar:3.4.0.Beta1:compile
[INFO] |  +- io.netty:netty-common:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-buffer:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-transport:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-handler:jar:4.1.8.Final:compile
[INFO] |  |  \- io.netty:netty-codec:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-handler-proxy:jar:4.1.8.Final:compile
[INFO] |  |  \- io.netty:netty-codec-socks:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-codec-http:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-codec-http2:jar:4.1.8.Final:compile
[INFO] |  +- io.netty:netty-resolver:jar:4.1.8.Final:compile
[INFO] |  \- io.netty:netty-resolver-dns:jar:4.1.8.Final:compile
[INFO] |     \- io.netty:netty-codec-dns:jar:4.1.8.Final:compile
[INFO] +- junit:junit:jar:4.12:test
...

[INFO] +- com.hazelcast:hazelcast:jar:3.8-EA:compile
[INFO] \- org.slf4j:slf4j-jdk14:jar:1.7.22:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.785 s
[INFO] Finished at: 2017-02-06T09:52:46+02:00
[INFO] Final Memory: 25M/435M
[INFO] ------------------------------------------------------------------------

When I run mvn package to create the shaded Jar, I get the correct version of Hazelcast.

The problem is that if I create an Eclipse launch configuration for running the project or its unit tests, it inserts both the old version of Hazelcast as well as the new version of Hazelcase into the classpath - here's an example command line from a unit test being run:

/usr/lib/jvm/java-8-openjdk-amd64/bin/java -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:33123 -ea -Dfile.encoding=UTF-8
  -classpath ...:
  $HOME/.m2/repository/io/vertx/vertx-hazelcast/3.3.3/vertx-hazelcast-3.3.3.jar:
  $HOME/.m2/repository/com/hazelcast/hazelcast/3.6.3/hazelcast-3.6.3.jar:
  ...
  $HOME/.m2/repository/com/hazelcast/hazelcast/3.8-EA/hazelcast-3.8-EA.jar:
  ...
  -version 3 -port 38387 -testLoaderClass org.eclipse.jdt.internal.junit4.runner.JUnit4TestLoader 
  -loaderpluginname org.eclipse.jdt.junit4.runtime 
  -classNames my.group.project.SomeTest

Now because both versions are loaded into the classpath, the first one (the older) "wins" and I get the bug instead of getting the newer fixed version.

The launch configuration "Classpath" tab looks very standard:

+ Bootstrap Entries
 \- JRE System Library
+ User Enties
 \- project
 \- Maven Dependencies

And the "Maven Dependencies" "folder" in the "Project Explorer" view shows only the newer Hazelcast version.

What is going on?

Update:

As per the discussion in the comments, I added exclusions to the pom.xml file to prevent vertx-hazelcast from adding the old hazelcast dependency. Because vertx-hazelcast is loaded from yet another (private) dependency, the new setup is a bit more involved and looks like this:

<dependency>
    <groupId>some.private</groupId>
    <artifactId>dependency</artifactId>
    <version>[1.3,)</version>
    <exclusions>
        <exclusion>
            <groupId>io.vertx</groupId>
            <artifactId>vertx-hazelcast</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-core</artifactId>
    <version>[3.0.0,)</version>
</dependency>
<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast</artifactId>
    <version>[3.7,)</version>
</dependency>
<dependency>
    <groupId>io.vertx</groupId>
    <artifactId>vertx-hazelcast</artifactId>
    <version>[3.0.0,)</version>
    <exclusions>
        <exclusion>
            <groupId>com.hazelcast</groupId>
            <artifactId>hazelcast</artifactId>
        </exclusion>
    </exclusions>
</dependency>

I then removed the old launch configuration and recreated it (by right clicking the JUnit test case and choosing "Debug as Junit") - But that does not change the Eclipse behavior - some jars in the classpath have moved around a bit, but the result is still that vertx-hazelcast and its hazelcast-3.6.3.jar dependency are loaded before hazelcast-3.8.jar .

Note This answer is a summary from discussion with the OP

It looks like vertex-hazelcast declares both compile and test scoped dependencies on hazelcast . These scopes are not transitive so it's my understanding that this version will be included in the classpath by design. @Echnalb suggestion to use an exclusion is the recommended way to resolve this.

As that hasn't worked, it could be an ancestor is also declaring a dependency which would also need to be excluded.

After looking through some other dependencies that were declared in vertex-hazelcast , I checked hazelcast-client to see if it also declared a dependency on the earlier version of hazelcast the assumption being that the ancestral dependency was being added to the classpath despite the exclusion from the parent.

It did include such a dependency:

<dependency>
    <groupId>com.hazelcast</groupId>
    <artifactId>hazelcast</artifactId>
    <scope>test</scope>
    <version>${project.parent.version}</version>
    <classifier>tests</classifier>
</dependency>

I suggest( ed ) adding an exclusion for hazelcast-client which seems to have solved the problem.


@Guss comments

  • Prior to the exclusion, running dependency:tree , hazelcast-client is not listed at all
  • It is interesting that dependency:tree does not detect test scoped dependencies. Is there's a way to force it to switch scopes?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM