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