ふたつの川うるおう日記
2008-01-04 (Fri)
_ [Seasar][Admin][Linux] Mailman難しい
Mailman.Handlers.ToDigestがエラー吐かずにCPU食いまくってロック握ったまま落ちるものの、次のキュー処理し続けてる(ロックは解除されてないのでそのまま無限ループ)のは原因探すの難しいです。
対処方法は、$MAILMAN_HOME/lists/ML名/digest.mbox をリネームしました。
この問題が実は配送遅延してた原因の1つでもあるような気がするので、そっちも解決したならめでたしめでたし。
_ [Seasar][Java] Cubby + S2ContainerのHot deploy, publicフィールド, Beans, S2JDBC + Mayaaがちょうど良い
ってのを長々書いてたものの、Mailmanの対応してる時に書いてたやつ誤って消してしまった。。短く書くと、今までAbstractActionとかCommonAction、Dto、Dxo、Service、Logicとかいろいろ冗長に書いてたけど、僕みたいに一人で作るならここまでがっちり組まなくても良かったんだなーっと思ったという内容。もちろん複数人だったり作るアプリによってはそっちの方が適してる場合も有り。1個づつ良いと思ったことも書いてたけどもう1回書くの面倒なので以下省略。
あと12/30日にCubbyに入門して、上記の組み合わせ - S2JDBC + S2Directory使った小さなアプリが1/2に完成して昨日の夜から配備したよってのもあった。
2008-01-20 (Sun)
_ [Java][Seasar] Cubby 1.0.0-RC1 リリース
Cubby 1.0.0-RC1がリリースされました。詳細はid:agtさんのCubby 1.0.0-RC1 リリース案内をどうぞ。今回のバージョンから@Urlアノテーションが@Pathと@Acceptに変更・分割されたので、既に使っていた方は書き換える必要があります。@AcceptはPOSTやGETなどのリクエストメソッドを限定する新しい仕様なので、今までと同じPOSTもGETも区別しない挙動で良ければ、@Urlを@Pathに置換でサクっと書き換えるだけでOK。
_ [Java][Seasar] Cubbyの良いところ
先日Cubbyで作った2個目の簡単なアプリを予定通り動かし始めました。今のとこ大きなトラブルもないようです。というわけで、Cubbyの良いところを書きたいと思います。ちなみにほとんど同じことがSAStrutsにも言えます。
- Examplesが実用的で簡単
Cubbyに興味を持ったらとりあえずサンプルwarを動かし、Todoサンプルアプリケーションを見てみてください。一覧表示・詳細・追加・編集・確認・保存に加えて、ログインとログイン状態確認(AuthActionInterceptor)もついています。そして、それぞれの機能に対応するTodoListAction、TodoAction、LoginActionを見ると、とてもコードが少なく、これならすぐに似たようなアプリが作れる気がします(実際すぐに作れました)。
さらにコードを良くみると、フォーム=アクション自身になっています。これは僕の中でかなり革新的でした。今までフォーム用にPOJO(Entityを継承したりして)を用意してたけど、結局僕のように小さなアプリしか作らない場合、POJOを使いまわすなんてことは無く、それだったらアクション自身にあった方が見通しが全然良いんです。なお、別に分けたい場合は@Formで別途指定できるので、フォーム=アクション自身に絶対する必要があるというわけでもありません。
他にもCubbyのExampleは小さなテクニックがいろいろ散りばめられています。例えば、エラー時の画面装飾。effects.jsでちょっと目に付いて親切な装飾がされています。もちろんこれはCubbyでしかできないことではないですがこういったちょっと「良いな」っと思えるサンプルがいろいろあります。そんなわけでますますCubbyを使ってみたいと思ってしまうわけです。
また、今のExampleの例では、S2DxoとS2Daoを使っていますがここをBeansとS2JDBCにしたって問題ありません。僕はそうしています。
- URIが綺麗
やはりURIは、名は体を表す如く美しくあるべきだと思います。以前、無設定S2Struts用にSplitUpperActionPathNamingRuleというのを取り入れていただきましたが、それでも自由自在というところまではいきませんでした。Cubbyでは@Pathにより、URIの一部分をリクエストパラメータにするなど思い通りにURIを表現できます。この仕組みは、RequestRoutingFilterというフィルタにより、実体のアクションクラスへフォワードすることで実現されています。この仕組みも最初見たときそんな手があったかーっと驚きました。
また、通常認証確認処理はURI単位で設定したいので今まではオリジナルのフィルタで書いていました。StrutsなどでInterceptorを使ってやろうとすると、アクションに引っ掛けることになるので、.jspなどのページに直接アクセスされると認証処理が掛けられないので困ってしまいます。でも、Cubbyを使ったアプリでユーザがアクセスするのはすべて綺麗なURIにすることができ、実体のページにアクセスさせないようにしやすいです。なのでExampleのAuthActionInterceptorのようにInterceptorでも抜けのない認証確認が出来ます。ちなみにこのInterceptorはcustomizer.diconでLoginAction以外のアクションに適用するように設定されています。サンプルのAuthActionInterceptorをちょっと拡張すれば、URIごとにアクセス権限を分けるといったことも簡単に実現できます。
public Object invoke(MethodInvocation invocation) throws Throwable {
// 実行しようとしているアクションを取得
final Action action = (Action)invocation.getThis();
// リクエストされたURLを取得
final String url =
(String)request.getAttribute("javax.servlet.forward.servlet_path");
// 非ログインページ
if (url.startsWith("/index")) {
return invocation.proceed();
}
...
// ログインページ
// ログイン状態の確認
final PosixAccount user = (PosixAccount)sessionScope.get("user");
if (user == null) {
action.getFlash().put("notice", "ログインしていません。");
return new Redirect("/login/");
}
...
// 各ページへのアクセス権限の確認
Object group;
// admin
group = sessionScope.get("group_admin");
if (url.startsWith("/admin/") && group == null) {
return new Redirect("/");
}
...
return invocation.proceed();
}
- @Pathによる制約
「URIが綺麗」に関係しますが、@Pathで指定する値には正規表現で制約を付けることができます。簡単な例だと次のとおりです。
public class TodoAction extends Action {
public Integer id;
@Path("{id,[0-9]+}")
public ActionResult show() {
Todo todo = todoDao.selectById(this.id);
todoDxo.convert(todo, this);
return new Forward("show.jsp");
}
}
これだと、/todo/1 にアクセスすれば、idに1が自動的に入った状態でshow()が実行されます。/todo/aa の時はshow()は実行されません。この例はアクションメソッドに@Pathを付けていますが、クラス自身に@Pathを付けることもできます。
僕が使った複雑な例としては、こんな感じです。
@Path("admin/{thesisTypeName,abstract|full}/{userId}")
public class AdminThesisAction extends ThesisAction {
...
@Validation(rules = "submitValidation", errorPage = "/admin/index.html")
public ActionResult submit() {
super.submit();
return new Forward("/admin/submit.html");
}
...
public ActionResult download() {
File file = new File(saveDir, thesis.getFileName());
if (!file.exists()) {
flash.put("notice", "ファイルが見つかりません: " + file.getName());
return new Redirect("/admin/");
}
return super.download(file);
}
}
public class ThesisAction extends DownloadAction {
public String thesisTypeName;
public String userId;
...
public ActionResult submit() {
if (thesis != null) {
Beans.copy(thesis, this).excludesNull().execute();
}
return new Forward("submit.html");
}
...
}
public class DownloadAction extends Action {
public HttpServletResponse response;
protected ActionResult download(File file) {
...
}
}
この例だと、/admin/abstract/user001/submitや/admin/abstract/user099/downloadなどがAdminThesisActionですべて処理されます。extends ThesisActionとしているのは同じようなことをユーザごとや特定の権限を持った人も同じ機能を使いたかったからです。 実際に@Path("student/{thesisTypeName,abstract|full}")を持つStudentThesisActionと@Path("faculty/{thesisTypeName,abstract|full}/{userId}")を持つFacultyThesisActionを作りました。権限ごとに項目が多少違うので、validationはそれぞれの権限に応じたものをそれぞれの実装クラスで定義しました。
- Validationが柔軟
CubbyではValidationはValidationRuleをValidationRulesでひとまとめにして定義し、それぞれのアクションメソッドにそれぞれ適用できます。つまり、アクションメソッドごとに違うValidationを適用できます。アクションのコードが少ないのはここでも役に立ちます。ExampleのLoginActionを見れば判りますが、アクション内にオリジナルのValidationRuleがあります。ここでも僕のように小さなアプリで使いまわすことがないなら同じアクション内の方が見通しが良いです。しかも同じアクション内にあることでアクションにあるパラメータもそのまま使えます。
@Binding(bindingType = BindingType.NONE)
public ValidationRules confirmValidation = new DefaultValidationRules() {
@Override
public void initialize() {
add("token", new TokenValidator());
add("enTitle", new RequiredValidator());
add("enTitle", new RegexpValidator("\\p{ASCII}+"));
add("jaTitle", new RequiredValidator());
add("pageSize", new RequiredValidator());
add("file", new RequiredValidator());
add("file", new FileRegexpValidator(".+\\.pdf"));
}
};
Cubbyが提供するカスタムタグは親切な設計になっています。特にお気に入りなのが、tokenです。ページのform内に <t:token /> と書いて、ValidatgionRulesに add("token", new TokenValidator()); するだけで、2重サブミット・CSRF対策が出来てしまいます。また、カスタムファンクションのoddもテーブルなどで色分けが簡単に出来るようになっていて親切です。
- プレゼンテーションがJSPである = Mayaaが使える
個人的にフレームワークを選ぶ基準の一つにMayaaが使えるかどうかというのがあります。Mayaaは「プログラマとデザイナの作業分担を強く意識したWEBフロントサービスエンジン」という説明がありますが、一人で作る場合でも有効です。主な理由は2つです。1つ目はそのページの機能が一目瞭然になること。2つ目はコンポーネントによる機能分割が可能なことです。
1つ目は、僕の記憶力が良くないことに関係します。たいてい1日経たずしてそのページが何の機能を持ってたか綺麗に忘れます。そんな時、まず.mayaaを見ます。.mayaaにはそのページで実現される「機能」しか書かれていません。それもたいていたいした量はありません。そんなわけで、一目瞭然にそのページの機能が判ります。そして機能を把握したら、頭をデザイナモードにして.htmlを編集するか、プログラマモードにしてアクションを編集します。記憶力が良い方でもおそらく1年も経てばすっかり忘れてしまうと思います。そんな時、.mayaaはきっと役に立つはずです。
2つ目は、1つ目にも関係しますが、まとまった機能・使いまわす機能はコンポーネントにして、<m:insert>を使えば、複雑なページでも.mayaaが簡潔になります。簡潔になれば、1つ目のように機能を確認する時にすぐに把握できます。先程の@Pathのとこで出てきた複雑な例は、ThesisActionを継承したクラスが3つありました。フォームの項目に1つか2つの違いはありますが基本的に同じです。そんなわけでそれらに対応したフォーム部分は共通のコンポーネントに切り出してしまいます。
他にも、m:extendsでページデザインを楽に出来たり、やろうと思えば.mayaa単体でアクション相当のことが出来てしまうなどMayaaは超強力です。そんなわけで、フレームワークを選択する時、僕はMayaaが使えるかどうかは重要な判断基準になります。
- 何はともかくS2ContainerのHOT deploy, publicフィールド, Beans, S2JDBCなどなど
CubbyとMayaaの良いところを書きましたが、忘れちゃいけないのがS2Containerです。アクションのコードを小さく書けるのは、Cubbyだけでなく、S2Containerの多くの機能があるおかげです。S2ContainerというとDI・AOPと想像される方もいるかもしれませんが、S2Containerのすごいとこは、DI・AOPと同じかそれ以上にその周辺の様々な強力な機能群があることだと思います。Cubbyの内部でもリクエストパラメータを処理するのにS2Dxoが使われていたり、CubbyやSAStruts利用者がアクションメソッドを小さく書くのに、publicフィールド, Beans, S2JDBCは必須機能です。これらはきちんと型を理解して処理してくれるのも大きな魅力です。また、サクサク開発するのにHOT deployは欠かせません。
というわけで、長々書きましたが、今現在僕には、Cubby + S2ContainerのHot deploy, publicフィールド, Beans, S2JDBC + Mayaaがちょうど良いのです。
他にも書いてない良いとこもあると思いますがとりあえずこんな感じです。Cubbyの代わりにほぼ同様のことのできるSAStrutsを選択するのも良いと思います。CubbyとSAStruts、まだ触ってない方は是非触ってみてください。
2008-01-22 (Tue)
_ [雑記] 物欲
- 東プレ/Topre Realforce 108UBK (2月上旬出荷開始予定 -> 1/24に入るっぽい)
- フルキーボード、黒、19,800円、先日買ったMajestouch Wireless FKBT108M/JBは家用で利用中
- E-MOBILE D02NE (2月1日予約開始、2月9日発売)
- 7.2Mbps対応PCカード型、現在はまだVista 64-bit非対応、年とく割付きで本体9,980円、ライトデータプラン月額2,480円
- Buffaro RUF2-J8GS-SV
- 容量8GB、本体小さい、Read/Write最速じゃないけど速い方、12,500円
2008-01-24 (Thu)
_ [雑記] Buffaro RUF2-J8GS-SV 8,800円 - ポイント1,584円
ここ数日の間に一体何が起こったのかワカラナイけど、新宿西口のビックカメラでBuffaro RUF2-J8GS-SV買いにいったら8,800円 - ポイント1,584円(実質7,216円)で売ってた。こないだ調べた時は最安12,500円だったのに!7,216円で8GBとか安すぎー。
ちなみに商品札のとこには4GBまでしか置かれてなかったけど、レジでこれの8GBあるか聞いてみたら棚から出てきました。
2008-01-28 (Mon)
_ [Linux][Admin] RHEL 5とCentOS 5のライセンスに関連しているために違う部分
意外とCentOS 5と違う点がある。土日潰して検証して良かった。
- CentOS 5にあるyum-cronがない
- 代替1: 標準の yum-updatesd を設定する
- 5.0で登場した最初に登場した yum-updatesd がバグってた(アップデートされない)のでCentOS 5.xではyum-cron使ってました
- 設定: /etc/yum/yum-updatesd.conf
- 代替2: RHELらしくRHNでスケジュール組んで、rhnsdに任せる
- 設定: /etc/sysconfig/rhn/rhnsd
- 代替1: 標準の yum-updatesd を設定する
あと、RHEL4までのup2dateが無くなっているので、RHELでも標準となったyumを使いましょう。




_ やn [あちょーーーっ・・・!! オメデト]