web-dev-qa-db-fra.com

NoClassDefFoundError: SparkSession - même si la construction fonctionne

J'ai copié https://github.com/Apache/spark/blob/master/examples/src/main/scala/org/Apache/spark/examples/ml/RandomForestClassifierExample.scala dans un nouveau projet et une configuration build.sbt

name := "newproject"
version := "1.0"
scalaVersion := "2.11.8"

javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
scalacOptions += "-deprecation"

libraryDependencies ++= Seq(
  "org.Apache.spark" % "spark-core_2.11"  % "2.0.0" % "provided",
  "org.Apache.spark" % "spark-sql_2.11"   % "2.0.0" % "provided",
  "org.Apache.spark" % "spark-mllib_2.11" % "2.0.0" % "provided",
  "org.jpmml" % "jpmml-sparkml" % "1.1.1",
  "org.Apache.maven.plugins" % "maven-shade-plugin" % "2.4.3",
  "org.scalatest" %% "scalatest" % "3.0.0"
)

Je suis capable de le construire à partir d'IntelliJ 2016.2.5, mais je reçois le message d'erreur

Exception in thread "main" Java.lang.NoClassDefFoundError: org/Apache/spark/sql/SparkSession$
    at org.Apache.spark.examples.ml.RandomForestClassifierExample$.main(RandomForestClassifierExample.scala:32)
    at org.Apache.spark.examples.ml.RandomForestClassifierExample.main(RandomForestClassifierExample.scala)
    at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62)
    at Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
    at Java.lang.reflect.Method.invoke(Method.Java:498)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.Java:147)
Caused by: Java.lang.ClassNotFoundException: org.Apache.spark.sql.SparkSession$
    at Java.net.URLClassLoader.findClass(URLClassLoader.Java:381)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:424)
    at Sun.misc.Launcher$AppClassLoader.loadClass(Launcher.Java:331)
    at Java.lang.ClassLoader.loadClass(ClassLoader.Java:357)
    ... 7 more

Je suis même capable de cliquer sur SparkSession et d’obtenir le code source. Quel est le problème?

15
Make42

Lorsque vous indiquez provided pour votre dépendance, la construction sera compilée en fonction de cette dépendance, mais elle ne sera pas ajoutée au chemin de classe au moment de l'exécution (elle est supposée y être déjà).

C'est le paramètre correct lors de la création de travaux Spark pour spark-submit (car ils s'exécuteront à l'intérieur d'un conteneur Spark qui fournit la dépendance, et l'inclure une deuxième fois causerait des problèmes).

Toutefois, lorsque vous exécutez localement, vous avez besoin de cette dépendance. Vous pouvez donc modifier la construction pour ne pas avoir cette provided (mais vous devez alors l'ajuster lors de la génération pour soumettre le travail) ou configurer votre chemin d'accès aux classes d'exécution dans le répertoire IDE pour qu'il contienne déjà ce fichier .jar.

18
Thilo

Dans mon cas, j’utilisais mon cluster local Cloudera CDH 5.9.0 avec Spark 1.6.1 installé par défaut et Spark 2.0.0 installé en tant que colis. Ainsi, spark-submit utilisait Spark 1.6.1 alors que spark2-submit était Spark 2.0.0. Comme SparkSession n’existait pas dans la version 1.6.1, l’erreur a été renvoyée. L'utilisation de la bonne commande spark2-submit a résolu le problème.

4
Garren S

J'ai eu le même problème et il a été corrigé après avoir défini la variable SPARK_HOME avant de soumettre le job d'allumage à l'aide de spark-submit.

2
Ravi

Ok, j'ai atterri ici en suivant un lien sur sbt gitter channel cherchant autre chose. J'ai une solution pour cela. Thilo a décrit le problème correctement. Votre sbt indique "fourni", ce qui est correct pour votre environnement cible lorsque vous l'exécutez sur votre cluster où les bibliothèques d'étincelles sont fournies, mais lorsque vous exécutez localement dans IntelliJ, vous devez "fournir" ces bibliothèques externes à IntelliJ au moment de l'exécution et façon de le faire serait 

  1. Faites un clic droit sur votre projet -> 
  2. Ouvrir les paramètres du module -> 
  3. Sélectionnez le menu Libraries on LHS -> 
  4. Cliquez sur + signe -> 
  5. choisissez 'De Maven' -> 
  6. Tapez ou recherchez les coordonnées maven. Vous pouvez rechercher en tapant le nom de la bibliothèque et en appuyant sur la touche de tabulation. Cela affichera un menu déroulant de toutes les correspondances et vous pourrez choisir la version correcte pour votre bibliothèque -> 
  7. Cliquez sur OK 

Notez que lorsque vous avez redémarré IntelliJ, vous devrez peut-être répéter ce processus. J'ai trouvé que c'était le cas pour IntelliJ IDEA 2016.3.6 sur OS X El Captain. 

1
sparker