2008年6月5日木曜日

Spring Web Flowを試してみる(2)

Spring Web Flowを試してみる(2)

eclipse3.3にswf-booking-mvc-2.0.1.RELEASE.warをインポートしてantのbuildファイルを作成しました。
あとはwarの中身の探検ですが、その前にbooking-mvcをdeployしてみました。動かないものをいじってもしょうがないので。
するとTomcat起動時にいきなりエラーが。まあ覚悟はしてましたけどね。DB関係の設定何もしてないし。
2008/06/05 10:45:55 org.apache.catalina.core.StandardContext listenerStart
致命的: クラス org.springframework.web.context.ContextLoaderListener のリスナインスタンスにコンテキスト初期化イベントを送信中の例外です
org.springframework.beans.factory.BeanCreationException: Error creating bean with name '_rememberMeServicesInjectionBeanPostProcessor': Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanCreationException: ・・・

ログに出ていた[/WEB-INF/config/data-access-config.xml]をチェック。HSQLDBを使っているようなので、springサンプルで使ったDBのURLに編集しなおしました。
jdbc:hsqldb:mem:booking

jdbc:hsqldb:hsql://localhost

hsqlを起動して再チャレンジ。
当然のようにだめ。同じエラーがでます。DBが出来ていないことが原因だろうと推測。
hsqldbにテーブル群を作成してみます。(← 6/6追記:作成してはいけません。ダメです)
テーブルは insert.sql を参考にして適当に作りました。(割と嫌気がさしてきています。こんなのサンプルにつけておくべきでしょう)
(後記:動かなかったのは別の原因でした。ひょっとしたらdeployしたら自動で作ってくれるのかもしれません)
(6/6追記:自動で作ってくれます。しかも以下のテーブルを作ってしまうと動きません!)
CREATE TABLE Customer (
username varchar(127),
name varchar(127)
);
create table Hotel (
id INTEGER NOT NULL PRIMARY KEY,
price decimal(15,2),
name varchar(127),
address varchar(127),
city varchar(127),
state varchar(20),
zip varchar(10),
country varchar(20)
);


hsqlの管理画面から上記テーブルを作成。
java -classpath ../war/WEB-INF/lib/hsqldb.jar org.hsqldb.util.DatabaseManager

データのロードを実施。データロードにはantのタスク(spring mvcのチュートリアルからコピペ)を使いました。
    <target name="loadData">
<echo message="LOAD DATA USING: ${db.driver} ${db.url}"/>
<sql driver="${db.driver}"
url="${db.url}"
userid="${db.user}"
password="${db.pw}"
onerror="continue"
src="src/import.sql">
<classpath refid="master-classpath"/>
</sql>
</target>

結果はやはり失敗。
同じエラーが出ます。

googleで"No persistence units parsed from"で検索すると Error using JPAというページが引っかかりました。内容を読んでみると"WEB-INF/classes/META-INF/persistence.xml"がないとダメだ、とのこと。

eclipseにwarをインポートして、antでデプロイしていたのですが、"src/META-INF/persistence.xml"をtomcatにデプロイできていなかったことが判明しました。
上記をWEB-INF/classesにコピーする処理をbuild.xmlに追加。
    <target name="build" description="Compile main source tree java files">
<mkdir dir="${build.dir}"/>
<javac destdir="${build.dir}" source="1.5" target="1.5" debug="true"
deprecation="false" optimize="false" failonerror="true">
<src path="${src.dir}"/>
<classpath refid="master-classpath"/>
</javac>
<copy todir="${build.dir}" preservelastmodified="true">
<fileset dir="${src.dir}">
<include name="**/*.xml"/>
</fileset>
</copy>

</target>

無事にアクセスできました。
よかったよかった。

結論として、warファイルの中身はdata-access-config.xmlの"jdbc:hsqldb:mem:booking"を適切なものに変更し(本当は不要なのかもしれませんが)テーブルを作ればwarのデプロイに成功しました。
(6/6追記:テーブルは作成不要です。自動で作ってくれます)

日暮れて道遠しですが、とりあえずは一段落。

Spring Web Flowを試してみる(1)

Spring MVCは確かに優れたフレームワークなのですが、SimpleFormControllerとAbstractWizardFormControllerだけでは一般的に要求されるページ遷移を実装するのは難しいと思われます。
単に行ったり来たりするだけならば問題はありません。そうではなくブラウザの戻るボタンが押されたときに画面遷移を無効化したいとか、ブラウザリフレッシュ(リロード)を無効化したいという要件にSpring MVCで対応するのは厳しいようです。

SimpleFormControllerはformBackingObjectで画面出力し、画面入力をdoSubmitで受けて処理をし、redirectで返すという単発の処理に適したコントローラです。入力もセッションもその場限りで更新されるイメージです。
画面遷移を制御したい場合には、セッション管理やBeanを作りこみ、かつredirectではなくforwardで画面遷移を構成する必要がありますが、単にゴリゴリ書いて行くだけではSimpleFormControllerを実装したコントローラの肥大化を招くだけです。
AbstractWizardFormControllerは、Wizard形式の画面遷移を簡単に実装できる素晴らしいコントローラですが、同じく多数の画面(例えば50画面)をこれで管理するのはムリがあります。

