2010-11-27

TemplateエンジンVelocityを使ってみよう

今さら感がありますが、TemplateエンジンVelocityについてです。ずいぶん昔からあったフレームワークですが、私自身、以前はJSFベースで作っていたので全く眼中になかったというのが正直なところ。ただ今はGWTに移行したこともあり、Servlet回帰も含めて再評価しているところです。

ライブラリのダウンロードと設定

以下のサイトからダウンロードして下さい。


クラスパスには、"velocity-1.6.4.jar"を追加しておくとよいでしょう。

Velocityの仕組み
利用方法はとてもシンプルです。まず、Templeteとなるファイル(拡張子はvm)を用意し、そこにVelocityの命令文法に従ってテンプレートを記述していきます。Velocityの文法と言っても身構えることはなく、通常のテキスト文の中に命令文法を記述するだけです。その特徴は以下のとおりです。

  • 変数は頭に$を付ける。任意の位置に記述することが可能。
  • foreach, if 文等の繰り返しや条件分岐の処理ができる。
  • Velocityの命令文法を記述した行は先頭に#を付ける

テンプレートファイルの書き方

ここではJSON形式のファイル作成を対象としてみます。

{"name": "$user.name", "age": "$user.age"}


Javaの記述の仕方は以下のようになります。

StringWriter w = new StringWriter();
 //マッピングするデータをクラスに格納
 testUser u = new testUser();
 u.setName("おち");
 u.setAge(20);
 Velocity.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM, new JdkLogChute());
 Velocity.setProperty(Velocity.INPUT_ENCODING, "UTF-8");
 Velocity.setProperty(Velocity.OUTPUT_ENCODING, "UTF-8");
 Velocity.init(); // 初期化
 VelocityContext context = new VelocityContext();
 //テンプレートとのマッピング
 context.put("user", u);
 //テンプレートファイルの指定
 Template template = Velocity.getTemplate("/WEB-INF/test.vm", "UTF-8");
 //実行。結果はwに出力
 template.merge(context, w);

補足しますと、上記のプログラムはテンプレート内の変数とJava内でのデータ変数をクラスの受け渡しによりマッピングさせていることがわかります。

今回はシンプルなJSONを例にしましたが、複雑な形式のファイルをテンプレートを利用して動的に生成することができます。XMLは当然のこと、HTMLの記述もできます。また、Texような文書ファイルにも適用できるでしょう。

これをみて思うのはJSPと何が違うのかということですが、まあVelocityのほうはあくまでもTemplateエンジンとしてシンプルな枠組みになっているような気がします。JSPはあれもこれもいろいろできてしまうわけで、、、
個人的には、XMLとかJSONとかのフォーマットをServlet等で出力する際に、print文とか使ってコード内にガガガッと書かれるのは勘弁してほしいなと思っていたので、VelocityみたいなTemplateエンジンは魅力的なだなぁといまさらながら感じた次第です。

追記:注意事項
上記のサンプルで、testUserというデータクラスを用意していますが、このデータクラスは必ずpublicなものにして下さい。ここをうっかり忘れてて、テンプレートに反映されないという自体に何回か繰り返したので、自分用のメモ追記です。

2010-11-26

GAE/JでAmazon Product Advertising APIを使い始める際の注意事項

Amazon Product Advertising APIで遊んでいるわけですが、ちょっと注意することがあったのでメモ。このAPIについては、認証シグネチャーを要求するようになって、プログラム的にめんどくさそうな感じはしてるが、実際はサンプルプログラムに同梱されているSignedRequestHelperクラスを利用すれば問題ない。。。。はずなんですが、それでも認証のエラーが出ることがあります。これはBASE64エンコードの処理でトラブルらしいのですが、いろいろ情報が錯綜しているようなので,整理してみます。

【GAE/J上で動作させる場合】

  • commons-codec-1.3を利用するとOK
  • 最新版であるcommons-codec-1.4を利用するとエラーになります。

参考までに、

【GAE/J以外で動作させる場合(例えばGlassfishの場合)】

  • commons-codec-1.4での動作OK

ということらしいです。

また、いろいろ検索して出てくる

Base64 encoder = new Base64(); を Base64 encoder = new Base64(0); に修正する

というのもやらなくても動きました。(逆に0を追記するとエラーになりました。1.4では)これは古い情報なのでしょうか?