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?
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.
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.
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.
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
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.