ということで、Spring Web Flowがどれほどのものか試してみたいと思います。

【途中経過】

思った以上にドキュメントが貧弱で苦労しています。
eclipse 3.3へのプロジェクトのインポートもreadme通りには行きませんでした。

とりあえずspring-webflow-2.0.1.RELEASE\projects\spring-webflow-samples\booking-mvcで
ant jar 
ant publish

するとspring-webflow-2.0.1.RELEASE\projects\integration-repo\org.springframework.webflow.samples\swf-booking-mvc\2.0.1.RELEASE\swf-booking-mvc-2.0.1.RELEASE.war"が出来たようなので、ここから始めたいと思っています。

2008年6月4日水曜日

10年続けてみる

今朝ふと吉本隆明が言った「何事も10年続けるとモノになる」という言葉を思い出しました。
どういう文脈だったかは思い出せません。

いろいろつらいことも気に入らないこともあるだろうけど、まあとにかく10年続けてれば何かしら光明が見えてくる。体がそう成ってくる、という風に私は理解しました。

何事も10年続ければモノになる。

ありふれた言葉の要ですが、なかなか含蓄があります。

 確かにある種の技量は幼いうちに素養を積んでおかないと、歳をとってからは厳しいと思います。
例えば楽器の演奏です。小さい頃に耳が出来ていないと、例えばバイオリンの学習は難しいでしょう。
しかし、上手く行かなくて難しくて大変だからこそ、10年続けることに意義があるのかもしれません。

すこし脱線しますが、「耳が出来る」ということを、私は養老猛司風に「脳に回路が出来る」と解釈しています。耳が出来るということは、脳に音階に対応した回路が出来る。耳からのインプットを受けて指が勝手に動くような仕組みが脳に出来て行く。そう考えるとなんだか楽しくなるので。

私の人生をふり返ってみても、とにかく頑張って仕事をしてきて、いろいろ外部の環境の変化もあったけれど、でも何とか仕事がモノになってきた。幸福か?人のことがうらやましくないか?という問いには簡単には答えられませんし、先の不安もないわけではありません。それにしてもまあこれまで何とかなったもんだな、という感慨があります。

楽器など趣味の世界でもそうですね。確かに小さい頃からみっちり練習してきたプロや音大/芸大出の方にはかなわない。でも趣味も10年続けていれば、それなりに自己満足できるところまでは行けると思います。

10年。長いようで短い期間です。30歳から本気で何かをやり始めたとして、50歳まで20年しかありません。しかし短い期間といえども続けるということはそんな簡単ではない。何かを続ける10年間は長くも短くもなるわけです。

そう考えると今の時間と、今10年後を見定めて何を始めるのか、という問いが非常に重いものであることが分かります。またその問いには自分を何かに投げかけるという生き方が示唆されている。ただ漫然と日々を過ごすのではなく未来へ向かって自分を投げ入れるという生き方です。そして10年という単位で人生を見たときに今の時間が非常に貴重であることに気がつかされます。

これからも大変なことはいろいろあるでしょうが、頑張って生きて行こうと思います。

(6/6追記)
asahi.comに『「ほぼ日刊」実はホントに日刊 「イトイ新聞」10周年』という記事が出ていて、以下の文章がありました。(リンクが許可制なのでリンクなしです)
糸井さんは「10年続けること」を目標にしてきた。文芸評論家の吉本隆明氏に「とにかく毎日、10年続けたらものになる。ぼくが保証する」と言われたからだ。

微妙にシンクロしてうれしいです。こういうことってたまにある。

2008年6月3日火曜日

「障害を許さない」プロジェクトが破綻する理由(4)

■障害の予防にかけるコスト

障害が発生すれば当然コストがかかります。
障害によってはその損失額は膨大になるでしょう。また考えられる障害のケース毎に予想される損失額を加算して行くと、ほとんど無限とも言える額になると思います。
小は個々のコンポーネントの障害から、大きくは(昨今話題の銀行システムで言えば)ATMの障害や勘定系システムの障害、情報系システムの障害、あるいは顧客情報の漏洩、ブランドイメージの失墜などなど・・・

では、障害を予防するためにはどれだけコストをかけるべきか。
障害が発生した場合の推定損失額は無限だから無限にコストをかける?それはあり得ません。時間と金を無限にかけるシステムは決して完成することはないでしょう。

では適性なコストとは?

障害の根本的な原因は常に人だと私は思います。人が何か新しいことを始めればミスをする。そして運が悪ければそのミスの結果、障害が発生する。だから障害を発生させないためには、人に障害につながるようなミスをさせないような仕組みが必要です。

   素晴らしい。これで障害を根絶できます。まさにノーベル賞ものの理論ではないでしょうか。

でも残念でした。そんなに簡単には行きません。

