OGNLコレクションの射影

Struts2のOGNLでコレクションの射影を容易に作成できる

コレクション.{ 操作 }

で新しいコレクションが返される。{ }内では #thisで現在要素を参照できる。

例えば文字列のリストがあったとして、各要素の後に " ({文字列長})"のような文字列を付加したリストを作成したい場合は次のように書くことができる。

元の list1 の作成

<s:generator separator="|" val="'aaa|bb|ccc|dd|eee|fff'">
  <s:set name="list1" value="top"/>
</s:generator>

射影操作を行い結果をlist2に保存

<s:set name="list2" value="#list1.{ #this + ' ('+#this.length()+')' }"/>

結果の確認用の出力

<s:iterator value="#list2">
  [<s:property value="top"/>]
</s:iterator>

この結果は次のようになる

 [aaa (3)] [bb (2)] [ccc (3)] [dd (2)] [eee (3)] [fff (3)] 

s:generatorタグの例

Struts2のs:generatorタグを使うと次のようにして配列を生成できる。

<s:generator separator="|" val="'a|b|c|d|e|f'">
  <s:set name="lst" value="top"/>
</s:generator>

これは

<s:set name="lst" value="{ 'a', 'b', 'c', 'd', 'e', 'f' }"/>

と同じ結果になる。

この配列は例えばStruts2のs:selectタグの要素に指定できる

<s:select list="lst" name="selecttest1"/>

s:generatorタグのブロックでは生成結果の配列がValueStackの先頭に積まれているので変数に代入せずに次のようにも書くこともできる。

<s:generator separator="|" val="'a|b|c|d|e|f'">
  <s:select list="top" name="selecttest2"/>
</s:generator>

prepareインターセプターについて

Struts2のprepareインターセプターを利用するとメソッド実行前に処理を行わせることができるようになる。
実行するメソッドによって前処理で行う内容を変更したい場合は、staticParamsでパラメータを注入してもらい、その値で振り分けるようなことを考えていた。

Struts2の設定的にはこなん感じのイメージ

<action name="sample" class="SampleAction" method="doFoo">
  <param name="mode" value="foo">
</action>
<action name="sample" class="SampleAction" method="doBar">
  <param name="mode" value="bar">
</action>

そしてActionは

  String mode;
  public void setMode( String mode ) {
    this.mode = mode;
  }
  void prepare() throws Exception {
    if ("foo".equals(mode)) {
      // fooの前処理
    } else {
      // barの前処理
    }
  }

こんな感じとなる。

しかし、prepareインターセプターにはもっとストレートに振り分ける機能があった。
この方法だとパラメータで渡してもらう必要もない。

なんと、呼び出すメソッドの前にprepareを付けたメソッドが自動で呼ばれるのである。

  void prepareDoFoo() throws Exception {
      // fooの前処理
  }
  void prepareDoBar() throws Exception {
      // barの前処理
  }
  void prepare() throws Exception {
      // 何もしない
  }

本家Guideのhttp://struts.apache.org/2.0.11.2/docs/prepare-interceptor.htmlを良く見るとそんな事が確かに書いてある。

ちょっとTIPS:alwaysInvokePrepareをfalseにすれば prepare() は呼ばれなくなる

GWTのコンパイル

GWTで開発されたクライアント側のコードは最終的にJavaScriptに変換する必要があるが、HsotedモードブラウザのCompile/Browseボタンで生成されたコードとコマンドラインコンパイルして生成したコードでは内容が異なるので注意が必要だ。

Hostedモードブラウザで生成したコードは可読性の良いコードとなっており、パッケージ名とかが変数名についていて生成されるJavaScriptのコードサイズが大きくなる。一方でコマンドラインでのコンパイルで生成されるJavaScriptコードは短い変数名となる。

iBatisの結果キャッシュ

iBatisSQL設定ファイルで次のようにして結果キャッシュの指定ができる

  <cacheModel id="test.cache" type="LRU">
    <flushInterval hours="24"/>
    <flushOnExecute statement="test.refresh"/>
    <property name="size" value="200"/>
  </cacheModel>

これはLRUで最大24時間、200件のキャッシュを行う指定となる。またキャッシュを無効にする条件として test.refreshを指定している。

あとはこのキャッシュ設定を適用するselectでcacheModelとして指定する

  <select id="test.getAll" resultClass="test.Entry"
  	cacheModel="test.cache">

ちょっとTIPS:cacheModelはいくつも定義できるのでそれぞれのデータで最適なcache設定にできる

Struts2のセキュリティーアップデート

Struts2の 2.0.11.2 がリリースされています。セキュリティアップデートですので入れ替えておきましょう。

http://jira.opensymphony.com/secure/ViewIssue.jspa?key=XW-641

ダウンロードはこちらから
http://struts.apache.org/download.cgi#struts20112

iBatisのサブクエリに複数のパラメータを渡す

iBatisで1対多のテーブルからの取得などの場合にサブクエリの指定は次のように行う。

    <result property="history"      column="id"         select="getHist"/>

これで、 getHist のSQL中で id の値は #value# で参照できるようになる。サブクエリに渡す値が一つで足りる場合は問題ないが、複合キーなどの場合に駆動表の複数カラムをgetHist側のSQLで参照したい場合があるこの方式では渡せない。

複数渡したい場合は column部分の記述を次の様にする。

 column="{ 参照名 = DBカラム名 , ... }"

駆動表の id, some を使ってサブクエリを発行する場合次のようになる。

    <result property="history"      column="{value=id,second=some}"         select="getHist"/>

これで、 getHist のSQL中で #value# と #second# が利用できる。

column="id"

という書き方は

column="{value=id}"

のショートカットという風に考えるとスッキリする