Karatachi Project ( 仮 ) たけうち(ちめら) chimera@karatachi.org
流 しの 似 非 プログラマ 兼 NEET アセンブラからアスペクト 指 向 までが 座 右 の 銘 言 語 オタクというよりはソフトウェア 工 学 オタク 一 応 まだたぶん 学 生 システムのバグでforループから 抜 け 出 せません アスペクト 指 向 の 研 究 室 のはず ベンチャーもしてたりするかもしれない 一 緒 に 働 いてくれる 人 募 集 中 ( 主 にWicketとかC#とか) 仕 事 はたまに 欲 しいかも
上 から 下 まで 非 常 に 拡 張 性 の 高 いフレームワーク 高 レベルなところではPanelによるコンポーネント 化 低 レベルでは 各 種 ListenerやBehaviorによる 振 る 舞 いの 追 加 もっと 低 レベルなところにも 探 せばいろいろ とりあえず 拡 張 したいと 思 ったところにはだいたい 拡 張 ポイントがある HTML 要 素 の 素 直 かつエレガントなオブジェクト 表 現 ほどよい 粒 度 でのコンポーネント 化 タグの 階 層 構 造 をオブジェクトのコンポジションで 表 している のが 素 敵 ポイント
Component Resolver HTMLタグからのコンポーネントインスタンスの 自 動 生 成 について Teedaっぽいフィールドとプロパティの 関 連 づけの 設 計 と 実 装 Wicket with DI Container SeasarとWicketのつなぎこみをしたときに 見 つけたおもしろい 拡 張 ポイントの 紹 介 むしろ 作 ったS2Wicketもどきの 宣 伝 London Wicket Users Group から Tips & Etc Component Visitorによるコンポーネントの 振 る 舞 いの 一 括 変 更 Borderの 使 い 道 の 模 索
コンポーネントの 自 動 解 決 とその 応 用
Wicketでページを 作 るとき 基 本 となるメソッド HTMLのタグとコンポーネントを 関 連 づける なんか 追 加 するコンポーネントがたくさんあるとだるい 保 守 しにくい <h2> 名 前 入 力 フォーム</h2> <form wicket:id="form"> <p><input wicket:id= name type= text /><p> <p><input type= submit /></p> </form> private class NameForm extends Form { private String name; public InputForm(String id) { super(id); add(new TextField( name, new PropertyModel(this, name )));
public interface IComponentResolver extends IClusterable { public boolean resolve( MarkupContainer container, MarkupStream markupstream, ComponentTag tag); コンポーネント 自 動 解 決 のためのインターフェース HTMLのパース 中 にMarkupContainerに 登 録 されていないwicket:id が 出 現 したとき 呼 び 出 される MarkupContainerに 実 装 するだけで 勝 手 に 呼 び 出 される 登 録 とか 何 もない implementsするだけ ビックリ
public interface IComponentResolver extends IClusterable { public boolean resolve( コンポーネントを 解 決 できなかったコンテナ MarkupContainer container, MarkupStream markupstream, パース& 変 換 中 のストリーム ComponentTag tag); 解 決 できなかったタグの 情 報 タグの 情 報 が 渡 されるのでcontainerに 対 してコンポーネントを 追 加 するだけ public class HomePage extends WebPage implements IComponentResolver { public boolean resolve(markupcontainer container, MarkupStream markupstream, ComponentTag tag) { if (tag.isautocomponenttag()) return false; タグのIDを 取 得 してラベルを 生 成 Label label = new Label(tag.getId(), "Component Not Found + "[id:" + tag.getid() + "]"); return container.autoadd(label, markupstream); ラベルをコンテナに 追 加
<?xml version="1.0" encoding="utf 8"?> <html xmlns:wicket> <head> <title>wicket demo</title> </head> <body> <div wicket:id="test1" /> <div wicket:id="test2" /> <div wicket:id="test3" /> </body> </html> public class HomePage extends WebPage implements IComponentResolver { public boolean resolve(markupcontainer container, MarkupStream markupstream, ComponentTag tag) { if (tag.isautocomponenttag()) return false; Label label = new Label(tag.getId(), "Component Not Found + "[id:" + tag.getid() + "]"); return container.autoadd(label, markupstream);
ComponentTagは 勝 手 に 追 加 したタグの 属 性 も 取 得 で きる つまりはresolverの 制 御 コマンドをタグに 埋 め 込 める.propertiesファイルを 使 うとあんなことやそんなことまで タグ 内 のテキストを 取 得 するのは 少 し 面 倒 MarkupStreamの 動 作 について 知 る 必 要 がある
コンポーネントと 指 定 したオブジェクトのプロパティを その 名 前 で 結 びつけるModel <h2> 名 前 入 力 フォーム</h2> <form wicket:id="form"> <p><input wicket:id= name type= text /><p> <p><input type= submit /></p> </form> 名 前 で 関 連 づける private class NameForm extends Form { private String name; public InputForm(String id) { super(id); setmodel(new CompoundPropertyModel<NameForm>(this));
以 上 を 踏 まえるときわめて 怪 しいことが 可 能 Formクラスのインスタンス 自 身 をCompoundPropertyModelに 入 れて コンポーネントが 自 身 のIDでFormのフィールドを 参 照 で きるようにFormクラスを 継 承 <input>タグや<select>タグのタイプによって 自 動 生 成 するコン ポーネントを 変 えてしまうようなResolverを 実 装 必 須 項 目 を 属 性 としてタグに 追 加 ついでにValidation 情 報 も 追 加 できるようにしちゃったり Reslover 特 盛 り 化 ListViewの 子 要 素 のコンポーネント 追 加 処 理 も 自 動 化 しちゃった りなんかして
<h2> 登 録 フォーム</h2> <form wicket:id="form"> <dl> <dt>お 名 前 </dt><dd><input wicket:id="name" type="text" size="30" wicket:required="true" /></dd> <dt> 参 加 形 態 </dt><dd><select wicket:id="entry" wicket:type="enum:org.karatachi.demo.entrytype" /></dd> <dt> 懇 親 会 </dt><dd><select wicket:id="party" wicket:type="enum:org.karatachi.demo.partytype" /></dd> <dt> 一 言 </dt><dd><input wicket:id="message" type="text" size="80" /></dd> <dd><input type="submit" value=" 登 録 " /></dd> </dl> </form> private class InputForm extends SelfResolveForm implements Cloneable { String name; EntryType entry = EntryType. 一 般 参 加 ; PartyType party = PartyType. 参 加 しない; String message; public InputForm(String id) { super(id); @Override protected void onsubmit() { list.add((inputform) this.clone());
ちなみに 正 規 表 現 での Validationなんかも タグに 記 述 可 能 です 可 能 です
WicketにおけるDIコンテナのサポートとその 利 用
Wicketに 登 録 するオブジェクトはすべてSerializableでな くてはいけない WicketはPageクラスのシリアライズ デシリアライズを 繰 り 返 してセッションを 保 つ DIで 利 用 するオブジェクトはSerializableにすることが 難 しいこと が 多 い Wicketでもコンポーネント 管 理 をおこなっている DI Containerの 管 理 とバッティング Hot Deployを 利 用 しようとするとClassLoaderが2 系 統 作 られDI ContainerのHot Deployが 利 用 できない
WicketとDI Containerの 間 にProxyをはさむ 他 方 のオブジェクトにアクセスする 際 には 必 ずコンポーネン トマネージャーを 一 度 通 す private Foo foo; イメージ @Override public void onpageattached() { foo = SingletonS2Container.getComponent(Foo.class); ページが 表 示 されるときマネージャから 取 得 @Override protected void ondetach() { 表 示 し 終 わったら 一 度 nullにもどす foo = null;
wicket ioc クラスのフィールドをProxyとするためのライブラリ wicket springやwicket guiceなどが 利 用 IComponentInstantiationListener WebApplication 初 期 化 時 に 登 録 すると 全 Component 継 承 クラス でコンストラクタの 一 番 はじめに 呼 び 出 される この 時 点 でDIを 利 用 できるようにすると 継 承 クラスでのコンス トラクタでDIされたコンポーネントを 利 用 できる ReloadableWicketFilter WicketでHot Deployを 実 現 しているFilter DI Container 側 でこいつのClassLoaderを 利 用 するようにしてやれ ばDIContainer 側 もHot Deployされる
IInitializer & IDestroyer WebApplicationの 初 期 化 時 破 棄 時 に 呼 ばれるインターフェース 拡 張 ライブラリを 作 ったときにjarファイル 内 のwicket.properties にinitializerという 名 前 で 実 装 クラスのパスを 書 いておくと 自 動 的 に 起 動 される
Hot Deployの 改 良 Hot Deploy 時 にSeasar 側 で 全 コンポーネントがリロードされてし まうため PermGenスペースが 開 発 時 にすぐ 無 くなる 現 在 あれこれ 呼 び 出 し 順 序 などの 組 み 合 わせを 入 れ 替 えつつ 調 整 中 公 開 にむけて ドキュメントの 準 備 先 のComponentResolverを 使 用 した 作 りためたコンポーネント 群 をどうするか