Inside of Teeda
Download
Report
Transcript Inside of Teeda
Inside of Teeda
おおたに
Teeda?
JSF実装部分
拡張部分
1.1ベース。TCKは(まだ)通してない。
ViewHandlerをエントリポイントとして介入。
PRGパターン、HTMLテンプレート
Ajax
実はTeedaに依存してない。
Core
思想
最初のアイデアはJSFのDI機能
貧弱すぎ→S2使えればいいんじゃないの?
負の面で言えば、他JSF実装がいまいちだっ
た(当時)
実はOSSになる予定も無かった。
Core(2)
一通り実装
UIComponent、Lifecycle&Phase、Renderer、
StateManager、Validator/Converter、Tag、
ValueBinding、Handlerなどなど
DIコンテナとの連携を最初から意識
普通にVariableResolverでS2を呼ぶ
Core(3)
Lifecycleは以下のPhaseから成る
RestoreView:Viewの復元
ApplyRequestValue:requestからdecode
ProcessValidation:Convert/Validate
UpdateModelValue:Modelの更新
InvokeApplication:Model実行
RenderResponse:描画
Core(4)
UIComponent
画面上に配置される各項目を抽象化したもの
このツリーが構築される
Renderer
実際に描画する。
JSFで最も毒素がつまったところ。
Core(5)
ValueBinding
内部的にはJSP2.0のEL式
#{aaa.bbb} -> ${aaa.bbb}
#{クラス.プロパティ}
#{クラス.メソッド名}(メソッドバインディング)
ぶっちゃけCommonsELじゃん。
Extensionで多用
Core(6)
そのほか
StateManager
他JSF実装ではしこたまSessionに格納
Teedaでは、ComponentTreeは1つのみ
ほとんどのコンポーネントで動的に変更が入るのは
valueとsubmittedValueくらい。だからいいじゃん。
Test
JSFとしてのテスト環境は群を抜いて揃ってる
Test重要
Extensionのコンセプト
S2JSFより軽いHTMLテンプレート
規約重視で設定少ない
POJO
Page駆動
JavaEE勉強会のyuki_neko_nyanさんの
「私がほしいPresentationFramework」に
は結構影響を受けてる。
Extensionばっさり
基本的なベースは、S2JSFの発展系
Id書いて、HTMLとPageをマッピング
ドン引きではそんなことは説明しません
サンプル見て。ソース嫁。おしまい。
その代わりにHowを書き殴りご紹介
Extensionばっさり(2)
HtmlViewHandlerがエントリポイント
restoreView
createView
renderView
HtmlViewHandler#restoreView
restoreView(TagProcessorCache)
Teedaで扱う抽象的なリソースの作成・復元
HtmlDesc
PageDesc
XercesにXHTMLとして読ませ、HtmlNodeのツリー構築
NamingConventionにviewIdをキーにfind
/aaa/bbb.html -> aaa_bbbPage
ActionDesc
どれも更新時間をstoreして、毎回チェック
HotDeployのため
HTMLのparseと分類
TeedaではXHTMLとしてparse
Neko使わないで、Xercesのみで。
HtmlNodeに分類
DocumentNode
ElementNode
DOCTYPEをあらわす要素
基本idがついている要素(カスタマイズ可能)
JSFのUIComponentとして処理される
TextNode
Textとして出力される要素
HTMLのparseと分類(2)
XercesのXNIレベルで文字実体参照のま
ま、ブラウザに任せている。
DocumentScannerでnormalizeさせない
http://d.hatena.ne.jp/shot6/20060730
コンポーネントとのマッチング準備編
構築されたDesc系はこのようになる。
HtmlDescはNodeツリーを保持。
PageDescはClassから、各要素を抽出・集約
各DescにあるFileは、更新チェックのため。
HtmlDesc
HtmlNodeツリー
Htmlファイル
PageDesc
Pageのclass
Pageファイル
pageName
規約によるコンポーネントとのマッチング
各Descを元に規約とマッチングしたものを
JSFのコンポーネントとバインディングする。
AbstractElementProcessorFactory
各JSFコンポーネント毎に継承して作成
Org.seasar.teeda.extension.html.factory
isMatch 規約とのマッチング
customizeProperties
各コンポーネント用にプロパティをValueBinding式で独
自にカスタマイズ。
こんな感じ
protected void assembleTagProcessor(ElementProcessor parentProcessor,
ElementNode elementNode, PageDesc pageDesc, ActionDesc actionDesc) {
for (int i = 0; i < factories.length; ++i) {
ElementProcessorFactory factory = factories[i];
if (factory.isMatch(elementNode, pageDesc, actionDesc)) {
ElementProcessor elementProcessor = factory.createProcessor(
elementNode, pageDesc, actionDesc);
parentProcessor.addElement(elementProcessor);
if (!factory.isLeaf()) {
assembleElementNodeChildren(elementProcessor, elementNode,
pageDesc, actionDesc);
}
elementProcessor.endElement();
return;
}
各JSFコンポーネント毎の
}
FactoryがDIされる。
InputTextFactory#isMatch
public class InputTextFactory extends AbstractElementProcessorFactory {
public boolean isMatch(ElementNode elementNode, PageDesc pageDesc,
ActionDesc actionDesc) {
if (!JsfConstants.INPUT_ELEM.equalsIgnoreCase(elementNode.getTagName())) {
return false;
}
if (!JsfConstants.TEXT_VALUE.equalsIgnoreCase(elementNode
.getProperty(JsfConstants.TYPE_ATTR))) {
return false;
}
if (pageDesc == null) {
return false;
}
return pageDesc.hasProperty(elementNode.getId());
}
Tagがinputで、typeはText、PageにプロパティがあればOK。
InputTextFactory#customizeProp
erties
protected void customizeProperties(Map properties, ElementNode elementNode,
PageDesc pageDesc, ActionDesc actionDesc) {
super
.customizeProperties(properties, elementNode, pageDesc,
actionDesc);
if (pageDesc != null) {
properties.put(JsfConstants.VALUE_ATTR, getBindingExpression(
pageDesc.getPageName(), elementNode.getId()));
}
}
#{addPage.arg1}のようにEL式を生成して、
value属性に突っ込まれる。他もほぼすべてこれと同じ。
ここで初めてJSFのコンポーネントとマッピングされる。
HtmlViewHandler#createView
createView
JSPをエミュレートして、動かす
基本的にはS2JSFと同じやり方
ぶっちゃけコンポーネントツリーさえ出来れば良い
ので、その該当部分であるfindComponentだけ呼
んで、構成。
こんな感じ
protected void composeComponentTree(FacesContext context,
PageContext pageContext, UIComponentTag tag,
UIComponentTag parentTag) throws JspException {
}
if (parentTag != null) {
tag.setParent(parentTag);
}
tag.setPageContext(pageContext);
Map ignoredProps = setupProperties(tag);
tag.setupFacesContext();
UIComponent component = tag.findComponent(context);
component.getAttributes().putAll(ignoredProps);
tag.pushUIComponentTag();
try {
composeComponentTreeChildren(context, pageContext, tag);
} finally {
tag.popUIComponentTag();
}
HtmlViewHandler#renderView
renderView
実際のViewのレンダリング
S2JSFと同じ
PRG
POST-REDIRECT-GETの組み合わせによ
る画面遷移を実現
TSSの記事読んでください。
URLが正しく出るのは、気持ち良い。
PRG、Teedaでの実装
HtmlNavigationHandler.handleNavigatio
nでredirect
ただREDIRECTするだけだと、問題
Pageクラスのスコープはrequest
PRGでは当然requestスコープのインスタンス
を2つ使うため、インスタンス間でデータの
LOSTが無いようにしないといけない。
PRGパターンイメージ(こぴぺ
View(Client)
Teeda(Server)
POST
addInput.html
REDIRECT
ブラウザが反応
GET
AddInputPage
状態を
restore
状態を
save
AddResultPage
addResult.html
PRG実装雑多ネタ編
HTTPのステータスコードが302の場合、ほ
とんどのブラウザはconfirmメッセージを出
さない。
実は厳密には仕様ではそうじゃない。
PRGを考えた人は確信犯的にこれを狙ってる。
だからconfirmメッセージが出ない。
SessionPagePersistence
Pageのプロパティのsave/restore
基本同一のプロパティ名があればコピー
画面から入力されてきそうな型しかサポートし
てない。
余分なプロパティを渡さないため
LRU形式でviewIdに対して10個のみ管理
TakeOverアノテーションで細かく管理可能
TakeOver
public class AddResultPage {
private Integer arg1;
private Integer arg2;
private Integer result;
public static final String jumpAddInput_TAKE_OVER = "type=never";
後、省略。
設定いらず
ほとんどは規約のおかげ
Navigationの部分はそれなりにやってる
現在のViewIdとValueBinding結果
(outcome)から行き先を類推
viewId=/view/aaa/bbb.html、outcome=ccc
とすると、/view/aaa/ccc.htmlと類推。
viewId=/view/aaa/bbb.html、outcome=ddd_ccc
とすると、/view/ddd/ccc.htmlと類推。
ま、そんなもんでげす。
Teeda再考
私がほしいPresentationFrameworkを
ベースに再考してみる。
ここからが実は一番やりたかったこと
Architecture
普通にMVC
ひたすらWrap(request/responseAPI、JSF
のXxxとか)
当然使うことも当然出来る。
しかしJSF自体を隠蔽しきれてはいない。
Unobtrusiveだとは少しはいえる。
ConfigurationとOCP
新しいAction追加したときに何故かXMLを
いじったりしてない?
してない。そもそもConfigurationをほとんど
XMLでは書かない。
規約ベースはやはり楽。
Rule and Conventions
そのルール(規約)は明解か?
余計なことは言わず、必要なことだけちゃんと
言ってる?
直感的?
多すぎてない?
これらが正直ちょこっと改善の余地あり。規約が増え
ていったときの対策は必要。
でも規約は決めてしまうと変えずらい。
今後の方向性に影響。
Simplicity/Complexity
do one thing very well?
とは言えず、多方面に手を出しすぎてる
JSF実装した時点でわかれよw>自分
正直自分のポリシーからは、ずれが出ている。
JSFとの協調
ベースのJSFの制約が徐々に増加。
コードベースの拡大につながる。
個人的には割と不安。良い傾向じゃない。
UserInterfaceとしてのFW
動かすまでの設定
Doltengのサポートつきで及第点
いまだHotDeployをゼロからは多分難しい
開発/運用モードのDebugスクリーン
Clickにあるブルースクリーンのような機能は
無い。ユーザーに易しいとはいえない。
ExceptionにJIRAとMLのアドレス埋め込むくら
いからスタートしてもかも。
UserInterfaceとしてのFW(2)
VisualConfiguration(設定の可視化、
Deploy/Undeployも操作可能、履歴・状況
把握機能など)
HotDeploy/CoolDeployなどはようやく可視化
でも他にもやれる事はたくさんある。
Testability
今でもそれなりに高いが、それはUTの話。
IntegrationTestツールの提供は急務
Thanks
ありがとうございましたm(_ _)m
もう眠いです、限界ですZzzzz