mock-server / mockserver

MockServer enables easy mocking of any system you integrate with via HTTP or HTTPS with clients written in Java, JavaScript and Ruby. MockServer also includes a proxy that introspects all proxied traffic including encrypted SSL traffic and supports Port Forwarding, Web Proxying (i.e. HTTP proxy), HTTPS Tunneling Proxying (using HTTP CONNECT) and SOCKS Proxying (i.e. dynamic port forwarding).
http://mock-server.com
Apache License 2.0
4.58k stars 1.07k forks source link

Fails on No method due to Netty version collision #283

Closed asafm closed 7 years ago

asafm commented 8 years ago

Hi,

Our project uses Netty 4.0.24.final but the latet mockserver-netty uses 4.0.34.final. This makes mock server fail.

One way of handling it is use the Maven shade plugin. Here's an example taken from (logzio-logback-appender project):

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.3</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <minimizeJar>true</minimizeJar>
                    <artifactSet>
                        <includes>
                            <include>com.google.guava:guava</include>
                            <include>com.bluejeans.common:bigqueue</include>
                            <include>com.google.code.gson:gson</include>
                        </includes>
                    </artifactSet>
                    <relocations>
                        <relocation>
                            <pattern>com.google.common</pattern>
                            <shadedPattern>io.logz.com.google.common</shadedPattern>
                        </relocation>
                        <relocation>
                            <pattern>com.bluejeans.common.bigqueue</pattern>
                            <shadedPattern>io.logz.com.bluejeans.common.bigqueue</shadedPattern>
                        </relocation>
                        <relocation>
                            <pattern>com.google.gson</pattern>
                            <shadedPattern>io.logz.com.google.gson</shadedPattern>
                        </relocation>
                    </relocations>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>LICENSE</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
            </plugin>

This way you can work with any version you choose, it will never collide. I can submit a PR if it's fine with you?

jamesdbloom commented 7 years ago

There are two general mechanisms to solve this without making any changes to MockServer:

  1. "Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM." see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html
  2. "Excluded dependencies - If project X depends on project Y, and project Y depends on project Z, the owner of project X can explicitly exclude project Z as a dependency, using the "exclusion" element." see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html. Once the dependency is excluded you can ensure your version of the dependency will be used.

I would recommend using one of these two approaches to resolve your issue.

asafm commented 7 years ago

We use different minor Netty versions which are incompatible. If I exclude your version, your code runs with the error I described. If I do the opposite , my code will not work.

Shading your dependencies solves it all. When java 9 is out you will be able to use modules and get back to normal jar sizing.

On Wed, Oct 12, 2016 at 10:47 PM James D Bloom notifications@github.com wrote:

There are two general mechanisms to solve this without making any changes to MockServer:

1.

"Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM." see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html 2.

"Excluded dependencies - If project X depends on project Y, and project Y depends on project Z, the owner of project X can explicitly exclude project Z as a dependency, using the "exclusion" element." see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html. Once the dependency is excluded you can ensure your version of the dependency will be used.

I would recommend using one of these two approaches to resolve your issue.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jamesdbloom/mockserver/issues/283#issuecomment-253318111, or mute the thread https://github.com/notifications/unsubscribe-auth/AA8Y8RVPk7jZkLJ8qYaeBvojIvpBd4jrks5qzTlFgaJpZM4J6B8t .

asafm commented 7 years ago

We were forced to switch to another mock framework due to this issue. On Wed, 16 Nov 2016 at 15:16 Asaf Mesika asaf.mesika@gmail.com wrote:

We use different minor Netty versions which are incompatible. If I exclude your version, your code runs with the error I described. If I do the opposite , my code will not work.

Shading your dependencies solves it all. When java 9 is out you will be able to use modules and get back to normal jar sizing.

On Wed, Oct 12, 2016 at 10:47 PM James D Bloom notifications@github.com wrote:

There are two general mechanisms to solve this without making any changes to MockServer:

1.

"Dependency mediation - this determines what version of a dependency will be used when multiple versions of an artifact are encountered. Currently, Maven 2.0 only supports using the "nearest definition" which means that it will use the version of the closest dependency to your project in the tree of dependencies. You can always guarantee a version by declaring it explicitly in your project's POM." see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html 2.

