したがって、次のユースケースがあります。
DSL のようなインターフェイスを提供することで、特定のドメインでの Spark データフレームの使用を簡素化しています。このコードはすべて、Maven シェード プラグインによって作成されたファット jar に入れられます。(fat jar = spark と hadoop の依存関係なし)
このファット jar にはメイン クラスがあり、それを JavaMain と呼びましょう。
JavaMain 内で、残りの呼び出しを行って、内容が有効な DSL である文字列を取得します。
初期設定オブジェクトを使用して IMain オブジェクトをインスタンス化します。そして、いくつかの変数をバインドします。imain.bind メソッドを使用します。
ただし、このバインドは次のエラーで失敗します。
Set failed in bind(results, com.dhruv.dsl.DslDataFrame.DSLResults, com.dhruv.dsl.DslDataFrame$DSLResults@7650a5f3)
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:734)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.callEither(IMain.scala:738)
at scala.tools.nsc.interpreter.IMain.bind(IMain.scala:625)
at scala.tools.nsc.interpreter.IMain.bind(IMain.scala:661)
at scala.tools.nsc.interpreter.IMain.bind(IMain.scala:662)
at com.thoughtworks.dsl.DSL.run(DSL.scala:44)
at com.thoughtworks.dsl.JavaMain.run(JavaMain.java:30)
at com.thoughtworks.dsl.JavaMain.main(JavaMain.java:43)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.spark.deploy.SparkSubmit$.org$apache$spark$deploy$SparkSubmit$$runMain(SparkSubmit.scala:665)
at org.apache.spark.deploy.SparkSubmit$.doRunMain$1(SparkSubmit.scala:170)
at org.apache.spark.deploy.SparkSubmit$.submit(SparkSubmit.scala:193)
at org.apache.spark.deploy.SparkSubmit$.main(SparkSubmit.scala:112)
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.lang.ClassCastException: com.thoughtworks.dsl.DslDataFrame$DSLResults cannot be cast to com.thoughtworks.dsl.DslDataFrame$DSLResults
at $line3.$eval$.set(<console>:6)
at $line3.$eval.set(<console>)
... 21 more
詳細なコンテキスト:
これを試してみると、クラスパスに問題がありました。私はそれらすべてを解決できていないようですが。
以前に設定オブジェクトを作成したとき、私は次のようなことをしていました:
val settings = {
val x = new Settings()
x.classpath.value += File.pathSeparator + System.getProperty("java.class.path")
x.usejavacp.value = true
x.verbose.value = true
x
}
ただし、spark サブミットを実行すると、クラスパスに spark および hadoop 関連の jar しかないため、これは機能していないように見えました。
次に、クラスパスに次を追加しました。
val urLs: Array[URL] = Thread.currentThread.getContextClassLoader.asInstanceOf[URLClassLoader].getURLs
そして、次のことを行いました:
val settings = {
val x = new Settings()
x.classpath.value += File.pathSeparator + urLs(0)
x.usejavacp.value = true
x.verbose.value = true
x
}
これは、オブジェクトをバインドするために使用しているコードです。
interpreter.bind("notagin", new SomeDummyObject)
これにより、先ほど添付した例外がスローされます。興味深いことに、次のコードが機能します: (つまり、Interpreter 内の同じオブジェクトの import と new は問題を引き起こしません)。
interpreter.interpret(
"""
import com.dhruv.dsl.operations._
import com.dhruv.dsl.implicits._
import com.dhruv.dsl.DslDataFrame._
import org.apache.spark.sql.Column
import com.dhruv.dsl._
implicit def RichColumn(column: Column): RichColumn = new RichColumn(column)
val justdont = new SomeDummyObject()
justdont.justdontcallme(thatJson)
"""
)
私が知っていて気になっているもう 1 つの詳細は、IMain がクラスローダーを内部的に変更することです。それが問題の原因であるかどうかはわかりません。
どんな助けでも大歓迎です。