今天想在之前的一个项目里加一个对docker的监控功能,调研了一下看到docker-java用的人比较多,于是在pom文件里加入了该依赖:

 <dependency>
     <groupId>com.github.docker-java</groupId>
     <artifactId>docker-java</artifactId>
     <version>3.1.5</version>
</dependency>

跑了一下,报错了:

看到这个NoSuchMethodError,应该是版本冲突了,看了下maven的依赖里,javax.ws.rs这个包的版本是2.1,是有addAll方法的,maven工具里的依赖列表里显示的是omitted for duplicate,所以应该不是直接和某个jar包版本冲突了,于是直接在intellij里全局(double shift:search everywhere)搜了下javax.ws.rs.core.MultivalueMap这个类,发现果然是和jersey-core-1.9.jar这个jar包里的类冲突了,并且该类里没有addAll方法。

我本来想直接把这个类升级或者删除,但发现该类在hadoop的一些包里被用到了,无法删除。搞了好一会儿都解决不了,本来想放弃这个包了,想换成docker-client试试看,结果还是报一样的错,看来这个错是绕不过去了。

于是我去找了下maven加载jar的顺序,maven寻找jar包主要有两个原则:最短路径原则和声明优先原则。具体我参考的是:https://cloud.tencent.com/developer/article/1429940

那么我现在就要找到这个jersey-core-1.9.jar究竟被那个jar包依赖了,使用mvn dependency:tree > {输出的txt路径}可以把所有依赖包的树状结构打印到一个文件里,然后在这个文件里搜索jersey-core这个包即可。最终我找到在hadoop-aws 2.7.2的hadoop-common依赖里用到了这个包。于是我在pom文件里将docker-java的依赖声明提到了hadoop之前。

本来以为大功告成了,结果一跑又出错了:

查了一下,依然是jar包冲突的问题。看到一个解决方案:http://www.voidcn.com/article/p-mrqkkcfq-bob.html,很简单粗暴。

于是我在jersey-core里把UriBuilder.url这个抽象方法的实现类:UriBuilderImp给直接删掉了,问题解决!

 

后续:

后来有一天再跑这个工程的时候,突然报错说被我删掉的那个UriBuilderImp 找不到了,于是继续求解。。。

解决方案:

通过maven查看依赖树发现hadoop-aws这个包用到了jersey-core,

保留原来的jar包,并在pom里修改:

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-aws</artifactId>
            <version>${hadoop.version}</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>log4j</groupId>
                    <artifactId>log4j</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.servlet</groupId>
                    <artifactId>servlet-api</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-core</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-json</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jersey</groupId>
                    <artifactId>jersey-server</artifactId>
                </exclusion>
            </exclusions>
        </dependency>

把关于jersey的三个core json和server都放到exclusion里就好了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