"Excluded dependencies - If project X depends on project Y, and project Y depends on project Z, the owner of project X can explicitly exclude project Z as a dependency, using the "exclusion" element." see http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html. Once the dependency is excluded you can ensure your version of the dependency will be used.

I would recommend using one of these two approaches to resolve your issue.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/jamesdbloom/mockserver/issues/283#issuecomment-253318111, or mute the thread https://github.com/notifications/unsubscribe-auth/AA8Y8RVPk7jZkLJ8qYaeBvojIvpBd4jrks5qzTlFgaJpZM4J6B8t .

jamesdbloom commented 7 years ago

Thats unfortunate that you where forced to use another framework.

However I'm not sure it makes sense to say that shading the version made the code work but using exclusion didn't because the same bytecode is running in the JVM. If the two techniques are implemented correctly they result in the same outcome in terms of classes and code running in the JVM. I suspect if you are finding different results between the different approaches that means one of the two methods was not being used correctly, or something else is going on. Usually to work out exactly what is going on I use dependency:tree task in maven as follows mvn dependency:tree -Dverbose -Dincludes=io.netty

For example this gives the following output in the build for mockserver-netty module.

$ mvn dependency:tree -Dverbose -Dincludes=io.netty
[INFO] Scanning for projects...
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building MockServer & Proxy Netty 3.10.5-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ mockserver-netty ---
[INFO] org.mock-server:mockserver-netty:jar:3.10.5-SNAPSHOT
[INFO] +- org.mock-server:mockserver-core:jar:3.10.5-SNAPSHOT:compile
[INFO] |  +- (io.netty:netty-buffer:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  +- (io.netty:netty-codec:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  +- (io.netty:netty-codec-http:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  +- io.netty:netty-codec-socks:jar:4.0.42.Final:compile
[INFO] |  |  +- (io.netty:netty-codec:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  |  \- (io.netty:netty-handler:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  +- (io.netty:netty-handler:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  \- (io.netty:netty-transport:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] +- org.mock-server:mockserver-integration-testing:jar:3.10.5-SNAPSHOT:test
[INFO] |  +- (io.netty:netty-buffer:jar:4.0.42.Final:test - omitted for duplicate)
[INFO] |  +- (io.netty:netty-codec:jar:4.0.42.Final:test - omitted for duplicate)
[INFO] |  +- (io.netty:netty-codec-http:jar:4.0.42.Final:test - omitted for duplicate)
[INFO] |  +- (io.netty:netty-common:jar:4.0.42.Final:compile - scope updated from test; omitted for duplicate)
[INFO] |  +- (io.netty:netty-handler:jar:4.0.42.Final:test - omitted for duplicate)
[INFO] |  \- (io.netty:netty-transport:jar:4.0.42.Final:test - omitted for duplicate)
[INFO] +- io.netty:netty-buffer:jar:4.0.42.Final:compile
[INFO] |  \- (io.netty:netty-common:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] +- io.netty:netty-codec:jar:4.0.42.Final:compile
[INFO] |  \- (io.netty:netty-transport:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] +- io.netty:netty-codec-http:jar:4.0.42.Final:compile
[INFO] |  +- (io.netty:netty-codec:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  \- (io.netty:netty-handler:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] +- io.netty:netty-common:jar:4.0.42.Final:compile
[INFO] +- io.netty:netty-handler:jar:4.0.42.Final:compile
[INFO] |  +- (io.netty:netty-buffer:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  +- (io.netty:netty-transport:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] |  \- (io.netty:netty-codec:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] \- io.netty:netty-transport:jar:4.0.42.Final:compile
[INFO]    \- (io.netty:netty-buffer:jar:4.0.42.Final:compile - omitted for duplicate)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.249 s
[INFO] Finished at: 2016-11-17T09:29:32+00:00
[INFO] Final Memory: 20M/437M
[INFO] ------------------------------------------------------------------------

Although Java modules could help I don't see how they would make the jar any smaller as MockServer would still have its own dependence on Netty which is different to the version your project depends on thus causing the issue. Therefore MockServer would still need to include its own Netty dependency version.