Category Archives: maven

解决Jersey 2.x Jersey 1.x冲突问题– UriBuilder问题

最近在使用Java Docker来控制Docker的过程中发现了一个问题,因为Java Docker使用的是Jersey 2.x,maven pom如下:

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

而集群中Hadoop的依赖都是Jersey 1.x。所以在引用的过程中提示如下错误:

Exception in thread "main" java.lang.AbstractMethodError: javax.ws.rs.core.UriBuilder.uri(Ljava/lang/String;)Ljavax/ws/rs/core/UriBuilder;
        at javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:119)
        at org.glassfish.jersey.client.JerseyWebTarget.<init>(JerseyWebTarget.java:71)
        at org.glassfish.jersey.client.JerseyClient.target(JerseyClient.java:290)
        at org.glassfish.jersey.client.JerseyClient.target(JerseyClient.java:76)
        at com.github.dockerjava.jaxrs.JerseyDockerCmdExecFactory.init(JerseyDockerCmdExecFactory.java:237)
        at com.github.dockerjava.core.DockerClientImpl.withDockerCmdExecFactory(DockerClientImpl.java:161)
        at com.github.dockerjava.core.DockerClientBuilder.build(DockerClientBuilder.java:45)

很明显这是Jersey版本mismatch导致的,在解决这一过程中,走了不少弯路,包括采用了maven shade plugin来解决,采用exclude一些jar包来解决等,都没有解决问题。
最后还是从错误出发,这个错误的原因是fromUri这个方法是一个抽象方法,没有实现,也就是只有抽象方法,没有实现类。
再把代码看一下,在Jersery 2.x中的实现为:

public abstract UriBuilder uri(String var1);

它的实现类为org.glassfish.jersey.uri.internal.JerseyUriBuilder,看到这一部分,大概了解到原因是缺少了实现类。于是加入相应的dependency到pom中

        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>2.23.1</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.containers</groupId>
            <artifactId>jersey-container-servlet-core</artifactId>
            <version>2.23.1</version>
        </dependency>

加入后再打包,解决这一问题。

使用Maven-Shade-Plugin 解决jar包依赖冲突

在我们向集群中提交任务的时候,常常因为app的jar包与Hadoop CLASSPATH中jar包冲突导致了No such method错误等等。究其原因,就是因为hadoop执行脚本启动用户jar包之前会设置CLASSPATH,CLASSPATH中有版本不一致,jar包启动读取某些库的版本与开发时候的版本不一致,导致了No such method错误。
为了解决这一问,我们可以采用Maven-shade-plugin,这个插件的主要作用是将打包过程中内部的jar包重新命名为新的名称,通过映射解决这一问,从而防止由于引用不同版本导致的问题,例如
org.codehaus.plexus.util包跟集群中的包有依赖冲突,我们将它重新命名为org.shaded.plexus.util

<project>
  ...
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>3.0.0</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>shade</goal>
            </goals>
            <configuration>
              <relocations>
                <relocation>
                  <pattern>org.codehaus.plexus.util</pattern>
                  <shadedPattern>org.shaded.plexus.util</shadedPattern>
                  <excludes>
                    <exclude>org.codehaus.plexus.util.xml.Xpp3Dom</exclude>
                    <exclude>org.codehaus.plexus.util.xml.pull.*</exclude>
                  </excludes>
                </relocation>
              </relocations>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  ...
</project>

Maven Classifier引用问题

最近在写集群的一些UT,使用了MiniDFSCluster以及MiniYarnCluster来搭建测试的模拟集群。在pom中引入依赖的时候发现了问题,通常引入依赖的时候使用下面的pom语句

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-server-tests</artifactId>
            <version>2.7.2</version>
            <scope>test</scope>
        </dependency>

加入后发现无法找到需要的类,找到jar包后比对了一下,发现引入的是hadoop-yarn-server-tests-2.7.2.jar,而我们需要的是hadoop-yarn-server-tests-2.7.2-tests.jar,查了一下发现需要加入classifier. classifier就是在maven主项目外通过标识能够获取的jar包,算作Maven pom的属性之一。所以修改pom文件如下就可以解决这一问题。加入classifier为tests之后就能够引入对应的jar包了。

        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-yarn-server-tests</artifactId>
            <version>2.7.2</version>
            <classifier>tests</classifier>
            <scope>test</scope>
        </dependency>