Javaによる拡張
HadoopやJaqlはJavaで動作するため、Javaによりモジュールが書けると、かなり幅広いことができるようになります。ここでは、JavaでJaqlオペレーターを追加する方法を説明します。
必要な環境
JaqlオペレーターをJavaでコーディングするには、コンパイル環境とjaql.jarが必要です。コンパイル環境は普通のEclipseでかまいません。jaql.jarは、jaqlのlibフォルダーにあるため、それをEclipseプロジェクトのビルドパスに追加してください。
Jsonクラスライブラリ
Jaqlオペレーターをコーディングするにあたり、Jsonクラスライブラリをある程度理解しておく必要があります。JaqlとJavaオペレーターは、Jsonクラスを使ってデータの交換を行うからです。
Jsonクラス群はjaql.jarに含まれています。このクラスは、基本的にパーサーである、と考えてください。読み取りが得意なクラス群です。図1はJsonクラスを利用する際によく使うクラスの継承図です(一部省略)。
大きいくくりから説明していきましょう。すべてのオブジェクトはJsonValueです。
JavaScript配列( [ と ] で囲まれたもの)はJsonArrayとなり、JavaScriptオブジェクト( { と } で囲まれたもの)は、JsonRecordとなります。JsonRecordは、JsonStringとJsonValueがEntryオブジェクトでペアとなり、Iteratorとして集合になっています。JsonArrayとJsonRecordのEntryの値部分にはJsonValueが入ることになっていますから、どのオブジェクト型でもセットされることがあり、無限に階層構造が作れることに注意してください。
JsonValueは、boolean、Date、String、Binary、Double、Decimal、Long、Functionなどの型式になることがあります。
以上の説明を図2で表しています。
Jsonオブジェクトの生成
Jsonオブジェクトを生成するには、Jsonクラス群の関数群を使うのが正しいのですが、非常に煩雑なコードを書かないといけません。そこで、筆者は「文字列でJavaScriptオブジェクトを作り、パースさせる」という方法をおすすめします。こちらはとてもコードがシンプルです。
String jsonString = "['a','2',{'name':'米持','address':'東京都','level':'100'}]"; JsonParser parser = new JsonParser(); JsonValue v = parser.parse(jsonString);
この場合、オブジェクトvは、JsonArrayオブジェクトへキャスト可能です。
オペレーターの実装
JaqlオペレーターをJavaで実装するのは意外と簡単で、ルールはシンプルです。
- Jaqlからは、クラス名で参照する
- 機能関数として「eval」を一つだけ実装する
- 戻り値には、いずれかのJsonオブジェクトを指定する
- 引数には、いずれかのJsonオブジェクトを複数指定できる
たったこれだけです。特定のクラスを継承する必要はありません。
では、簡単な例を説明してみます。ここでは、引数に文字列を二つ受け取り、配列に変換して返す、というJaqlオペレーターをJavaで書いてみます。
ここでは、Eclipseプロジェクト「yone.jaql」を作り、ビルドパスにjaql.jarを追加して作業しています。
package yone.jaql; import com.ibm.jaql.json.parser.JsonParser; import com.ibm.jaql.json.parser.ParseException; import com.ibm.jaql.json.type.JsonArray; import com.ibm.jaql.json.type.JsonString; public class ToArray { public JsonArray eval(JsonString st1, JsonString st2){ JsonParser p = new JsonParser(); try { return (JsonArray)p.parse( "['"+st1+"','"+st2+"']" ); } catch (ParseException e) { e.printStackTrace(); return null; } } }
コンパイルエラーが無くなったら、yone.jaql.jarとしてエクスポートします。ここでは、/home/idcuser/scriptsに置いてあります。
実行
jaqlshellを起動し、以下のコマンドを実行します。
[idcuser@vhost0000 scripts]$ jaqlshell Initializing Jaql - < version: 0.5.2; build time: November 07, 2011, 14:58:20; built for hadoop: 0.20 > jaql> addClassPath("/home/idcuser/scripts/yone.jaql.jar"); true jaql> toArray = javaudf("yone.jaql.ToArray"); jaql> toArray("a","b"); [ "a", "b" ] jaql>
ここでは、以下のコマンドを使っています。
- addClassPath:Java実装のJaql関数が収められているjarを検索するパスを追加します
- javaudf:Java実装のJaql関数をロードし、変数に割り当てます
このJARは、Jaqlジョブが生成されるとき自動的にジョブに取り込まれ、MapReduce環境へ配布されます。jaqlshellを実行するマシン(Master)にのみあればけっこうです。