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)にのみあればけっこうです。
