無設定への挑戦…
- マニュアルの無設定のリファレンス
…
となっているが、実は以下の間違い
…
- Validationのアノテーション
validateをtrueにしたらStackOverFlowが発生…アノテーション以外は特に何も設定していない
/** * @org.seasar.struts.annotation.backport175.StrutsAction( * validate=true) */ public interface ValidationAction { … }
Dtoで(上の設定だけならエラーにはならず)
/** * @org.seasar.struts.validator.annotation.backport175.Required */
エラー
java.lang.StackOverflowError org.apache.catalina.session.StandardSession.getSession(StandardSession.java:531) org.apache.coyote.tomcat5.CoyoteRequest.doGetSession(CoyoteRequest.java:2242) org.apache.coyote.tomcat5.CoyoteRequest.getSession(CoyoteRequest.java:2116) org.apache.coyote.tomcat5.CoyoteRequestFacade.getSession(CoyoteRequestFacade.java:526) javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:215) …(上の繰り返し) org.apache.struts.upload.MultipartRequestWrapper.getSession(MultipartRequestWrapper.java:265) org.apache.struts.action.RequestProcessor.processLocale(RequestProcessor.java:609) org.seasar.struts.processor.S2RequestProcessor.processLocale(S2RequestProcessor.java:55) org.seasar.struts.processor.AcceptorImpl.process(AcceptorImpl.java:40) org.seasar.struts.processor.S2RequestProcessor.process(S2RequestProcessor.java:43) org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) javax.servlet.http.HttpServlet.service(HttpServlet.java:709) javax.servlet.http.HttpServlet.service(HttpServlet.java:802) org.apache.struts.action.RequestProcessor.doForward(RequestProcessor.java:1063) org.seasar.struts.processor.S2RequestProcessor.doForward(S2RequestProcessor.java:219) org.apache.struts.action.RequestProcessor.internalModuleRelativeForward(RequestProcessor.java:1001) org.apache.struts.action.RequestProcessor.processValidate(RequestProcessor.java:966) org.seasar.struts.processor.S2RequestProcessor.processValidate(S2RequestProcessor.java:97) org.seasar.struts.processor.ValidateProcessorImpl.processValidate(ValidateProcessorImpl.java:49) org.seasar.struts.processor.S2RequestProcessor.processS2Validate(S2RequestProcessor.java:90) org.seasar.struts.processor.AcceptorImpl.process(AcceptorImpl.java:66) org.seasar.struts.processor.S2RequestProcessor.process(S2RequestProcessor.java:43) org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194) org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432) javax.servlet.http.HttpServlet.service(HttpServlet.java:709) javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
- ファイルのアップロード
フォームにenctype="multipart/form-data"を設定するとパラメータがDtoにセットされない
さてどうしたものか。
サンプル(RC6)を動かす
とりあえずサンプルをDLして実行…問題なく動いた。ってことでちょびちょび触ってみることにする。
- まずは、Helloから
”Hello World ”って表示された。生成されたHTMLを見たらidとか凄い事になってる。JavaScriptとかでid使うとき大丈夫なんだろうかとちょと心配。まぁ方法はあるだろうということで後にしよう。ってことで、htmlファイルを見たが非常にシンプル。layoutTitleってのは例のレイアウトと関係があるのだろうか?何がどうなっているのかさっぱりわからない…
う〜む、あるタイミングでメニューを選択しても画面が切り替わらなくなる現象に遭遇する。現状の知識ではとても原因を追究することは出来そうもない。ってよく見りゃリンクがどれを選択しても同じになってる。セッションとかと関係あるのかなぁ…ん?!ってSQLException出とるがな!!メニュー適当に選んでたらDBアクセスしにいって失敗してたのね<まぁ原因わかったし良かったとしよう。
layoutを見てみるとなんとなくわかった。Tiles触ったことがあったので抵抗ないし、むしろわかりやすいかも(あの設定XMLファイルを書かないで済むのは非常に嬉しい)。つまり、
<span m:inject="f:param" m:name="layoutTitle" m:value="Hello"/>
のHelloが、
<title m:value="#{layoutTitle}">S2JSF Example</title>
の #{layoutTitle} に入る。hello.html自身にも title があったので最初は、ん?とか思ったけど、モックのときにはこっちを表示するのね。んで、
<span m:inject="s:insert" m:name="body"> Hello <span m:value="#{message}">hoge</span> </span>
が、
<span m:inject="s:insert" m:name="body"/>
に突っ込まれる。って”World”はどこからやって来るの???と思って、おもむろに”World”をテキスト検索したら、あるじゃないですかmenu.htmlに。
<a m:action="hello">Hello <span m:inject="f:param" m:name="message" m:value="World"/> </a>
なるほど、というかなんと言うかそういうことですか。んで、もう一度生成されたHTMLを見ると、
<a href="/s2jsf-example/hello/hello.html?_id28:_link_hidden_=_id28:_id34&message=World" id="_id28:_id34">Hello
てな感じでしっかり”World”を渡しているのね。ふ〜ん、”f:param”だけに…JSFも全然知らんしこのまま進めていいものか疑問はあるが、非常にとっつき易く、かつ非常に魅力的であることがこの時点でもはっきりと感じ取れるわけで、ここで止めるわけにはいきませんな。
ということで勝手に”Hello World”卒業!おっと、レイアウト使ってる場合は、
<html xmlns:m="http://www.seasar.org/maya" m:extends="/WEB-INF/layout/layout.html">
になるのね。
- そしてAddへ
さすがにここまで来るとかなり複雑…ってこともなく、でもActionが出てきた…あら単なる足し算とはいえLogicまでお出ましとは。てかこの辺はく〜す的なあれで特に問題ないな。気になるのはエラーメッセージのところか。一体エラーメッセージは誰が出しとるんじゃい!!ってきっとデフォルトのConverterとかその辺だろうと勝手に納得。
name="addDto"とname="addActin"を消してみたら案の定エラーとなった。S2Strutsのときみたいに勝手にプロパティをバインドして…とはこの場合違ったみたい。う〜ん、浅はかな自分。
なるほどメッセージリソースは、myfaces.jarの中で定義してあって、IntegerConverterクラスでチェックしてたわけね。なるほど、なるほど。でもってUIComponentのIDを{0}にぶち込むからあんなわけわからんエラーメッセージを出してくれるわけだ。
この辺の詳細はJSFの話だろうから、とりあえずこう書くってことでお茶を濁しておこう。
<span m:inject="h:messages" m:globalOnly="false" m:showDetail="true"/>
- そしてForEachへ
おぉHello/Addとインデントがなかったから見難いなぁと思っていたら、早速インデントが。へ〜、formは属性とか何にもなしなんだ(Addで気づけ)。Strutsと比べるとえらい違い。ちょっとした記述ミス/ど忘れでどんだけハマッたか…
でも、forEachResultInitActionって誰が呼んでるんだぁ〜。ってこんな風になってた。なるほど画面の初期化はこうするのか。
<html xmlns:m="http://www.seasar.org/maya" m:action="#{forEachResultInitAction.initialize}" m:extends="/WEB-INF/layout/layout.html">
- そのままForEach2
なるほどぉ。基本的にこれまでやってきたことですぐ理解できる。イベントドリブン(であってたっけか)ってのがようやっとわかってきた気がする。
ん??そのまま流すのはマズイだろ…そういえばupdateで値かわるけど、この辺てどうやってるんだ…ん〜〜どういう加減でリストに値が入って来るんだろう…全くわからん。まぁ裏でうまいことやってくれてるということでここはお茶を濁しておこう。
Cewolfを使ってみる
1.ダウンロード:http://sourceforge.net/project/showfiles.php?group_id=57282
2.解凍しlibの以下のjarをWEB-INF/libにコピーする。SVGに対応しているらしいがやはりbatikを使ってるのね。
jfreechart-*.jar jcommon-*.jar commons-logging.jar cewolf.jar batik-xml.jar batik-util.jar batik-svggen.jar batik-dom.jar batik-awt-util.jar
3.web.xmlの設定
CewolfServlet de.laures.cewolf.CewolfRenderer CewolfServlet /cewolf/*
4.動作確認:http://localhost:8080/myapp/cewolf?state
こんなん出たので動いてるってことにしよう。
Cewolf servlet up and running. Requests served so far: 0
5.概要
6.実践
そのうち
FastCronParserは意外と使えるかも
cronの式(っていうのか?)をパースして時刻とかの比較をしてくれる。でも何に使おう…
GeneralCacheAdministratorを触る
基本的な使い方
- キャッシュに格納: putInCache
- キャッシュからの取り出し: getFromCache
getFromCache で refreshPeriod を指定するとキャッシュの最終更新と比較し、その期間が過ぎていたら NeedsRefreshException を投げてくる。getCacheContent メソッドで一応今格納されているオブジェクトを取得することが可能。cron形式で期間を指定することも可能(refreshPreriod との合わせ技も可)。
しっかし、キャッシュから取り出すときに期間を指定する方法はいまいちしっくりこない。putするときに保持期間を指定するほうが自分としては自然な気がする。んで、取り出すときに期間過ぎてたら例外投げればいいじゃない。ってことでちょっと改造してみよう。
OSCacheを使ってみる
- 概要
JSP Caching
カスタムタグを使ってレンダリングされたJSP(カスタムタグで指定した部分、ページ全体をキャッシュしたい場合は2の方法を使う)をキャッシュする
Request Caching
サーブレットフィルタを使って HTTP のレスポンスをキャッシュする(自動生成された画像やPDF等のバイナリも可)
General-Purpose Cache
OSCache の API を直接使用してオブジェクトをキャッシュする。
- キャッシュ先
メモリとディスクにキャッシュを保持できる模様(両方の組み合わせも可)。ディスクはサーバが落ちたときやメモリから溢れたときに有用。また、キャッシュのクラスタリングもできる模様。
- キャッシュアルゴリズム
・LRU (Least Recently Used)
・FIFO (First In First Out)
・Unlimited
独自のアルゴリズムを追加することも可能。
1.ダウンロード:https://oscache.dev.java.net/servlets/ProjectDocumentList
2.DLしたファイル(oscache-2.1-full.zip)を解凍し、oscache.jar を /WEB-INF/lib にコピー
3.commons-logging.jar が必要なようなので /WEB-INF/lib になければこれもコピーする
(lib/core にjarに置いてある)
4.JDK 1.3.x使ってる場合は、commons-collections.jar を /WEB-INF/lib に入れときなさい、とのこと。
JDK 1.4以降であればそっちの方が(今のところ)早いので必要ないらしい(あっても中でJDKのバージョンを判断してるので特に気にする必要はない)。
5.設定ファイル src/oscache.properties を /WEB-INF/classes に置く
6.src/META-INF/taglib.tld を /WEB-INF/classes に置く(置き場は環境によるかな)
7.ってことでここまででこんな感じになってるでしょ、ってところ
$WEB_APPLICATION/WEB-INF/lib/oscache.jar $WEB_APPLICATION/WEB-INF/classes/oscache.properties $WEB_APPLICATION/WEB-INF/classes/taglib.tld
8.でもって、
oscache /WEB-INF/classes/taglib.tld
として、あとはJSPにTagでキャッシュの設定をするなり、サーブレットフィルタでページごとキャッシュしたりすればいいじゃない、とのこと。
JSPとかフィルタが一押しなのか、ドキュメントにはそこら辺しか書いてない。それ以外のインスタンスのキャッシュとかの方法はAPIドキュメント見ないといけない。こっちの方が主に知りたいんだけどなぁ。
サーブレットフィルタを使ってページを丸ごとキャッシュする。例えば全てのJSPのページをキャッシュしたい場合は web.xml にこんな感じでフィルタを設定する。
CacheFilter com.opensymphony.oscache.web.filter.CacheFilter CacheFilter *.jsp
デフォルトではキャッシュ保持期間は1時間で、application スコープに保持しているようなので、必要に応じて初期化パラメータで変更する(scope に指定できるのは application または session、て当たり前だわな)。
CacheFilter com.opensymphony.oscache.web.filter.CacheFilter time 600 scope session
上の設定ではキャッシュ保持期間は10分で session スコープに保持する。ちなみにステータス 200(HttpServletResponse.SC_OK)だったコンテンツのみキャッシュする模様。
・cache.memory(true or false)
メモリキャッシュを使用するかどうか。デフォルトはtrue。
・cache.capacity
キャッシュに保持できるアイテムの数。デフォルトはunlimited。
・cache.algorithm
キャッシュアルゴリズムを指定する。
・com.opensymphony.oscache.base.algorithm.LRUCache
・com.opensymphony.oscache.base.algorithm.FIFOCache
・com.opensymphony.oscache.base.algorithm.UnlimitedCache
注:LRUCache/FIFOCache は cache.capacity が指定されていないと有効にならないし、cache.capacity が指定されていない場合、UnlimitedCache がデフォルトとなる。
・cache.persistence.class
キャッシュを永続化するために使用するクラス。デフォルトでファイルシステムに永続化する HashDiskPersistenceListener が提供されている(cache.path にキャッシュを保存するディレクトリを指定する必要有)。
・cache.persistence.overflow.only
キャッシュを永続化するタイミング。デフォルトは false となっており、メモリの保持サイズに達した場合のみ永続化する。キャッシュサイズの指定をしている場合は、true にすることを推奨している。
・cache.key
ServletCacheAdministrator が application/session スコープにキャッシュを保持するためのキー。デフォルトは、"__oscache_cache"。コードから直接キーを扱う場合、デフォルトのキーは com.opensymphony.oscache.base.Const.DEFAULT_CACHE_KEY で定義されている模様。
- インスタンスのキャッシュ
保留…GeneralCacheAdministrator の JavaDoc を見るべし。
v2.0からの新機能らしいが、きっと使うことはない…