無設定への挑戦…

  • マニュアルの無設定のリファレンス

となっているが、実は以下の間違い


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.概要
でChartの定義をして、で画像をレンダリングする
6.実践
そのうち

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からの新機能らしいが、きっと使うことはない…