2017-12-21 5 views
2

私はsbt 1.0.4とsbt-assembly 0.14.6を使ってSparkアプリケーションをアセンブルしようとしています。 IntelliJ IDEAまたは​​に発売されたときにSparkアプリケーションが、 "ClassNotFoundException:データソースの検索に失敗しました:jdbc"がsbtアセンブリのuber-jarとして失敗するのはなぜですか?

スパークアプリケーションが正常に動作しますが、私は(Windowsの10でCMD)コマンドラインで組み立てられユーバー-jarファイルを実行する場合:

java -Xmx1024m -jar my-app.jar 

私は次の例外を取得します:

スレッド "main"の例外java.lang.ClassNotFoundException:データソースの検索に失敗しました:jdbc。パッケージを見つけるにはhttp://spark.apache.org/third-party-projects.html

Sparkアプリケーションは次のようになります。

package spark.main 

import java.util.Properties  
import org.apache.spark.sql.SparkSession 

object Main { 

    def main(args: Array[String]) { 
     val connectionProperties = new Properties() 
     connectionProperties.put("user","postgres") 
     connectionProperties.put("password","postgres") 
     connectionProperties.put("driver", "org.postgresql.Driver") 

     val testTable = "test_tbl" 

     val spark = SparkSession.builder() 
      .appName("Postgres Test") 
      .master("local[*]") 
      .config("spark.hadoop.fs.file.impl", classOf[org.apache.hadoop.fs.LocalFileSystem].getName) 
      .config("spark.sql.warehouse.dir", System.getProperty("java.io.tmpdir") + "swd") 
      .getOrCreate() 

     val dfPg = spark.sqlContext.read. 
      jdbc("jdbc:postgresql://localhost/testdb",testTable,connectionProperties) 

     dfPg.show() 
    } 
} 

build.sbtです。

name := "apache-spark-scala" 

version := "0.1-SNAPSHOT" 

scalaVersion := "2.11.8" 

mainClass in Compile := Some("spark.main.Main") 

libraryDependencies ++= { 
    val sparkVer = "2.1.1" 
    val postgreVer = "42.0.0" 
    val cassandraConVer = "2.0.2" 
    val configVer = "1.3.1" 
    val logbackVer = "1.7.25" 
    val loggingVer = "3.7.2" 
    val commonsCodecVer = "1.10" 
    Seq(
     "org.apache.spark" %% "spark-sql" % sparkVer, 
     "org.apache.spark" %% "spark-core" % sparkVer, 
     "com.datastax.spark" %% "spark-cassandra-connector" % cassandraConVer, 
     "org.postgresql" % "postgresql" % postgreVer, 
     "com.typesafe" % "config" % configVer, 
     "commons-codec" % "commons-codec" % commonsCodecVer, 
     "com.typesafe.scala-logging" %% "scala-logging" % loggingVer, 
     "org.slf4j" % "slf4j-api" % logbackVer 
    ) 
} 

dependencyOverrides ++= Seq(
    "io.netty" % "netty-all" % "4.0.42.Final", 
    "commons-net" % "commons-net" % "2.2", 
    "com.google.guava" % "guava" % "14.0.1" 
) 

assemblyMergeStrategy in assembly := { 
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard 
    case x => MergeStrategy.first 
} 

誰もが知っている理由は何ですか?

[UPDATE] GitHubのリポジトリは、トリックをした公式から取ら

構成:

assemblyMergeStrategy in assembly := { 
    case PathList("META-INF", xs @ _*) => 
    xs map {_.toLowerCase} match { 
     case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) => 
     MergeStrategy.discard 
     case ps @ (x :: xs) if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") => 
      MergeStrategy.discard 
     case "services" :: _ => MergeStrategy.filterDistinctLines 
     case _ => MergeStrategy.first 
    } 
    case _ => MergeStrategy.first 
} 

答えて

1

質問はほとんどWhy does format("kafka") fail with "Failed to find data source: kafka." with uber-jar?のApache Mavenを使用した他のOPはuber-を作成することの違いがありますjarとここではsbtについてです(正確にはsbt-assemblyプラグインの設定)。


データソースの短い名前(別名別名)、例えばjdbcまたはkafkaは、対応するMETA-INF/services/org.apache.spark.sql.sources.DataSourceRegisterDataSourceRegisterを登録している場合にのみ利用可能です。

jdbcの別名スパークSQLは、次のエントリでMETA-INF/services/org.apache.spark.sql.sources.DataSourceRegisterを使用して動作するように(他のものがある)。

org.apache.spark.sql.execution.datasources.jdbc.JdbcRelationProvider 
That's what ties jdbc alias

データソースとアップ。

そしてあなたはそれをuber-jarから次の​​で除外しました。

assemblyMergeStrategy in assembly := { 
    case PathList("META-INF", xs @ _*) => MergeStrategy.discard 
    case x => MergeStrategy.first 
} 

注単にMergeStrategy.discardcase PathList("META-INF", xs @ _*)。それが根本的な原因です。ただ、

は「インフラ」が利用可能であることを確認するために、あなたはその完全修飾名(エイリアスではなく)によって jdbcデータソースを使用することができ、これを試してみてください。

spark.read. 
    format("org.apache.spark.sql.execution.datasources.jdbc.JdbcRelationProvider"). 
    load("jdbc:postgresql://localhost/testdb") 

はあなたが原因他の問題が表示されますurlのような欠落しているオプションに... を脱出しています。

解決策は、jdbcデータソースを含むすべてのデータソースを持つuber-jarを作成します。MergeStrategy.concatすべてです。

case "META-INF/services/org.apache.spark.sql.sources.DataSourceRegister" => MergeStrategy.concat 
+0

ありがとうございます。実際には[ここ](https://github.com/sbt/sbt-assembly)から取得されたデフォルト設定がこのトリックでした。更新された質問を参照してください。 – korbee82

+0

'case 'サービス" :: _ => MergeStrategy.filterDistinctLines "だけが機能するかどうかを調べることができますか? 'META-INF/services/*'だけに興味があるので、行だけで十分です。更新していただきありがとうございます(私の答えを受け入れる)! –

+1

私は試しましたが、うまくいかなかった。 – korbee82

関連する問題