Struts本を 1冊買っておくか,と思い,本屋でいろいろ立ち読みした結果,これが一番よさそうだったので購入。チュートリアルなどといった初心者向けの情報はあまり書いてないけど,そういうのは Webでいくらでも入手できるから構わないでしょう。各項目の説明も非常に詳しく,これから何かと役にたってくれそうです。まあ,お値段もそれなりにしますが…。
カテゴリー: Java
Tapestryを勉強してみた
今日は Tapestryを勉強してみた。
http://jakarta.apache.org/tapestry/
まずはググることから始めてみたが日本語リソース少ねー。解説記事は数えるほどで後は個人の日記ページばかり。そんなこと言ったらこのページも日記なのでえらそうなこと言えないけど。
まずは EclipseのプラグインであるSpindleをインストール。これは簡単。
後は数少ない解説記事の中から
634 – Tapestry
http://634.ayumu-baby.com/tapestry/
新Jakartaフレームワーク Tapestryがやってきた(前編)
http://www.duo.co.jp/column/35tapestry_java00.html
この辺のページを参考にしながらデモを一通り動かしてみました。基本的な考え方は
- ロジックとビューを完全分離できます。ビューは普通の HTMLファイルで作成することができます。独自タグとかは入らないピュアな HTMLファイルなのでデザイナーも安心して作業できます。もっとも画面デザインをデザイナーに委託するほどおしゃれなサイトを作った経験がないので,この辺,完全分業できるとどれくらいうれしくなるのかはピンとこなかったりしますが。
- ピュアな HTMLファイルなら,どうやってフォームの情報を取り出すのよ,という話になりますが,そこは HTMLの id属性で指定します。情報を取得したい,表示を動的に変化させたいという領域に id属性を指定しておいて tapestryが理解できるようにしておきます。
- 宣言された id属性に対し,これはテキストフィールド,これはメソッド呼び出し,といった風にそれぞれの性質を定義していくのが *.pageファイル(XML形式)です。これは *.htmlと一対一対応します。
- 後は *.javaに好きなようにロジックを実装していきます。画面遷移は *.java内で指定します。XMLファイルなどの外部ファイルではありません。この辺 Struts, JSFなどと違うところです。
という感じでしょうか。GUIアプリケーションのあるべき設計により近づいていると思うので,筋は悪くなさそうです(←えらそう)。日本語リソースが少ないのが難ですが。
S2Dao
調子にのって S2Daoも試してみました。
http://www.seasar.org/s2dao.html
「Seasarにさわるさー S2DAO
http://muimi.com/j/aop/seasar/s2dao/
も参考にしながらやってみましたが,動きませんねえ…。クエリをなげると NullPointerExceptionが返ってきます。エラー自体は S2Daoで出ているので何が悪いのかもさっぱりわかりません。
とりあえず動かすのは諦めて,思想だけでもまとめると
- データベースのテーブルと Javaクラスとのマッピングも JavaBeansでおこなう。メソッドのネーミングを S2Daoのルールに従ってつけてもらうことで実現します。
- SQLもかけます。外出しのファイルとして管理できるのでうれしい。
となります。やっぱり O/Rマッピングではマッピングの方法を何でやるかがポイントなんですかね。
一般的に考えると,記述すべき内容はソースコード内で完結できればそれに越したことはないはず。設定ファイルが必要なのはパラメータの中には外部から与えたほうが便利な場合,あるいはそうじゃないと使い物にならない場合が存在するためです。
じゃあマッピングルールは本来,コード内で処理すべきなんでしょうか,それとも外部から制御すべきものなんでしょうか。外部から制御する,すなわちリコンパイルの必要がないというのが後者の大きなメリットですが,マッピングの変更,例えば DBスキーマに変更があった場合は,それに関連する処理コードに手を入れないといけない可能性が高いように思いますので,あまりこのメリットは享受できないかもしれません。
となると,あるべき論からいくと,O/Rマッピングはソースコード内でおこなうのがいいんでしょうね。ネーミングルールで縛るのが最適解かどうなのかはわかりませんが。
と,考えてみました。
Hibernate
少しは O/Rマッピングも勉強しとかないと,と思ってまず Hibernateを動かしてみることにしました。
まずは
Hibernateで理解する O/Rマッピング
http://www.atmarkit.co.jp/fjava/rensai3/ormap01/ormap01.html
を参考にしてぽちぽちとやってみました。
記事ではバージョン 2.1.4を使っていますが,現在の最新バージョンは 3.0.5ということでそれでやってみたところ,構成ファイルやパッケージ名やら色々変わっていますね。とりあえず hibernate3.jarだけパスを通しておいて,コンパイルして「そんなのない!」と怒られたクラスが含まれるライブラリを順番にパスに加えていったところ,なんとか動くようになりました。
Hibernateの思想(というほどでもないけど)を自分なりにまとめておくと,
- データベースのテーブルと Javaクラスとのマッピングは XMLファイル(*.hbm.xml)でおこなう。
- Javaクラスについては JavaBeans(要は setter/getter)も作成する必要がある。
- 問い合わせは HQL(SQLに似たクエリ言語)でおこなう。
- SQLは使えない?(不明。よくわからない)
という感じでしょうか。
Struts Best Practices
http://www.jaxmag.com/itr/online_artikel/psecom,id,648,nodeid,147.html
要旨を簡単にまとめてみます。多少意訳や誇張も含んでいますので正確なところは原文をあたって下さい。
共通機能をまとめるために 中間 Actionクラスを用意するとよい。
例えばユーザ認証機能などは,ユーザからのリクエストの度に呼ばれるわけですが,いちいち execute()メソッドに書くのはコードが重複してしまってよくない!ということで,中間 Actionクラスにその処理を追加し,他の Actionクラスはこの中間 Actionクラスを継承するという方法。したがってorg.apache.struts.action.Actionを継承するのは中間 Actionクラスになります。
関係するアクションを 1つのクラスにグルーピングすべく DispatchActionを使おう
オンラインショッピングアプリケーションを考えたとき,カートの商品の追加,削除,更新といった機能が必要になります。単純に考えるとこれらの機能 1つ 1つに対して Actionクラスを割り当てて excute()メソッドで実装することになりますが,それってなんかいやです。関係するアクションは 1 Actionクラスにまとめて管理したいです,というときに使うクラス。
フォームの 2重送信を防ぐ
注文確定ボタンを間違って 2回クリックしてしまって,2重注文になってしまった,というような悲しい状況を回避するための方法。サーバ側とクライアント側のトークンの比較をおこないます。2度目のクリックではクライアント側のトークンは変化していないけどサーバ側のトークンが変化しているので,そこで処理の振り分けができます。使用する APIは saveToken()と isTokenValid()です。
アプリケーションモジュールを使って平行開発する
大規模アプリケーション開発ではアプリケーションを複数モジュールに分割して,それぞれのモジュールを平行開発できると開発効率の面でハッピーなわけですが,モジュールが分割できても設定ファイルが 1つのままではそこがボトルネックになってしまい何もうれしくありません。ということでモジュールごとに設定ファイルを切り分けて開発することができるような struts-config.xmlの書き方のお話。
類似するフォームは 1つの ActionFormにまとめる
使用される可能性のあるフィールドをすべて持った 1つの ActionFormにまとめます。すべてのフィールドを同時に使うことはないかもしれないけどそれでもいいです。メンテナンスの容易性が最優先。
冗長なフォワードを避けるために global-forwardsを使おう
例えばオンラインショッピングアプリケーションで,セッションタイムアウト時にはログインページに遷移させるべきですが,そのルールをすべての Actionに書くのは冗長です。global-forwardsを使えば 1箇所で済みます。
ビジネスロジックは Actionクラスに実装しない
Actionはそういうことをする場所ではないです。モデル層に委譲したほうがいいです。
Actionクラスではインスタンス変数やクラス変数は使わない
複数スレッドから予期しないタイミングで更新されるのを避けるためです。
ActionFormsはモデルではない
ActionFormは HTMLフォームを表現するためのもので,ビューとコントローラの間で Strutsによってデータをやりとりするために使います。モデル層と混同しちゃだめです。