仕組みといってもシステム開発作業は決まりきったルーチンワークではありません。ルーチンワークならそれこそシステムに任せればいい(そのシステムも障害からは逃れられませんが・・・)。むしろ少なからずクリエイティブな作業です。機械的に定義できるようなものではない。従って運用や仕組みによってその成果を一定の品質に保つことはできません。成果物の品質は個人の能力に依存してきます。しかしいくら優秀な人間が作業をしても当然勘違いやミスは発生する(世の中に完璧な人生を送る人がいるでしょうか?)。そして事前に潰せるミスも少なからずある。ではどのようにしてミスを潰すか。例えばミスのチェック体制を作ることによって潰すことができますね。

ここで私は「ミスを起こさない/起こさせないためにどれだけ努力するか」という命題を「人をどれだけ信頼するか」という命題に差し替えます。

人を疑えばコストが掛かります。ある人の行動や成果を徹底的にチェックしようとすると、もう一人の人がいる(実は一人では足りないんじゃないか、という気もします。人が増えるとそれだけで仕事が増えますから)。じゃあ、そのチェックする人を信用するのか、という話も出てきます。つまり疑い始めればきりがないのです。

かといってメンバーを全面的に信頼するわけには行かない。プロジェクトに関わったことがある人ならお分かりだと思います。ウソを報告したりまずいことを隠したりメンバーもいるものです。

逆説的ですが障害やミスを発生させないように強いプレッシャーをかけるとメンバーがウソをついたり隠したりする傾向が強まります(むしろ当然?)。そうならないためには、かえって障害やミスを報告したメンバーを誉めてやるべきです。

ですから、プロジェクトの運営を通じて信頼度と技術力が見極めたら、信頼できるメンバーには基本的に任せる。そして技術力が疑わしいメンバーのタスクを減らし、その成果物をチェックする。これがもっとも効率がいい。別にウソをついているのではないか。信頼できない、と疑うってかかるわけではありません。それは却って逆効果でしょう。オーバーワークになったメンバーはえてして品質の悪いものを作ります。しかしその人が悪いわけではなく、追い込んだリーダー/マネージャの問題です。
とにかくここが出発点だと思います。まずは信頼できる人間を信頼すること。そして信頼できる人間が前向きに作業できる時間を確保した上で、チェック体制を作ること。チェックばかりに体力が行ってしまうと、行きつく先は品質の劣化に他なりません。

システム開発メンバの本業は何か。障害を潰すためのチェックではありません。障害を洗い出し、品質を向上させるのが本業のはずです。それを見失ってはならない、と私は思います。

2008年6月2日月曜日

「障害を許さない」プロジェクトが破綻する理由(3)

■障害と不安
以前にも不安とプロジェクトの関係について述べましたことがありますが、今回は障害と不安との関係に焦点を当てて考えてみたいと思います。

障害は常に不安を煽るものです。なぜでしょうか。それは障害がわれわれを(未だ来ぬ)未来の可能性へと差し向けるからです。

普段われわれは特にその瞬間瞬間の可能性と直面することなく日常を過ごしています。先のことは全て予定表に入っている。つまり日常の時間にあるのは「未だ来ぬ」未来ではなく「将に来たるべき」将来です。これが普通日常に生きているわれわれの時間意識です。
具体的に言えば、例えば明日、いや次の瞬間にも大地震がおきてわれわれは死ぬかもしれない。あるいは車にぶつかって死ぬかもしれない。残念ながらそれは本当のことです。しかしそれを普段本気で考えている人はいません。健康な人であっても時折自分の死について考えることがあるかもしれません。しかし「次の瞬間死ぬかもしれない」と一瞬一瞬常に真剣に考えている人はほとんどノイローゼでしょう。

もう少し踏み込んで言えば、われわれは日常的な営みによって未来という巨大な不安を覆い隠しているのです。

そして障害は予期されない不愉快な事象として、われわれの不安を顕わにします。だからこそわれわれは障害を前もって、あらかじめ知りたいと思うのです。
しかし残念ながら障害の発生日は手帳には書いていません。予定通りに発生する障害というのはほとんど言葉の矛盾です。

ところが障害の原因が判明した事後からふり返ってみれば、その発生が必然であったことが分かる。
ここである種の人の中で時系列が逆転します。あのときこういう対応をしておけば障害は未然に防ぐことができた。なぜそれができなかったのか。

ある意味正しい反応です。好ましくない事象が発生したときにその原因を究明し次のアクションを取る。ヘビに噛まれて痛かったのならば次はヘビに噛まれないように用心する。しかし残念ながらシステム障害に対応するための方法論としてはいささか貧弱過ぎる。システムはあまりに複雑だし、人はあまりに不完全だからです。

障害に対応するためにはまずは人の不完全さを受け入れる必要があると私は思います。つまり事前に潰そうといたずらに体力をかけるのではなく(これは経済学の問題です)、事前に障害を出来るだけ出して直しておくこと。そして障害が発生したときの運用を確立しておくこと。それがもっとも効率的に障害に対処する方法だと私は思います。