解决Maven、sbt无法下载依赖包的问题

大数据学习路线图

在编写使用 Maven 编译运行 Storm 代码教程时遇到了一个比较棘手的问题,首次编译代码需要下载相应的依赖包,有时会下载失败,一直以为多试几次就可以,但后来发现,并非是简单的网络问题,依赖包链接(clojars.org)在浏览器中可以打开,却始终无法通过 Maven 进行下载。困扰了好几天终于解决了,在此记录一下遇到的问题以及解决方法。

默认镜像无法下载依赖的问题

发现这个问题的缘由是我在另一台电脑上编译运行 Storm 代码时,一运行 maven .... 进行编译就遇到了问题,并且试了好几次,间隔一两天后还是会如此,输出信息如下:

Downloading: https://repo.maven.apache.org/maven2/org/apache/storm/storm/0.9.6/storm-0.9.6.pom
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[FATAL] Non-resolvable parent POM for org.apache.storm:storm-starter:[unknown-version]: Could not transfer artifact org.apache.storm:storm:pom:0.9.6 from/to central (https://repo.maven.apache.org/maven2): java.security.ProviderException: java.security.KeyException and 'parent.relativePath' points at wrong local POM @ line 20, column 11
 @ 
[ERROR] The build could not read 1 project -> [Help 1]
[ERROR]   
[ERROR]   The project org.apache.storm:storm-starter:[unknown-version] (/usr/local/storm/examples/storm-starter/pom.xml) has 1 error
[ERROR]     Non-resolvable parent POM for org.apache.storm:storm-starter:[unknown-version]: Could not transfer artifact org.apache.storm:storm:pom:0.9.6 from/to central (https://repo.maven.apache.org/maven2): java.security.ProviderException: java.security.KeyException and 'parent.relativePath' points at wrong local POM @ line 20, column 11 -> [Help 2]

在下载第一个 pom 文件时就出错了,提示无法从中心库(Maven central)中下载,并且 'parent.relativePath' 属性指向的是一个错误的本地 POM。'parent.relativePath' 这个错误实际上是个误导,这个错误在这边是没有影响的,只要换个 Maven 镜像就可以了,可使用开源中国 Maven 库来解决该问题。

修改 Maven 的配置文件(安装目录下的 conf/settings.xml 文件),将 <mirrors>..</mirrors> 间的内容改为:

<mirrors>
    <!-- mirror | Specifies a repository mirror site to use instead of a given 
        repository. The repository that | this mirror serves has an ID that matches 
        the mirrorOf element of this mirror. IDs are used | for inheritance and direct 
        lookup purposes, and must be unique across the set of mirrors. | -->
    <mirror>
        <id>nexus-osc</id>
        <mirrorOf>central</mirrorOf>
        <name>Nexus osc</name>
        <url>http://maven.oschina.net/content/groups/public/</url>
    </mirror>
    <mirror>
        <id>nexus-osc-thirdparty</id>
        <mirrorOf>thirdparty</mirrorOf>
        <name>Nexus osc thirdparty</name>
        <url>http://maven.oschina.net/content/repositories/thirdparty/</url>
    </mirror>
</mirrors>

以及将 <profile>...<profile> 之间的内容改为:

<profile>
    <id>jdk-1.4</id>

    <activation>
        <jdk>1.4</jdk>
    </activation>

    <repositories>
        <repository>
            <id>nexus</id>
            <name>local private nexus</name>
            <url>http://maven.oschina.net/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>nexus</id>
            <name>local private nexus</name>
            <url>http://maven.oschina.net/content/groups/public/</url>
            <releases>
                <enabled>true</enabled>
            </releases>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</profile>

改好后保存,再次执行 maven ... 应该就可以了。

Maven 第三方库(thirdparty)

开源中国 Maven 库的说明里是说“补充: 如果还需要osc的thirdparty仓库或多个仓库,需要如下修改”,但实测若没有加上thirdparty(也就是上述 mirror 设置中,id 为 nexus-osc-thirdparty 的那一项)的话,可能会遇到如下的错误:

Could not find artifact clj-time:clj-time:jar:0.4.1 in nexus-osc (http://maven.oschina.net/content/groups/public/)

clojars.org 的 https 证书问题

有时需要多试几次才能下载完全部依赖包,通常遇到的问题是 clojars.org 这个网站的依赖包下载不了(clojars.org这个网站确实有时无法访问),提示的错误如下:

Downloading: https://clojars.org/repo/clj-time/clj-time/0.4.1/clj-time-0.4.1.pom
Downloading: https://clojars.org/repo/compojure/compojure/1.1.3/compojure-1.1.3.pom
...
Downloading: https://clojars.org/repo/reply/reply/0.3.0/reply-0.3.0.pom

Could not transfer artifact clj-time:clj-time:pom:0.4.1 from/to clojars (https://clojars.org/repo/): java.security.ProviderException: java.security.KeyException

试了下,通过浏览器可以访问列出来无法下载的连接,但通过 wget 命令却无法下载,提示“证书通用名 "www.clojars.org" 与所要求的主机名 "clojars.org" 不符”。注意到 Maven 给出的错误为“java.security.ProviderException: java.security.KeyException”,搜索了下,看出这是 https 的问题。把 https://clojars.org 的证书下载来看,证书的通用名(CN)为 www.clojars.org,而不是 *.clojars.org...

通过 http 可以访问,但通过 https 无法访问,看似不好解决,但后来脑洞大开,在配置文件中为 clojars.org 单独设置一个 http 镜像就可以了。

在 Maven 配置文件中添加如下配置:

<!-- 在 <mirrors> .. </mirrors> 中添加如下配置: -->
<mirror>
    <id>clojars</id>
    <mirrorOf>clojars</mirrorOf>
    <url>http://clojars.org/repo/</url>
</mirror>

<!-- 在 <repositories> .. </repositories> 中添加如下配置: -->
<repository>
        <id>clojars</id>
        <url>http://clojars.org/repo/</url>
</repository>

配置完再次编译,perfect,问题完美解决,从 clojars 下载的依赖包都通过 http 下载了...

如果你需要这份配置文件,可以直接下载笔者修改好的版本,下载地址:http://pan.baidu.com/s/1qXwZlsK,下载后执行如下命令替换配置文件:

cp ~/下载/maven-settings.xml /usr/local/maven/conf/settings.xml   # /usr/local/maven 为maven的安装目录

sbt 也存在 https 的问题

在编写 Spark 快速入门指南时,需要使用 sbt 编译打包 Scala 编写的代码,同样遇到了 https 的问题,运行时会出现如下错误:

Getting org.scala-sbt sbt 0.13.9 ...

:: problems summary ::
:::: WARNINGS
        module not found: org.scala-sbt#sbt;0.13.9

    ==== local: tried
      /home/hadoop/.ivy2/local/org.scala-sbt/sbt/0.13.9/ivys/ivy.xml
      -- artifact org.scala-sbt#sbt;0.13.9!sbt.jar:
      /home/hadoop/.ivy2/local/org.scala-sbt/sbt/0.13.9/jars/sbt.jar

...

        ::::::::::::::::::::::::::::::::::::::::::::::
        ::          UNRESOLVED DEPENDENCIES         ::
        ::::::::::::::::::::::::::::::::::::::::::::::
        :: org.scala-sbt#sbt;0.13.9: not found
        ::::::::::::::::::::::::::::::::::::::::::::::


:::: ERRORS
    Server access Error: java.security.ProviderException: java.security.KeyException url=https://jcenter.bintray.com/org/scala-sbt/sbt/0.13.9/sbt-0.13.9.pom

:: USE VERBOSE OR DEBUG MESSAGE LEVEL FOR MORE DETAILS
unresolved dependency: org.scala-sbt#sbt;0.13.9: not found
Error during sbt execution: Error retrieving required libraries
  (see /home/hadoop/.sbt/boot/update.log for complete log)
Error: Could not retrieve sbt 0.13.9

这里有两个问题:

  1. 用浏览器访问给出的链接,也是 404 的状态,这就需要修改 repositories 的地址。
  2. 提示 “Server access Error: java.security.ProviderException: java.security.KeyException”,但通过浏览器可以访问,就跟 Maven 遇到的问题一样,需要将 https 改成通过 http 访问。

sbt 修改镜像会稍微麻烦一些,需要先下载官方的 sbt-launch.jar,解压后修改配置文件,再重新打包,可以下载笔者修改好的版本: http://pan.baidu.com/s/1eRyFddw

自行修改的话,命令如下:

mkdir ~/sbt
cd ~/sbt
wget https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.13.9/sbt-launch.jar -O ./sbt-launch.jar      # 下载
unzip -q ./sbt-launch.jar                 # 解压

需要修改其中的 ./sbt/sbt.boot.properties 文件(vim ./sbt/sbt.boot.properties),将 [repositories] 处修改为如下内容(即增加了一条 oschina 镜像,并且将原有的 https 镜像都改为相应的 http 版):

[repositories]
  local
  oschina: http://maven.oschina.net/content/groups/public/
  jcenter: http://jcenter.bintray.com/
  typesafe-ivy-releases: http://repo.typesafe.com/typesafe/ivy-releases/, [organization]/[module]/[revision]/[type]s/[artifact](-[classifier]).[ext], bootOnly
  maven-central: http://repo1.maven.org/maven2/

保存后,重新打包 jar:

rm ./sbt-launch.jar         # 删除旧的
jar -cfM ./sbt-launch.jar .       # 重新打包
ls | grep -v "sbt-launch.jar" | xargs rm -r    # 解压后的文件已无用,删除

注意打包时,需要使用 -M 参数,否则 ./META-INF/MANIFEST.MF 会被修改,导致运行时会出现 “./sbt-launch.jar中没有主清单属性” 的错误。