snakeyaml und funken führt dazu, dass Objekte nicht konstruiert werden können

8

Der folgende Code wird in einer scala-Shell in der snakeyaml-Version 1.17

korrekt ausgeführt %Vor%

Wenn jedoch in Spark (in diesem Fall 2.0.0) ausgeführt wird, lautet der resultierende Fehler:

%Vor%

Ich habe die Scala-Shell mit

gestartet %Vor%

Ich habe die Funkenschale mit

gestartet %Vor%     
placeybordeaux 23.06.2016, 22:25
quelle

1 Antwort

6

Lösung

Erstellen Sie eine eigenständige Anwendung und führen Sie sie mit% aus co_de% anstelle von spark-submit .

Ich habe ein minimales Projekt für dich als hier erstellt . Alles, was Sie tun müssen, ist, beide Dateien ( spark-shell und build.sbt ) in ein Verzeichnis zu stellen und dann folgendes auszuführen:

%Vor%

um ein JAR zu erstellen. Die JAR wird in Main.scala oder einem ähnlichen Ort sein. Sie können SBT von hier erhalten , wenn Sie es noch nicht benutzt haben. Schließlich können Sie das Projekt ausführen:

%Vor%

Die Ausgabe sollte lauten:

%Vor%

Erklärung

Sparks Shell ( REPL ) transformiert alle Klassen, in denen Sie definieren es durch Hinzufügen von target/scala-2.11/sparksnakeyamltest_2.11-1.0.jar -Parameter zu Ihren Konstruktoren. Ich habe es hier erklärt . SnakeYAML erwartet einen Zero-Parameter-Konstruktor für JavaBean-ähnliche Klassen, aber es gibt keinen, so dass es fehlschlägt.

Sie können das selbst ausprobieren:

%Vor%

Wie Sie sehen, transformiert Spark den Konstruktor, indem er einen Parameter vom Typ $iw hinzufügt.

Alternative Lösungen

Definieren Sie Ihre eigene $iw

Wenn Sie wirklich in der Shell arbeiten müssen, könnten Sie Ihre eigene Klasse definieren, die Constructor implementiert und sicherstellen, dass org.yaml.snakeyaml.constructor.BaseConstructor an Konstruktoren übergeben wird, aber das ist eine Menge Arbeit (ich habe tatsächlich meine eigene geschrieben $iw in Scala aus Sicherheitsgründen vor einiger Zeit, so habe ich einige Erfahrungen damit.)

Sie könnten auch eine benutzerdefinierte Constructor fest codieren, um eine bestimmte Klasse ( Constructor in Ihrem Fall) ähnlich der EmailAccount wird in der SnakeYAML-Dokumentation angezeigt . Dies ist viel einfacher, erfordert jedoch das Schreiben von Code für jede Klasse, die Sie unterstützen möchten.

Beispiel:

%Vor%

Sie können dies als Datei speichern und mit DiceConstructor in die REPL laden.

Der Bonusvorteil dieser Lösung besteht darin, dass sie Instanzen von unveränderlichen Fallklassen direkt erstellen kann. Leider scheint Scala REPL Probleme mit Importen zu haben, daher habe ich voll qualifizierte Namen verwendet.

Verwenden Sie keine JavaBeans

Sie können YAML-Dokumente auch einfach als einfache Java-Maps analysieren:

%Vor%

Auf diese Weise muss SnakeYAML keine Spiegelung verwenden.

Allerdings, da Sie Scala verwenden, empfehle ich es zu versuchen MoultingYAML , welches ein Scala-Wrapper für SnakeYAML ist. Es analysiert YAML-Dokumente auf einfache Java-Typen und ordnet sie dann Scala-Typen zu (sogar Ihren eigenen Typen wie :load filename.scala ).

    
Paweł Bartkiewicz 19.11.2016, 02:31
quelle

Tags und Links