SQL Server 2019 CTP2 で Java を動かしてみた - お だ のスペース で紹介した external_script で Java を呼べる機能を使って、Spark Framework: An expressive web framework for Kotlin and Java を実行してみました。
meetup app osaka@3 で Spark on SQL Server? という話ししました #meetupapp - お だ のスペース のスライドでも書いてますが、動いてますが外部*1から HTTP アクセス出来ませんでした。
なので、同じメソッド内から OkHttp で GETアクセスして動作確認しています。
Java 久しぶりすぎて、Maven も Gradle も書かれへんかった。。
適当に拾ってきたものをいじって、
- com.sparkjava.spark-core
- com.squareup.okhttp3.okhttp
を依存関係に突っ込んでるだけです。
幾つか必要な static フィールドがありますが、 How to call Java from SQL - SQL Server Machine Learning Services - SQL Server | Microsoft Docs を見てください。
実装の中で使わなくても今回のケースでは問題無いです。*2
package pkg; import static spark.Spark.*; import java.io.IOException; import java.time.LocalDateTime; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; public class Hoge { public static int[] inputDataCol1 = new int[1]; public static String[] inputDataCol2 = new String[1]; //Required: Input null map. Size just needs to be set to "1" public static boolean[][] inputNullMap = new boolean[1][1]; //Required: Output data columns returned back to SQL Server public static int[] outputDataCol1; public static String[] outputDataCol2; //Required: Output null map. Is populated with true or false values //to indicate nulls public static boolean[][] outputNullMap; //Optional: This is only required if parameters are passed with @params // from SQL Server in sp_execute_external_script // n is giving us the size of ngram substrings public static int param1; //Optional: The number of rows we will be returning public static int numberOfRows; //Required: Number of output columns returned public static short numberOfOutputCols; public static void runSqlServer() { get("/hello", (request, response) -> "<h1>Hello Spark!! on SQL Server?</h1>"); try { String res = run("http://localhost:4567/hello"); System.out.println(res); } catch (IOException e) { System.out.println(e); } } static OkHttpClient client = new OkHttpClient(); static String run(String url) throws IOException { Request request = new Request.Builder() .url(url) .build(); try (Response response = client.newCall(request).execute()) { return response.body().string(); } } }
これで HTTP アクセスが失敗する場合は、spark の設定 と HTTP アクセスの間に Thread.sleep なりなんなりで処理を遅らせてください。
Thread.sleep 入れて、実行中にポートの待ち受けを確認するとこんな感じです。
スライドにも書いてますが、Java.exe ではなく、ExtHost.exe として動いています。
ExtHost.exe として、4567 ポートで待ち受けています。
メソッド内の処理が全て終わってしまう*3と、spark のサーバーは落ちてしまいます。
外部からアクセス出来ないし、ずっと動かすには sleep や無限ループ等でメソッドが終わらないようにする必要があります。
※ExtHost にタイムアウトがあるかは未検証なので、無限ループの場合は注意
という訳で、余り実用向けではありませんが遊ぶ分には問題ありません。
sparkjava の実行とは関係無いですが、OkHttp なりなんなりで、外部にHTTPアクセスする事も出来ます。
なので外部のAPIとかを叩いてデータを引っ張ってきて遊ぶことも出来ると思います。
今回ご紹介したものは、「実運用を目指していない」お遊びのものなので、本番でこの構成を使おうとか間違っても辞めてね。。