2008年12月13日土曜日

今日の料理

一週間前からからすみの作成に挑戦しています。(*参考1)(*参考2)

ボラではなくタラの卵を(タラコとか辛子明太ではなく生のやつですね)を買ってきて、まずは冷蔵庫で塩漬け。つーか全体的に食い物なの?大丈夫なの?って感じでした。一部緑色してるし(まあ最初からだけど。)。漬けていた間、冷蔵庫はずっと醗酵した魚卵のかほりで充満。腐敗臭ではなく、なんとなくたんぱく質系のまったりとした香りに海の匂いがするというか。人によっては好きな匂いかも。でも結構濃厚で冷蔵庫を開けると毎度ふわあぁんと塩漬け魚卵の匂い。幸い、妻の鼻の調子が悪かったので咎められることはありませんでしたが、う~ん、という感じ。一週間経過した昨日、塩を払って水に漬けました。塩抜きのためです。丸一日ほど塩抜きして、今は日本酒に漬けてます。



週中あたりから外+冷蔵庫で干し始めます。どうなることやら。

もう一つはアジの干物。30cmくらいのむっちりしたアジが一匹97円だったので、もうこれは買わないわけには行かなかったですよ。背開きにしようとしたら思ったよりアジが大きかったので3枚におろしました(相変わらず骨に身が残ってぐやじい(下手だから))。水800ccに対して大匙4杯の塩水+しょうゆと酒を少々(塩加減は水1リットルに対して大匙4杯+-1杯の塩くらいでいいみたい)に1時間浸してから

ベランダで乾燥。よっしゃ。明日の朝はアジの一夜干しでご飯だ。・・・よだれが出る・・・

ベランダに魚がぶら下がってる。いや、シュールな感じがしたのは一瞬だけですよ。すぐに違和感なく認識。というかしみじみとした豊かな気分も。縄文時代のDNAが生きているのだろうか。

サンマも安かったので(一匹58円!)、二匹買って酢で煮たのですが何故か最終的に全面的に焦げ付いてノックアウト。味見で美味かったので悔しさもひとしおでしたよ。明日はリベンジだ。

料理ばっかやってるけど、これが何故かストレス解消になるんだな。

まあ幸せな話だ。
.

DIとかAOPについて考えてみた

フレームワークって何だろう。最近Spring frameworkとかSeasarを試して考えさせられました。

(現時点での感想です。今後評価は変わるかもしれません)

なぜエンジニアはフレームワークを求めるのか。

開発生産性の向上とか、スキルの蓄積とか、そういう一般論やセールストークは脇においておきましょう。

フレームワークとは何か。フレームワークを使うものはフレームワークから使われる。ハリウッドの法則とも呼ばれます。これがフレームワークの本質のひとつです。フレームワークがメインで稼動し、開発者はフレームワークが呼ぶ部品を作る。この部品はフレームワークが定めるお作法に則って作成されなければなりません。つまり開発者はフレームワークが規定する型にハマったコードを書く必要がある。すなわち、フレームワークとは「アプリケーションこうあるべし」と定めるものです。しかも実装レベルで定めます。フレームワークに従わなければ稼動することもできません。

Strutsの目指したものは何だったか。もちろん、Webアプリケーションをシンプルに手早く開発することです。今思えば0.9時代のStrutsの抽象度は低く、またフレームワークにしては強制力が弱く柔軟に過ぎていました。しかしHTMLのインプットフォームをFormビーンにマッピングする発想(抽象化)と、画面遷移とBeanをXMLで定義する設計(疎結合)は非常に先進的であったと思います。

それではSpringの目指すものは何なのか。
Spring is a layered Java/J2EE application platform, based on code published in Expert One-on-One J2EE Design and Development by Rod Johnson (Wrox, 2002).

すなわちロッド・ジョンソン氏が提唱した、アプリケーションのデザインパターンの実装です。細かいところは省きますが、要するにSpringはStrutsとは異なり直接的な何らかの成果物を目標としているのではなく、より理念的なもの(概念と言ってもいいですし、思想、デザインと言ってもいい)を目指しているのです。それがSpringや(恐らくはSeasarも)をとっつきにくくしている理由のひとつであると思われます。

私はこのことが、つまり「目的が抽象的であること」がSpringフレームワークの問題だと思います。なぜか。私はそこにわれわれの業界に付きものの「手段と目的の逆転」が起こっていると見るからです。

なぜSpringを使うのか。Springを使うモチベーションとは何か。Springの位置づけからすると、それは「よいデザインパターンを実装するためである」ということになります。しかしちょっと待ってください。よいデザインパターンを実装するために、われわれはコードを書いているのでしょうか?コードを書くのは、何かやりたいことがあると思います。よい設計のためにコードを書く?そんなことがありえるでしょうか。

確かにオブジェクトをXMLから挿入できるDIや、横断的に割り込み処理をするAOPはよい発想だと思います。しかし、われわれはDIをするためにコードを書いているのではありません。DIやAOPは、あれば便利かもしれないもの。気の利いたスキマ商品なのではないか、と私は思います。例えるなら高級システム手帳。あったらうれしい。使いこなす人はカッコいいと思う。でも・・・別にいらないや。

Spring frameworkを開発する方の熱意と才能はすばらしいと思います。あんなものとても私には作れない。「よいフレームワークを提供して使って欲しい」「いいデザインのアプリケーションを作って欲しい」という熱意はまさに尊敬に値します。

でも私にはSpringは違和感がある。Data Injectionやるためにアプリ作ってんじゃねーや。と思ってしまう。

DBとエレガントに連携し、読みやすいコードで書きたいなら、HibernateやJPA(EJB3.0)を使うでしょう。

Webアプリを効率的に作ろうと思ったら、今の私なら躊躇なくJSFを選びます。

しかし、DIとAOPを使いたいから、XMLでデータや横断的処理を挿入したいからSpringを使うか?使わないと思うな。というかSpringとEJB3.0を連携させる体力の余裕があったら他に回すよね。

ということで、以上が現段階での私のSpring観です。否定的ってことで。

以上
.
(2008/12/15追記)
DIって本当に必要? - ひがやすを blogを見ると、Seasarのコミッタの方も真剣に自問しているようですね。偉い!偉いぞ!!
同じページで、普通の業務アプリケーションにはインターフェースはいらないんじゃないか、と言ってますがこれも偉い!!!よくぞ言った。必要だから使う、ではなく、ただ「インターフェースを使って設計しなきゃいけない」という強迫観念に襲われがちじゃありませんか?こういう問題提起・洞察は非常に重要です。
.

Seasar2を使ってみます(4)

次はAOPです。
わりあいすんなり行きました。

まず自前のIntercepterを準備します。
package test;

import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.aop.interceptors.AbstractInterceptor;

public class MyInterceptor extends AbstractInterceptor {

private static final long serialVersionUID = 1L;

@Override
public Object invoke(MethodInvocation method) throws Throwable {

System.out.println("Before");
Object ret = method.proceed();
System.out.println("After");
return ret;

}

}

次はexample2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<component class="java.util.ArrayList" name="list">
<initMethod name="add"><arg>"Hoge"</arg></initMethod>
<initMethod name="add"><arg>"Piyo"</arg></initMethod>
</component>

<component class="java.lang.String" name="autoBinding"/>
<component class="java.lang.String" name="useAnnotation"/>

<component class="test.Hello" name="hello">
<arg>list</arg>
<property name="autoBinding">"自動バインディング"</property>
<!-- ダメだった
<property name="useAnnotation">"アノテーション利用"</property>
-->
<aspect pointcut="sayHello">
<component class="test.MyInterceptor"
name="intercepterTest"/>
</aspect>
</component>
</components>

MainとHelloは変更なしです(AOPだからね)。

以上です。(はて、しかしこれをどう使うのかな)
.

Seasar2を使ってみます(3)

次はフィールドインジェクションです。publicフィールドへの自動バインディングとアノテーションを使ったバインディングを試します。

【結論】
自動バインディングは上手くいきましたが、アノテーションはダメでした。なぜだろう??
以下がメモです。
■まず"Binding"アノテーションが存在しない
■Webを調べると"Binding"ではなく標準の"Resource"を使ったほうがよいとのことだったので"javax.annotation.Resource"を使ってみたがダメ。
■@Resource(name="useAnotation")  → ダメ
■@Resource → ダメ
■privateじゃなくprotectedにしてみた → ダメ
■付属のライブラリjarを全部ビルドパスに追加してみた → ダメ
■ダメな理由は結局分からず(なんかすごい恥ずかしいミスをしている予感も)

【作業】
eclipse上でUTF8を入力するために、example2.diconの拡張子をxmlとしています。
(dicon拡張子だとデフォルトエンコーディングのMS932が適用されるらしく、日本語を入力するとSAXExceptionが出るため)

Helloクラス
package test;

import java.util.List;

import javax.annotation.Resource;

public class Hello {

public String autoBinding;

// ↓結局ダメ
@Resource
protected String useAnnotation;

private List<String> listNames;

public List<String> getListNames() {
return listNames;
}

public Hello(List<String> listNames) {
this.listNames = listNames;
}

public void sayHello() {
for (String name: listNames) {
System.out.println("Hello "+name+"! ");
}
System.out.println("Auto binding -> "+autoBinding);
// ↓nullが出るだけです
System.out.println("Annotation binding -> "+useAnnotation);
}

}

Mainクラス
package test;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

public class Main {
public static void main(String args[]) {
SingletonS2ContainerFactory.setConfigPath("example2.xml");
SingletonS2ContainerFactory.init();
S2Container container = SingletonS2ContainerFactory.getContainer();
Hello hello = (Hello)container.getComponent("hello");
hello.sayHello();
}
}

example2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<component class="java.util.ArrayList" name="list">
<initMethod name="add"><arg>"Hoge"</arg></initMethod>
<initMethod name="add"><arg>"Piyo"</arg></initMethod>
</component>

<component class="java.lang.String" name="autoBinding"/>
<component class="java.lang.String" name="useAnnotation"/>

<component class="test.Hello" name="hello">
<arg>list</arg>
<property name="autoBinding">"自動バインディング"</property>
<!-- ダメだった
<property name="useAnnotation">"アノテーション利用"</property>
-->
</component>
</components>

以上
.

Seasar2を使ってみます(2)

今度はHelloクラスのコンストラクタからデータを入れてみます(コンストラクタ・インジェクション)。

Helloからsetterを削除してコンストラクタでlistを受けるようにします。
package test;

import java.util.List;

public class Hello {

private List<String> listNames;

public List<String> getListNames() {
return listNames;
}

public Hello(List<String> listNames) {
this.listNames = listNames;
}

public void sayHello() {
for (String name: listNames) {
System.out.println("Hello "+name+"! ");
}
}

}

example2.diconを作成します。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<component class="java.util.ArrayList" name="list">
<initMethod name="add"><arg>"Hoge"</arg></initMethod>
<initMethod name="add"><arg>"Piyo"</arg></initMethod>
</component>
<component class="test.Hello" name="hello">
<arg>list</arg>
</component>
</components>

Main.javaを一応載せておきます。
package test;

import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;

public class Main {
public static void main(String args[]) {
SingletonS2ContainerFactory.setConfigPath("example2.dicon");
SingletonS2ContainerFactory.init();
S2Container container = SingletonS2ContainerFactory.getContainer();
Hello hello = (Hello)container.getComponent("hello");
hello.sayHello();
}
}

以上
.

Seasar2を使ってみます(1)

適切なTutorialやサンプルが見当たらないため躊躇していましたが、Spring(DIとしての)をいじってみてなんとなくDIフレームワークとやらが分かってきたので、その流れでSeasar2を触ってみました。

元にしたのは以下のページ。これ以上ないほどシンプルなサンプルです。

Human System: The First Seasar2 Example

まあ取っ掛かりとしては十分なんだけど、何も知らない人がこれ見ても厳しいでしょうな。つーかやってみようとすら思うかな?

で、Eclipseにエイヤとサンプルをつっこんで動作確認完了。クラスパスとかパッケージのパスとか基本的なところに注意しましょう(example.diconも暮らすパス上に配置します)。それ以外の注意点は以下の通りです。

▽稼動に必要なライブラリ
s2-framework-2.4.33.jar
commons-logging-1.1.jar
ognl-2.6.9-patch-20070908.jar
javaassist-3.4.ga.jar

▽XMLについて
example.diconから以下の二行を削除しないとエラーコード"ESSR0054"のSAXExceptionが発生して動きません。
</components>
<components>
すなわち
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<component class="java.util.ArrayList" name="list">
<initMethod name="add"><arg>"Naoki Takezoe"</arg></initMethod>
</component>
</components> <!-- この行と -->
<components> <!-- この行が不要。 -->
<component class="jp.sf.amateras.seasar.example.Hello" name="hello">
<property name="target">list</property>
</component>
</components>

当たり前だけどこれだけではふーん、という感じ。確かにDIだね。みたいな。でもちょっとSpringに比べてプリミティブ?

国産フレームワークということなので、それだけでも応援したいですね。

引き続き調べてみたいと思います。(何やろうかな)

.

2008年12月8日月曜日

偶然とチェ・ゲバラ

図書館で何気なく手に取ったチェ・ゲバラの「ボリビア日記」。チェ・ゲバラって結局誰なんだっけ?という程度の認識でナニゲに借りてしまったのが二週間ほど前でした。すなわち「ゲバラって誰」という認識だった。ゆえに借りてみた。実に薄っぺらいきっかけです。帰ってから妻に「チェ・ゲバラって誰だっけ」と聞くと「えーと、何かキューバとかカストロとかそんな感じ。それ以上のことは知らない」との答え。私の認識はそれ以前でした。

で、読んでみるとなかなか面白い。そうか。チェ・ゲバラってこんな人だったのか。理想に駆り立てられ、世界を変えようとゲリラ活動に身を投じた男。永遠の青春。偶像化されるのも理解できるなあ。日本の学園闘争とか60年代後半もこんな空気が流れてたんだろうな。

ま、それはさておいて「ボリビア日記」を読み始めてしばらくしていたら何やらチェ・ゲバラが映画化される模様。うん。シンクロした。たまにこういうことがありますね。

さて、この偶然をどう解釈するか。人間はなんにつけても意味を見出したい存在なのでいろいろパターンを考えてみる。

1.私が図書館でチェ・ゲバラの本を借りたがゆえに、まさにこの私をターゲットとして映画が作られた。
→ うん。オカシイ人の発想ですな。大体時系列でつじつまが合わない。映画作るのに数年はかかるはずだから。

2.チェ・ゲバラ再評価の雰囲気が以前からじわじわと高まっていた。映画の作成・公開もその流れに沿ったもの。私がたまたまチェ・ゲバラの本を手に取ったのはまったくの偶然。意味はない。
→ まあ、妥当な解釈でしょう。

3.小林多喜二の蟹工船のヒットやアメリカ流資本主義に対する批判的風潮に乗り、次はチェ・ゲバラ関連を売り込もうとして広告代理店がいろいろ布石を打っていた。私も無意識のうちにWebやテレビから触発されており、図書館で「ボリビア日記」を手に取ったのは私の自由意志ではなく、実は広告代理店のキャンペーンの結果でしかなかった。映画化もその流れ。
→ ありそうですが、ややオーバーな解釈。

というわけで、2がメインで3はそういうことも少しはあるかな、という感じですね。偶然っていうのも楽しいもんです。

私が一週間ほど前にカワハギについて書いた後、asahi.comでカワハギが出てきたのもまた別のシンクロ。カワハギの旬が冬だって理由はあるでしょうが、やっぱり楽しい。

以上
.

2008年12月6日土曜日

改めてSpringを試す(DIコンテナとしての)

これまでSpring MVCのついでにSpringの機能を使って気ましたが、改めてDIコンテナとしてのSpringコアを触ってみたいと思います。

大体"DIコンテナ"なんていう名称が胡散臭かったんだよね。またしてもJargonか。けっ。位にしか思っていなかった。でも理解しないままケチをつけるのもカッコ悪いので。

試したのは以下のチュートリアルです。こなれていて(特徴の示し方がシンプルで明確。分かりやすい)悪くないです。
http://www.atmarkit.co.jp/fjava/rensai3/springdi01/springdi01_2.html

【まとめ】

いや、Springって結構いいアイデアですね。要するにXMLを介してオブジェクトを連携させることで、疎結合やAOP(処理の注入。intercept。そんな感じ)を実現するフレームワークです。例によってSpringの本質をぜんぜん理解してなかったみたい(なんでわざわざHibernateやらStrutsと連携させる必要があるんだ。わずらわしい。くらいの認識でした。お恥ずかしい)。

以前「SpringはアーミーナイフでStrutsは鋭い刃物」と喩えました。このときはSpring MVCのみを念頭においていたのですが、Spring全体に対しても当たらずとも遠からずかもしれません。Springは便利で軽快な汎用ツール群だと思います。それにSpringで開発するのは結構楽しい(これって重要)。エンジニア魂をくすぐる。人気があるのも理解できます。

使い場所にもよるでしょうが、プロジェクトによっては有効ではないでしょうか。ただちょっとマニアックな気がするなあ。Springで作って良かった。と実感するケースはあまりなかったりして・・・(「再利用可能性」を志向して一生懸命デザインしても、実は誰も再利用しない、とかそんな感じ)

【おまけ】

チュートリアルの流れで少し拡張してみました。(ぜんぜん大したものではないですが一応)

■ SpringTest.java
package test;

import java.util.List;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {

/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"applicationContext.xml");
Target target = (Target) context.getBean("target");
System.out.println(target.getMessage());
Parent parent = (Parent) context.getBean("parent");
System.out.println("親:" + parent.getName());
List<Child> children = parent.getChildren();
for (Child child : children) {
System.out.println(child.getName());
}

}

}

■ applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="target" class="test.Target">
<property name="message">
<value>Hello World!</value>
</property>
</bean>
<bean id="oldest-son" class="test.Child">
<property name="name">
<value>長男</value>
</property>
<property name="no">
<value>1</value>
</property>
</bean>
<bean id="oldest-daughter" class="test.Child">
<property name="name">
<value>長女</value>
</property>
<property name="no">
<value>2</value>
</property>
</bean>

<bean id="parent" class="test.Parent">
<property name="children">
<list>
<ref bean="oldest-son" />
<ref bean="oldest-daughter" />
</list>
</property>
<property name="name">
<value>親</value>
</property>
</bean>
</beans>

■Parent.java

package test;

import java.util.List;

public class Parent {

private List<Child> children;
private String name;

public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}

}

■Child.java

package test;

public class Child {
private String name;
private Integer no;

public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getNo() {
return no;
}
public void setNo(Integer no) {
this.no = no;
}
}

以上
.

2008年12月5日金曜日

RAD7.5でWeb Serviceを作ってみる

ここ数年使われているjargonであるところのWeb service(英語圏では大文字でなく、かつ複数形のweb servicesみたいな記載をよく見ます)。せっかくなのでRAD7.5で作ってみました。個人的にはこのテクノロジーに対しては出た当初から半信半疑です。セールストークやらわけの分からない専門用語が飛び交い過ぎている。まあ私が見限ったのはずいぶん昔のことだし、食わず嫌いもよくないので、最近のweb sevicesがどうなってるのか見てみたいと思います。

TutorialはIBM dW "Create stand-alone Web services applications with Eclipse and Java SE 6, Part 1"。例によってIBM IDの登録が必要です。

注意点)
build.xmlを実行する箇所について。RAD上で右クリック、実行 > Antビルド としてもエラーとなります。コマンド・プロンプトからantを実行すると(別途Apache antの導入が必要)、問題なく実行できました。ちなみにCygwinでもダメです。"Program Files"以下に導入しているからかもしれません。

RunServer を実行する箇所について。実行するためには commons-logging.jar と commons-discovery.jar をビルドパスに追加する必要がありました。

WebサービスエクスプローラーからUDDIメインを開いた後の画面について。Tutorialとは違うようです。RAD7.5では、
レジストリー名:SayHelloService
照会 URL :http://localhost:8080/wsServerExample?wsdl
と入力します。

Webサービスエクスプローラーの使い勝手。ぜんぜん違いますね。いろいろいじってみましたが、とうとうgetGreetingsを呼び出すことができませんでした。

結論。大山鳴動ねずみ一匹、という感じです。まだまだだな。(<偉そう)

以上。
.

2008年11月30日日曜日

カワハギ、カワハギ

だって魚関係のWebサイトを見れば「カワハギといえば肝。肝は旨い」ばっかりですよ。@nifty:デイリーポータルでも取り上げられてるし。で、スーパーに行く途中のこと。しっかりカワハギ=肝=旨いと刷り込まれた私の脳は、目ざとく通りすがりの居酒屋のメニュー「カワハギの肝和え 800円」を発見。カワハギの肝和えか。高いな。旨いらしいな。

で、スーパーに行ってみたら魚コーナーに未処理のカワハギが。何かカワハギにインスパイアされまくりって感じで。魚コーナーのお兄ちゃんに「これ刺身いけますか」と聞くと「大丈夫ですよー」と威勢のよい答え。もう買うしかないでしょ。今日の晩御飯はカワハギの肝和えに決定、ということで、カワハギを一匹買って帰りました。子供には無理だから、メインというよりは大人向けのサブアイテム。

そして夕食。メインのコロッケを作るのに一生懸命になってしまい、カワハギのことはすっかり忘れてコロッケ食べてごちそうさまー。あー美味しかった。ってカワハギどうしよう。とよくあるパターン。

しょうがない、お父さんの夜のおやつはカワハギだ。と重い腰を上げて(それでも少し楽しみにしながら)カワハギの解体に向かいました。出刃でツノを切り落とし、口を切り落とす。皮をメリメリと剥いで、後頭部?こめかみ?あたりにざくっと包丁を入れて骨を断ち、そこから頭をもぎ取る。頭にくっついて肝が出てきました。他人のWebサイトで見ると肝だけきれいに取れているんですが、実際にはグダグダといろいろ張り付いている。写真はイメージで実物とは多少異なる場合がってやつですな。慎重に取り外したつもりでしたが少し崩れてしまった。肝は皿に乗せてしょうゆを掛けておきます。子供たちが「気持ち悪ーい」「これ何?」「苦玉ってどれ?」と騒ぎながら覗き込んでます。頼むから出刃包丁のそばに顔を近づけるな。それから身を三枚に下ろして(下手なので骨にしっかり肉がついてしまう・・・クヤシイ)から、中骨を避けてサク取りに。刺身包丁で小さく切って、肝と和えました。(子供はもう飽きてどっかで遊んでる。)

実家からもらった酒「越中五箇山 三笑楽」をコップにたっぷり一合分注ぎます。普段呑む酒と違って薄い琥珀色してて、香りとうまみが濃い。ちびりとすすって、デワデワ、とカワハギに箸をつける。

う~ん。見た目結構グロいっすよ。肝にはところどころ薄い血管がまとわりついてるし(多分解体が下手だった。もしくは取るか裏ごしするべきだったみたい)。身には薄皮がついてて(これも取り忘れた)、全体になんだかぴろぴろしてる感じ。

箸に肝をつけてちょっとなめてみると。うん。確かに旨い。結構旨い。生臭さは許容範囲。

肝にまみれた身を食べてみると、こりこりして旨い。これからは普通に好物って言うかも。カワハギの肝和え行っとく?みたいな。高いから自分で作るか。

高級そうな店で、小ざかしい器にちょこんと盛られてきたら、その旨さに感動してしまうかもしれません。形のそろわない刺身にところどころ赤い血管が張り付いている、その時点で負けだったかも。でも逆に言えばその見た目にもかかわらず旨いことは確か。

演出がまずかったな。あとは技術的な失敗もいくつかあったように思われました。以下が次回の課題。

・生臭さを取るため肝には酒を振りかけておくこと
・しょうがの絞り汁を入れたい
・血管は取り除いておくこと
・身から薄皮を取ること
・刺身は形をそろえて薄く切ること(いっそ軽く叩くか)

また食べようと思ってます。

以上。
.

2008年11月28日金曜日

偽善とか自己満足という言葉が気になっていた

気になりますよね。え?気にしたことなんかないって?そうか・・・私だけか。時々妙に「自己満足?偽善?」って考えこんじゃうんだけどな。

確かに青臭い同士学生の議論じゃあるまいし、大人になってしまえば「それはお前の自己満足だ」とか「偽善だ」などと決め付けられる機会も滅多にありませんね。それにたとえ他人から決め付けられるても「それがどーした」「ほっとけ」で済みます。オレが満足しようがしまいがお前の知ったことか。2ちゃんかどこかの標語にありましたが「しない善よりする偽善」。客観的な成果がでればいいじゃないか。だいたいお前には善が分かっているのか。お前はブッシュ大統領か、と。

そもそも、「自己満足」と「偽善」という言葉を平然と並べているが、関係あるのか、と。一括りにして語る意味があるのか。そんな声も聞こえてきそうです。

う~ん。そのとおりかもしれません。でも引っかかる。昔から幾度か反芻させられてきた言葉なんです。非難と若干の責める側の優越感を漂わせたこの言葉。「自己満足で終わってないか?」「それは偽善じゃないのか?」

なぜそれほどまでにこの言葉に引っかかるんだろう。ちょっと考えてみました。

両者の共通点って何だろう。

それはこれらの言葉が二つとも、その程度で満足していいのか、それでいいと思っているのか、と人に根底的に問いかける意図を持って発せられる、まずはそこが共通する点であるように思えます(言葉の裏にひそむ悪意や揶揄は考えないことにしましょう。ストレートに問いかけられたとします)。

お前の人生それでいいのか?大きなお世話だといえばその通りですが、私はふと足を止めて考えてしまう。俺はこれまで正しいことをしてきたのだろうか。これでよかったのか?でも次の瞬間にその問いを忘れてしまう。今日中に完了しなければならない仕事がある。あるいは子供が呼んでいる。一時的に私はその問いを忘れてしまう。でも忘れたつもりでもその問いは心の奥深くに沈殿し、再び浮かび上がる機会をじっと待っている。

お前の人生それでいいのか?実に青臭い問いかけです。あるいは人生を知らない浅い問いなのかもしれません。昔は常に自問していたような気がします。これでいいんだろうか。俺は何をしたいんだろうか。何をすべきなんだろうか。でも年を取るにつれてそんな問いは忘れていった。仕事も収入もあり、養うべき家族もいる。いまさら根本的に反省する必要などない。それより日々働いて家族と暮らすので精一杯。

希望や挫折や将来の不安で押しつぶされそうになりつつ、何ごとかを成し遂げたいと考えていたかつての自分。むやみに焦り、イライラとしながら周りを軽蔑し、でも何が出来るわけでもなく独り悶々と過ごしていた昔の"俺"。そんな"俺"が今の私を見たら何と言うだろうか。今の人生でいいのか。それでお前は本当に良かったのか。そんなふうに厳しく問い詰めてくるのかもしれません。

昔の自分と今の自分が顔を見合わせたとき、恥ずかしそうに去って行くのは今の"私"の方なのでしょうか。それとも昔の"俺"?

「自己満足」とか「偽善」という言葉を聞くと、かつての青臭い自分を思い出すような気がする。それがこの言葉が引っかかる理由なのかも知れません。

生きて行くために失われるもの。それは失われる必然性があったのか、それとも失われるべきではなかったのか。

死ぬときに自分の人生を肯定できれば、それでいい。そんな気がします。
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(11)

値をサーバ側で取得します。

1. ListBeanに選択された値を扱う変数と処理を追加します。
2. list.jspを編集します(変数の追加・送信ボタンの追加)。
3. faces-config.xmlに画面遷移定義を追加します。

1. ListBeanに選択された値を扱う変数と処理を追加
package test.beans;

import java.util.List;

import javax.ejb.EJB;

import test.MySample;
import test.MySampleSessionLocal;

public class ListBean {
private static final long serialVersionUID = 1L;

List<MySample> mySamples = null;
// Stringにしないとエラーが出ます。理由はよく分かりません・・・
private String selectedIndex = null;

public String getSelectedIndex() {
return selectedIndex;
}

public void setSelectedIndex(String selectedIndex) {
this.selectedIndex = selectedIndex;
}

@EJB(name="MySample")
private MySampleSessionLocal mySampleSession;

public List<MySample> getMySamples() {
// まあ二回くらい呼ばれたっていいでしょう
if (mySamples == null) {
try {
List<MySample> tmpList = mySampleSession.listMySamples();
setMySamples(tmpList);
} catch (Exception e) {
//
}
}
return mySamples;
}

private void setMySamples(List<MySample> mySamples) {
// 読み取り専用
this.mySamples = mySamples;
}

public String executeTest() {
System.out.println("Selected index -> " + selectedIndex);
return "success";
}

}

2. list.jspを編集
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="/WEB-INF/tld/mysample.tld" prefix="custom"%>
<html>
<head>
<title>list</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
<h2>リスト MySample</h2>
<f:view>
<h:form>
<h:dataTable value="#{listBean.mySamples}" var="item" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<custom:radioButton id="myRadioId1" name="myRadioCol"
overrideName="true" value="#{listBean.selectedIndex}"
itemValue="#{item.myid}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<f:verbatim>id: </f:verbatim>
<h:outputText value="#{item.myid}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="VAL" />
</f:facet>
<f:verbatim>value: </f:verbatim>
<h:outputText value="#{item.myFlag}" />
</h:column>
</h:dataTable>
<h:commandButton value="実行"
action="#{listBean.executeTest}" />
</h:form>
</f:view>
</body>
</html>

3. faces-config.xmlに画面遷移定義を追加
 <navigation-rule>
<from-view-id>list.jsp</from-view-id>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>list.jsp</to-view-id>
</navigation-case>
</navigation-rule>

以上。
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(10)

一覧表示した行を、ラジオボタンで選択できるようにします。
残念ながらカスタムタグを開発する必要があります。
(JSTLでもこの手の実装に苦労した記憶が・・・どうして標準の機能に無いんだろう??)

以下のページを参考にしました。というか、一部型のエラーが出たりしたので、変数をStringからObjectに変更してtoString()してますが、ほとんどそのまんまです。(感謝)

※RAD環境ではweb.xmlへのtaglib要素の追加は不要でした。web-app_2_5.xsdだから?よく分かってません。

Group radio buttons inside a JSF dataTable component
Write a custom JSF tag for enhancing radio button behavior
By Srijeeb Roy, JavaWorld.com, 02/27/07
(JAVAWORLD)
http://www.javaworld.com/javaworld/jw-02-2007/jw-02-jsf.html

ずいぶんとdeprecatedになってしまっているようですが、Webをダラダラ調べたところ、気にせず使うのが一番いいみたい。まだこれといった代替方法は確立されていないようです。

■準備
MySampleJSFの中にそのまま作ってもよいのですが、jarに分けたほうがカッコよいのでユーティリティ・モジュールプロジェクトとして作成します。

まずファイル > 新規 > その他 > 新規Javaユーティリティ・モジュールプロジェクト > "MySampleCTG" を作成。

MySampleJSF のプロパティを開き、Java EE モジュール依存関係 > Webライブラリータブ(J2EEモジュールではなく)を開いてMySampleCTGにチェックを入れます。

準備完了。

■カスタムタグの作成
以下のステップが必要です。結構大変ですね。

1. 以下の三つのクラスを作成します。
1-1. コンポーネント クラス(MySampleCTGプロジェクトに作成)
1-2. レンダー クラス(同上)
1-3. カスタム・タグ クラス(同上)
2. TLDファイルを作成します。(MySampleJSFプロジェクトに作成。MySampleCTGのMETA-INFではうまく行きませんでした)
3. faces-config.xmlにコンポーネント要素を追加します。(同上)
4. jspにタグを書きます。(同上)

1-1. コンポーネントクラス(UICustomSelectOneRadio)
package test.ctg;

import javax.el.ValueExpression;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;

public class UICustomSelectOneRadio extends UIInput {

// 1. 属性をクラス変数として定義
private String name = null;
private String overrideName = null;
private String styleClass = null;
private String style = null;
private String disabled = null;
private String itemLabel = null;
private Object itemValue = null;
private String onClick = null;
private String onMouseOver = null;
private String onMouseOut = null;
private String onFocus = null;
private String onBlur = null;

// 2. 動的に属性を取得するためのメソッドを定義
public String returnValueBindingAsString(String attr) {
// サンプルコードは一部Deprecatedだったので適宜変更しています。
ValueExpression valueExpression = getValueExpression(attr);
if (valueExpression != null) {
return valueExpression.getValue(this.getFacesContext()
.getELContext()).toString();
} else {
return null;
}
}

// 3. setter, getterを定義. getterでreturnValueBindingAsStringを使っている
// ので注意
public String getName() {
if (name != null) {
return name;
}
return returnValueBindingAsString("name");

}

public void setName(String name) {
this.name = name;
}

public String getOverrideName() {
if (overrideName != null) {
return overrideName;
}
return returnValueBindingAsString("overrideName");
}

public void setOverrideName(String overrideName) {
this.overrideName = overrideName;
}

public String getStyleClass() {
if (styleClass != null) {
return styleClass;
}
return returnValueBindingAsString("styleClass");
}

public void setStyleClass(String styleClass) {
this.styleClass = styleClass;
}

public String getStyle() {
if (style != null) {
return style;
}
return returnValueBindingAsString("style");
}

public void setStyle(String style) {
this.style = style;
}

public String getDisabled() {
if (disabled != null) {
return disabled;
}
return returnValueBindingAsString("disabled");
}

public void setDisabled(String disabled) {
this.disabled = disabled;
}

public String getItemLabel() {
if (itemLabel != null) {
return itemLabel;
}
return returnValueBindingAsString("itemLabel");
}

public void setItemLabel(String itemLabel) {
this.itemLabel = itemLabel;
}

public Object getItemValue() {
if (itemValue != null) {
return itemValue;
}
return returnValueBindingAsString("itemValue");
}

public void setItemValue(Object itemValue) {
this.itemValue = itemValue;
}

public String getOnClick() {
if (onClick != null) {
return onClick;
}
return returnValueBindingAsString("onClick");
}

public void setOnClick(String onClick) {
this.onClick = onClick;
}

public String getOnMouseOver() {
if (onMouseOver != null) {
return onMouseOver;
}
return returnValueBindingAsString("onMouseOver");
}

public void setOnMouseOver(String onMouseOver) {
this.onMouseOver = onMouseOver;
}

public String getOnMouseOut() {
if (onMouseOut != null) {
return onMouseOut;
}
return returnValueBindingAsString("onMouseOut");
}

public void setOnMouseOut(String onMouseOut) {
this.onMouseOut = onMouseOut;
}

public String getOnFocus() {
if (onFocus != null) {
return onFocus;
}
return returnValueBindingAsString("onFocus");
}

public void setOnFocus(String onFocus) {
this.onFocus = onFocus;
}

public String getOnBlur() {
if (onBlur != null) {
return onBlur;
}
return returnValueBindingAsString("onBlur");
}

public void setOnBlur(String onBlur) {
this.onBlur = onBlur;
}

// 4. restoreStateとsaveStateメソッドを実装します。
@Override
public void restoreState(FacesContext context, Object state) {
Object[] values = (Object[]) state;
super.restoreState(context, values[0]);
styleClass = (String) values[1];
style = (String) values[2];
disabled = (String) values[3];
itemLabel = (String) values[4];
itemValue = (String) values[5];
onClick = (String) values[6];
onMouseOver = (String) values[7];
onMouseOut = (String) values[8];
onFocus = (String) values[9];
onBlur = (String) values[10];
name = (String) values[11];
overrideName = (String) values[12];
}
@Override
public Object saveState(FacesContext context) {
Object[] values = new Object[13];
values[0] = super.saveState(context);
values[1] = styleClass;
values[2] = style;
values[3] = disabled;
values[4] = itemLabel;
values[5] = itemValue;
values[6] = onClick;
values[7] = onMouseOver;
values[8] = onMouseOut;
values[9] = onFocus;
values[11] = name;
values[12] = overrideName;
return (values);
}

// 5. getFamilyを実装します。faces-config.xmlにこの名前を指定します。
@Override
public String getFamily() {
return ("CustomSelectOneRadio");
}
}

次はレンダークラス(HTMLCustomSelectOneRadioRenderer)です。
package test.ctg;

import java.io.IOException;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIData;
import javax.faces.component.UIInput;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.Renderer;

public class HTMLCustomSelectOneRadioRenderer extends Renderer {

@SuppressWarnings("unchecked")
@Override
public void decode(FacesContext context, UIComponent component) {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}
UICustomSelectOneRadio aUICustomSelectOneRadio = null;
if (component instanceof UICustomSelectOneRadio) {
aUICustomSelectOneRadio = (UICustomSelectOneRadio) component;
} else {
return;
}
Map map = context.getExternalContext().getRequestParameterMap();
String name = getName(aUICustomSelectOneRadio, context);
if (map.containsKey(name)) {
String value = map.get(name).toString();
if (value != null) {
setSubmittedValue(component, value);
}
}
}

public void setSubmittedValue(UIComponent component, Object obj) {

if (component instanceof UIInput) {
((UIInput) component).setSubmittedValue(obj);
}
}

private String getName(UICustomSelectOneRadio aUICustomSelectOneRadio,
FacesContext context) {

UIComponent parentUIComponent = getParentDataTableFromHierarchy(aUICustomSelectOneRadio);
if (parentUIComponent == null) {
return aUICustomSelectOneRadio.getClientId(context);
} else {
if (aUICustomSelectOneRadio.getOverrideName() != null
&& aUICustomSelectOneRadio.getOverrideName().equals("true")) {
return aUICustomSelectOneRadio.getName();
} else {
String id = aUICustomSelectOneRadio.getClientId(context);
int lastIndexOfColon = id.lastIndexOf(":");
String partName = "";
if (lastIndexOfColon != -1) {
partName = id.substring(0, lastIndexOfColon + 1);
if (aUICustomSelectOneRadio.getName() == null) {
partName = partName + "generatedRad";
} else
partName = partName + aUICustomSelectOneRadio.getName();
}
return partName;
}
}
}

private UIComponent getParentDataTableFromHierarchy(UIComponent uiComponent) {
if (uiComponent == null) {
return null;
}
if (uiComponent instanceof UIData) {
return uiComponent;
} else {
// try to find recursively in the Component tree hierarchy
return getParentDataTableFromHierarchy(uiComponent.getParent());
}
}

@Override
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
if ((context == null) || (component == null)) {
throw new NullPointerException();
}

UICustomSelectOneRadio aUICustomSelectOneRadio = (UICustomSelectOneRadio) component;

if (component.isRendered()) {
ResponseWriter writer = context.getResponseWriter();

writer.write("<input type=\"radio\"");

writer.write(" id=\"" + component.getClientId(context) + "\"");
writer.write(" name=\"" + getName(aUICustomSelectOneRadio, context)
+ "\"");
if (aUICustomSelectOneRadio.getStyleClass() != null
&& aUICustomSelectOneRadio.getStyleClass().trim().length() > 0) {
writer
.write(" class=\""
+ aUICustomSelectOneRadio.getStyleClass()
.trim() + "\"");
}
if (aUICustomSelectOneRadio.getStyle() != null
&& aUICustomSelectOneRadio.getStyle().trim().length() > 0) {
writer.write(" style=\""
+ aUICustomSelectOneRadio.getStyle().trim() + "\"");
}
if (aUICustomSelectOneRadio.getDisabled() != null
&& aUICustomSelectOneRadio.getDisabled().trim().length() > 0
&& aUICustomSelectOneRadio.getDisabled().trim().equals(
"true")) {
writer.write(" disabled=\"disabled\"");
}
if (aUICustomSelectOneRadio.getItemValue() != null) {
writer.write(" value=\""
+ aUICustomSelectOneRadio.getItemValue().toString().trim() + "\"");
}
if (aUICustomSelectOneRadio.getOnClick() != null
&& aUICustomSelectOneRadio.getOnClick().trim().length() > 0) {
writer.write(" onclick=\""
+ aUICustomSelectOneRadio.getOnClick().trim() + "\"");
}
if (aUICustomSelectOneRadio.getOnMouseOver() != null
&& aUICustomSelectOneRadio.getOnMouseOver().trim().length() > 0) {
writer.write(" onmouseover=\""
+ aUICustomSelectOneRadio.getOnMouseOver().trim()
+ "\"");
}
if (aUICustomSelectOneRadio.getOnMouseOut() != null
&& aUICustomSelectOneRadio.getOnMouseOut().trim().length() > 0) {
writer
.write(" onmouseout=\""
+ aUICustomSelectOneRadio.getOnMouseOut()
.trim() + "\"");
}
if (aUICustomSelectOneRadio.getOnFocus() != null
&& aUICustomSelectOneRadio.getOnFocus().trim().length() > 0) {
writer.write(" onfocus=\""
+ aUICustomSelectOneRadio.getOnFocus().trim() + "\"");
}
if (aUICustomSelectOneRadio.getOnBlur() != null
&& aUICustomSelectOneRadio.getOnBlur().trim().length() > 0) {
writer.write(" onblur=\""
+ aUICustomSelectOneRadio.getOnBlur().trim() + "\"");
}

if (aUICustomSelectOneRadio.getValue() != null
&& aUICustomSelectOneRadio.getValue().equals(
aUICustomSelectOneRadio.getItemValue())) {
writer.write(" checked=\"checked\"");
}
writer.write(">");
if (aUICustomSelectOneRadio.getItemLabel() != null) {
writer.write(aUICustomSelectOneRadio.getItemLabel());
}
writer.write("</input>");
}
}
}

■カスタム・タグクラス(HTMLCustomSelectOneRadioTag)
package test.ctg;

import javax.faces.FactoryFinder;
import javax.faces.application.Application;
import javax.faces.application.ApplicationFactory;
import javax.faces.component.UIComponent;
import javax.faces.el.ValueBinding;
import javax.faces.webapp.UIComponentELTag;
import javax.faces.webapp.UIComponentTag;

public class HTMLCustomSelectOneRadioTag extends UIComponentELTag {

public HTMLCustomSelectOneRadioTag() {
name = null;
value = null;
styleClass = null;
style = null;
disabled = null;
itemLabel = null;
itemValue = null;
onClick = null;
onMouseOver = null;
onMouseOut = null;
onFocus = null;
onBlur = null;
overrideName = null;
}

public String getDisabled() {
return disabled;
}

public String getItemLabel() {
return itemLabel;
}

public String getItemValue() {
return itemValue;
}

public String getName() {
return name;
}

public String getOnBlur() {
return onBlur;
}

public String getOnClick() {
return onClick;
}

public String getOnFocus() {
return onFocus;
}

public String getOnMouseOut() {
return onMouseOut;
}

public String getOnMouseOver() {
return onMouseOver;
}

public String getOverrideName() {
return overrideName;
}

public String getStyle() {
return style;
}

public String getStyleClass() {
return styleClass;
}

public String getValue() {
return value;
}

public void setDisabled(String string) {
disabled = string;
}

public void setItemLabel(String string) {
itemLabel = string;
}

public void setItemValue(String string) {
itemValue = string;
}

public void setName(String string) {
name = string;
}

public void setOnBlur(String string) {
onBlur = string;
}

public void setOnClick(String string) {
onClick = string;
}

public void setOnFocus(String string) {
onFocus = string;
}

public void setOnMouseOut(String string) {
onMouseOut = string;
}

public void setOnMouseOver(String string) {
onMouseOver = string;
}

public void setOverrideName(String string) {
overrideName = string;
}

public void setStyle(String string) {
style = string;
}

public void setStyleClass(String string) {
styleClass = string;
}

public void setValue(String string) {
value = string;
}

protected void setProperties(UIComponent component) {
super.setProperties(component);
UICustomSelectOneRadio aUICustomSelectOneRadio =
(UICustomSelectOneRadio) component;
if (name != null) {
if (UIComponentTag.isValueReference(name)) {
aUICustomSelectOneRadio.setValueBinding("name",
getValueBinding(name));
} else {
aUICustomSelectOneRadio.getAttributes().put("name", name);
}
}
if (value != null)
if (UIComponentTag.isValueReference(value))
aUICustomSelectOneRadio.setValueBinding("value",
getValueBinding(value));
else
aUICustomSelectOneRadio.getAttributes().put("value", value);
if (styleClass != null)
if (UIComponentTag.isValueReference(styleClass))
aUICustomSelectOneRadio.setValueBinding("styleClass",
getValueBinding(styleClass));
else
aUICustomSelectOneRadio.getAttributes().put("styleClass",
styleClass);
if (style != null)
if (UIComponentTag.isValueReference(style))
aUICustomSelectOneRadio.setValueBinding("style",
getValueBinding(style));
else
aUICustomSelectOneRadio.getAttributes().put("style", style);
if (disabled != null)
if (UIComponentTag.isValueReference(disabled))
aUICustomSelectOneRadio.setValueBinding("disabled",
getValueBinding(disabled));
else
aUICustomSelectOneRadio.getAttributes().put("disabled",
disabled);
if (itemLabel != null)
if (UIComponentTag.isValueReference(itemLabel)) {
aUICustomSelectOneRadio.setValueBinding("itemLabel",
getValueBinding(itemLabel));
} else {
System.out.println("itemLabel=" + itemLabel);
aUICustomSelectOneRadio.getAttributes().put("itemLabel",
itemLabel);
}
if (itemValue != null)
if (UIComponentTag.isValueReference(itemValue))
aUICustomSelectOneRadio.setValueBinding("itemValue",
getValueBinding(itemValue));
else
aUICustomSelectOneRadio.getAttributes().put("itemValue",
itemValue);
if (onClick != null)
if (UIComponentTag.isValueReference(onClick))
aUICustomSelectOneRadio.setValueBinding("onClick",
getValueBinding(onClick));
else
aUICustomSelectOneRadio.getAttributes().put("onClick", onClick);
if (onMouseOver != null)
if (UIComponentTag.isValueReference(onMouseOver))
aUICustomSelectOneRadio.setValueBinding("onMouseOver",
getValueBinding(onMouseOver));
else
aUICustomSelectOneRadio.getAttributes().put("onMouseOver",
onMouseOver);
if (onMouseOut != null)
if (UIComponentTag.isValueReference(onMouseOut))
aUICustomSelectOneRadio.setValueBinding("onMouseOut",
getValueBinding(onMouseOut));
else
aUICustomSelectOneRadio.getAttributes().put("onMouseOut",
onMouseOut);
if (onFocus != null)
if (UIComponentTag.isValueReference(onFocus))
aUICustomSelectOneRadio.setValueBinding("onFocus",
getValueBinding(onFocus));
else
aUICustomSelectOneRadio.getAttributes().put("onFocus", onFocus);
if (onBlur != null)
if (UIComponentTag.isValueReference(onBlur))
aUICustomSelectOneRadio.setValueBinding("onBlur",
getValueBinding(onBlur));
else
aUICustomSelectOneRadio.getAttributes().put("onBlur", onBlur);
if (overrideName != null)
if (UIComponentTag.isValueReference(overrideName))
aUICustomSelectOneRadio.setValueBinding("overrideName",
getValueBinding(overrideName));
else
aUICustomSelectOneRadio.getAttributes().put("overrideName",
overrideName);
}

public ValueBinding getValueBinding(String valueRef) {
ApplicationFactory af = (ApplicationFactory) FactoryFinder
.getFactory("javax.faces.application.ApplicationFactory");
Application a = af.getApplication();
return a.createValueBinding(valueRef);
}

private String name;
private String value;
private String styleClass;
private String style;
private String disabled;
private String itemLabel;
private String itemValue;
private String onClick;
private String onMouseOver;
private String onMouseOut;
private String onFocus;
private String onBlur;
private String overrideName;

@Override
public String getComponentType() {
return "component.CustomSelectOneRadio";
}

@Override
public String getRendererType() {
return "renderer.CustomSelectOneRadio";
}
}

2. mysample.tldファイルです。
/WEB-INF/tldに置いてください。
<?xml version="1.0" encoding="UTF-8" ?>

<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib>
<!-- ============== Tag Library Description Elements ============= -->
<tlib-version>0.03</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>Custom JavaServerFaces Framework Tag Library</short-name>
<uri>http://www.srijeeb.com/jsf/tags-html</uri>
<tag>
<name>radioButton</name>
<tag-class>test.ctg.HTMLCustomSelectOneRadioTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>name</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>overrideName</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>value</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>styleClass</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>style</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>disabled</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>rendered</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>Boolean</type>
</attribute>
<attribute>
<name>itemLabel</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>itemValue</name>
<required>true</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>onClick</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>onMouseOver</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>onMouseOut</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>onFocus</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
<attribute>
<name>onBlur</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
<type>String</type>
</attribute>
</tag>
</taglib>

重要:TLDファイルをMySampleCTG/src/META-INF配下に置いたらうまく動きませんでした。web.xmlとかJSPをいろいろいじってみたのですがダメでした。

エラー例)
com.ibm.ws.jsp.inputsource.JspInputSourceImpl JspInputSourceImpl Failed to create inputsource contextURL =[file:/C:/Documents and Settings/user_name/IBM/rationalsdp/workspace/MySampleJSF/WebContent/ relativeURL =[http://www.srijeeb.com/jsf/tags-html]
java.net.MalformedURLException
at java.net.URL.<init>(URL.java:601)
...

おそらくそれと関連してると思われるのですが、WASテスト環境の調子も悪くなりました。
[08/11/27 13:14:21:000 JST] 0000001e annotations E ArchiveInputStreamData iterate unable to open file iterator
java.util.zip.ZipException: ZipFile closed
...のようなエラーが毎回出るようになった・WASの「公開」プロセスが0%のまま進まない、など。

ユーティリティプロジェクトは動作が怪しいですね。はっきり言って使わないほうがいいと思います。(昔のWSADでも動作が怪しかった記憶があります)
重要:ClassNotFoundエラーが出たら、MySampleCTGフォルダを右クリック Java EE > EARライブラリの更新 をしたら直ることがあります。MySampleCTG配下を編集したら「EARライブラリの更新」を実行するようにしましょう。

3. faces-config.xmlにコンポーネント要素を追加します。
以下の要素を追加してください。
 <component>
<component-type>component.CustomSelectOneRadio</component-type>
<component-class>test.ctg.UICustomSelectOneRadio
</component-class>
<component-extension>
<component-family>CustomSelectOneRadio</component-family>
<renderer-type>renderer.CustomSelectOneRadio</renderer-type>
</component-extension>
</component>
<render-kit>
<renderer>
<component-family>CustomSelectOneRadio</component-family>
<renderer-type>renderer.CustomSelectOneRadio</renderer-type>
<renderer-class>test.ctg.HTMLCustomSelectOneRadioRenderer
</renderer-class>
</renderer>
</render-kit>

4. jspにタグを書きます。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<%@ taglib uri="/WEB-INF/tld/mysample.tld" prefix="custom"%>
<html>
<head>
<title>list</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
<h2>リスト MySample</h2>
<f:view>
<h:dataTable value="#{listBean.mySamples}" var="item" border="1">
<h:column>
<f:facet name="header">
<h:outputText value="Select" />
</f:facet>
<custom:radioButton id="myRadioId1" name="myRadioCol"
overrideName="true" value="#{item.myid}"
itemValue="#{item.myid}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="ID" />
</f:facet>
<f:verbatim>id: </f:verbatim>
<h:outputText value="#{item.myid}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="VAL" />
</f:facet>
<f:verbatim>value: </f:verbatim>
<h:outputText value="#{item.myFlag}" />
</h:column>
</h:dataTable>
</f:view>
</body>
</html>s

以上です。表示だけはできるようになったはず。
(やれやれ。何で標準機能にしないんだろう・・・)

次回、radioボタンで送信されたデータを取得します。
.

2008年11月27日木曜日

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(9)

今度はテーブルの内容を一覧表示します。

■EJB(MySampleSession)に一覧(java.util.List)を取得するメソッドを追加します。
    // List<MySample>のwarningを抑止しています。それ以外は来ないはずなので。
@SuppressWarnings("unchecked")
public List<MySample> listMySamples() throws MySampleException {
Query query = em.createQuery("select m from MySample m");
List<MySample> result = query.getResultList();
return result;

}

■Webプロジェクト(MySampleJSF)に、新規にListBeanを追加します。
package test.beans;

import java.util.List;

import javax.ejb.EJB;

import test.MySample;
import test.MySampleSessionLocal;

public class ListBean {
private static final long serialVersionUID = 1L;
/*
* JPA直は好きじゃないのですが今回はこれで。
*/
List<MySample> mySamples = null;

@EJB(name="MySample")
private MySampleSessionLocal mySampleSession;

public List<MySample> getMySamples() {
// nullチェックでは厳密にインスタンスの生成を制御できませんが、
// まあ二回くらい呼ばれたっていいでしょう
if (mySamples == null) {
try {
List<MySample> tmpList = mySampleSession.listMySamples();
setMySamples(tmpList);
} catch (Exception e) {
//
}
}
return mySamples;
}

private void setMySamples(List<MySample> mySamples) {
this.mySamples = mySamples;
}
}

■faces-config.xmlにmanagedBean要素を追加します。
  <managed-bean>
<managed-bean-name>listBean</managed-bean-name>
<managed-bean-class>test.beans.ListBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>

■list.jspを新規に作成します。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %><html>
<head>
<title>list</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
<h2>リスト MySample</h2>
<f:view>
<h:dataTable value="#{listBean.mySamples}" var="item" border="1">
<h:column>
<f:verbatim>id: </f:verbatim>
<h:outputText value="#{item.myid}"/>
</h:column>
<h:column>
<f:verbatim>value: </f:verbatim>
<h:outputText value="#{item.myFlag}"/>
</h:column>
</h:dataTable>
</f:view>
</body>
</html>

今度は一覧表示にラジオボタンを追加したいのですが、これが大変なのです(<h:dataTable ..>と<h:selectOneMenu...>は入れ子にできないため・・・)。次回以降で挑戦してみます。

以上
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(8)

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(8)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)
(前回)
10. EJBに削除メソッドを作成する
11. JSFを作成(削除)
(今回はここまで)
12. 未定。テーブルの内容の一覧表示とか

後は似たようなものです。どんどん行きます。

10. EJBに削除メソッドを作成する

■MySampleSessionにロジックを追加します。
    public void deleteMySample(int myid) throws MySampleException {
MySample target = this.findMySample(myid);
if (target == null) {
throw new MySampleException();
}
em.remove(target);
em.flush();
}

以上。UTCなどで動作確認することもできます。

11. JSFを作成(削除)

■MySampleBeanにロジックを追加します。
    public void deleteMySample(int myid) throws MySampleException {
MySample target = this.findMySample(myid);
if (target == null) {
throw new MySampleException();
}
em.remove(target);
em.flush();
}

JSPは全てこれまでのものを流用します。
■success.jspに削除ボタンを追加します。
Found bean.<br>
id -> ${ mySampleBean.id } <h:inputHidden value="#{mySampleBean.id}"/>
value -> <h:inputText value="#{mySampleBean.value}"/>
<br>
<h:commandButton value="更新"
action="#{mySampleBean.updateValue}" />
<h:commandButton value="削除"
action="#{mySampleBean.deleteValue}" />

■faces-config.xmlを編集します(削除が成功したら検索画面に戻ります)。
  <navigation-rule>
<from-view-id>success.jsp</from-view-id>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/WEB-INF/results/success3.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>del_failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>del_success</from-outcome>
<to-view-id>/search.jsp</to-view-id>
</navigation-case>
</navigation-rule>

以上。
.

2008年11月26日水曜日

痛恨の片思い

一方的に仲良くしたい、親しみたいと思っていろいろアプローチしても、どうも相手のほうはその気になってくれないというか、うまく行かないということはよくありますが、私の場合、そのお相手は豚バラブロックの大きなかたまり肉でした。

昔からどうもこのほとんど脂身じゃねーかコノー、という巨大なかたまりに対しては、憎しみと共に愛情、あるいはほのかな憧れを抱いていたのです。憎たらしい脂身だけれども、いったいどうやったらこれを美味しく頂けるんだろう。スーパーでカナダ産やアメリカ産の豚バラブロック肉を見るにつけ、なんだか挑発されているような煽られているような気がしてならなかったのです。

妻は飽和脂肪酸とか動物性油脂や加工油脂とかを嫌がるので、ブロックだろうが薄切りだろうが豚バラ肉を嫌います。実は私だって脂身はさほど好きではない。豚ならバラよりヒレ肉。鳥ならモモ肉よりもムネやささみを好むほうです。しかしどうにもこの白い脂のかたまりは、私の本能を突き動かしてしょうがない。DNAレベルで揺さぶられている気すらしてしまう。

一部で話題の飽和脂肪酸。体によくないらしいけれども、沖縄では皮付きの豚ばら肉を泡盛で煮込んで黒糖としょうゆで煮付け、美味しい角煮を作っているらしい。つまり、沖縄では豚バラの角煮が食べられている。しかるに沖縄は長寿で有名である。すなわち豚バラの角煮を食べているにも関わらず、沖縄の人は長生きする。つまり、角煮を食べてもそれほど体に悪いことはないかしんない、という三段論法がここに成立するわけです。

昔テレビでやっていた「どっちの料理ショー」でも、よく肉からタラーリタラリと垂れる脂を見て歓声が上がっていたような気がします。しかも脂をたっぷり口に含んで「ジューシーで美味しい!」とか「甘~い」とか。脂舐めてうまいとは何ごとであるか、と半分怒りながらも見ていた私でしたが、豚ばら肉のレシピを見ると「最初にしっかり焼いて余分な脂を落とす」とか「酒を入れたお湯でしっかり茹でてから調理する」という記載があり「余分な脂が抜けて*サッパリした*美味しい豚バラの角煮」というものが存在しているかのように信じてしまい、いつかはそのような角煮を作って見たいものだ、などと考えていました。

で、一度作ってみたんですよ。もうしばらく昔になりますけど。しっかり焼いて脂も落としたし(60%くらいの大きさに縮まった)、味つけする前にお湯で1時間以上茹でたりもしました。でも、結果はやっぱり豚の脂。脂は脂。冷えるとにっちゃり。確かに美味しかったですけどね。でもニチャニチャ。

これに懲りてしばらくこの人には手を出さなかったんですが、またこの間また挑戦してみたのです。塩豚に。しかも塩豚を燻製にして自家製ベーコン を作ってみようと。よりによってというかアチャーという行為ですが、片思いから逃れられない私。恋は盲目です。

結論から言いますと、これが大失敗。いや、多分料理としては正当な手順でそこそこ正当な結果が得られたと思うんですが、その出来上がったものがまさに煙で燻されたしょっぱい豚脂。もう一口で勘弁って感じでした。頑張って半分ほど使いましたが、一週間ほど経過して消費できなかった残りは迷わずゴミ箱へダンクシュート。普段は食べ物を捨てるなんてことはしないんですよ。賞味期限+1、2日経過のものは平気だし、ものによっては味噌や塩に漬け込んで延命を図り、ちゃんと消費する性格です。食べ物は粗末にしたくない。でも塩豚の燻製はアウトでしたね。もう二度と作らない。

というわけで、ようやく豚バラの呪いから開放されたと思った私ですが、この前、業務用スーパーで巨大な豚バラかたまり肉(2,3kgもあろうかというやつ)を見かけて瞳孔を拡張しながら足を止めてしまいました。なんて懲りない私でしょうか。もう二度と自分で買うことはないでしょう。ないと思います。しかし、この豚バラのかたまりは、当分の間私を悩ませ続けるに違いない。巨大な生白いエロティックな脂肪の塊から目を離すことができないまま、私はそのように思ったのであります。

以上。
.

2008年11月25日火曜日

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(7)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
8. EJBに更新メソッドを作成する
(前回)
9. JSFを作成(更新)
(今回はここまで)
10. EJBに削除メソッドを作成する
11. JSFを作成(削除)

9. JSFを作成(更新)

JSFに更新ページを作成します。

■MySampleBeanにロジックを追加します。
 public String updateValue() {
try {
mySampleSession.updateMySample(id, value);
} catch(Exception e) {
return "failure";
}
return "success";
}

これだけ。

■次はJSP。
以前に作った検索(search.jsp)、結果表示ページ(/WEB-INF/results/success.jsp)を再利用します。

まず旧結果表示ページを/WEB-INF以外の場所に移動し、編集します。
なぜ移動するか。
以前に紹介したチュートリアルのPage-Navigation-1.pdfに以下の記述がありました。
Strategies
- You cannot put input-form JSP pages in WEB-INF
- Because URL must correspond directly to file location

そのまんまですね。この人はJSFの欠陥だ、と言い切ってます。私もそう思うな。

idはそのまま表示し(hidden要素に入れておく)、valueはテキストボックスに表示します。
Found bean.<br>
id -> ${ mySampleBean.id } <h:inputHidden value="#{mySampleBean.id}"/>
value -> <h:inputText value="#{mySampleBean.value}"/><br>
<h:commandButton value="更新"
action="#{mySampleBean.updateValue}" />

こんな感じで。

次に新しい方の結果表示ページ(更新結果を表示するページ)を作成します。
/WEB-INF/results/success3.jspとします。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Updated bean.<br>
id -> ${ mySampleBean.id }
value -> ${ mySampleBean.value }
</body>
</html>

次にfaces-config.xmlです。以下のタグを適切な場所に追加します。
  <navigation-rule>
<!-- この success.jsp が /WEB-INF/results の下にあるとダメな分けです -->
<from-view-id>success.jsp</from-view-id>
<navigation-case>
<from-outcome>failure</from-outcome>
<to-view-id>/WEB-INF/results/failure.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success</from-outcome>
<to-view-id>/WEB-INF/results/success3.jsp</to-view-id>
</navigation-case>
</navigation-rule>

以上。
.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(6)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
7. JSFを作成(挿入)
(前回)
8. EJBに更新メソッドを作成する
(今回はここまで)
9. JSFを作成(更新)
10. EJBに削除メソッドを作成する
11. JSFを作成(削除)

8. EJBに更新メソッドを作成する

EJBに更新メソッドを作成します。

以下のメソッドをMySampleSession セッションBeanに追加します。
 public void updateMySample(int myid, String value) throws MySampleException {
if (value.length() > 1) {
throw new MySampleException();
}
MySample target = (MySample)em.find(MySample.class, myid);
if (target == null) {
throw new MySampleException();
}
target.setMyFlag(value);
em.persist(target);
em.flush();
}

アウトラインでupdateMySampleメソッドを右クリックし、Java EE ツール > メソッドのプロモート を実行します。(忘れがちなので注意しましょう)

これでUTCからテストが出来ます(テスト方法このシリーズで何度か書いたので割愛します)。ちゃんと動くか確認してみて下さい。(サクサク行きますねえ)
.

プリキュア映画版は面白かった

やはり面白いですね。映画版プリキュア。普段は地味な主役もちゃんと活躍してたし。カッコよかったぜ、ていい歳ぶっこいて何言ってんだ、という照れもありつつも。

やはりおっさんが若い女子の活躍する熱血青春アニメを面白がるというのも恥ずかしいもんで、そこは勘弁して頂きたい。

しかし、今回は結構感情移入して見て楽しかったですよ。これまでは「よく出来ている」「面白い」とは思いつつも、客観的スタンスを崩していなかったのが、映画では結構引き込まれた。どうしてかな。悪役がどっかマヌけなモチベーションを持っていたのが良かったと思うな。

まあ、小さい子供を持つお父さんもぜひ一緒に楽しんできてください。面白いから。多分ね。

.

RAD v7.5 試用版 を使ってJSFとEJB3.0・・・(5)

手順

1. サンプルDBを作成
2. DBをWAS v7のデータソースに登録
3. JPAプロジェクトを作成
4. EJBを作成(findメソッドのみ)
5. JSFを作成
6. EJBに挿入メソッドを作成する
(前回)
7. JSFを作成(挿入)
(今回はここまで)
8. EJBに更新メソッドを作成する
9. JSFを作成(更新)

7. JSFを作成(挿入)

挿入を受け付けるJSF画面を追加します。(行き当たりばったりの画面設計・・・)

JSFの観点から言えばNothing Specialです。淡々と行きます。

■insert.jsp
<%@page language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h"%>
<f:view>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>挿入</title>
<meta http-equiv="Content-Type"
content="text/html; charset=windows-31j">
</head>
<body>
<CENTER>
<h2>挿入</h2>
<h:form>
myid:
<h:inputText value="#{mySampleBean.id}" />
value:
<h:inputText value="#{mySampleBean.value}" />
<h:commandButton value="挿入"
action="#{mySampleBean.insertValue}" />
</h:form>
</CENTER>
</body>
</html>
</f:view>

■/WEB-INF/result/failure2.jsp(重複キーエラーの時に表示させます)
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Duplicate key exists. Could not insert.
</body>
</html>

■/WEB-INF/results/failure2-1.jsp(その他のシステムエラー用です。UTできませんが念のため)

/WEB-INF/result.failure2.jspの"Duplicate key exists. Could not insert."を"System error"に変えるだけ

■/WEB-INF/reusults/success2.jsp
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><%@page
language="java" contentType="text/html; charset=windows-31j"
pageEncoding="windows-31j"%>
<html>
<head>
<title>exists</title>
<meta http-equiv="Content-Type" content="text/html; charset=windows-31j">
</head>
<body>
Inserted bean.<br>
id -> ${ mySampleBean.id }
value -> ${ mySampleBean.value }
</body>
</html>

■faces-config.xml
以下を追加
  <navigation-rule>
<from-view-id>/insert.jsp</from-view-id>
<navigation-case>
<from-outcome>failure2</from-outcome>
<to-view-id>/WEB-INF/results/failure2.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>failure2-1</from-outcome>
<to-view-id>/WEB-INF/results/failure2-1.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>success2</from-outcome>
<to-view-id>/WEB-INF/results/success2.jsp</to-view-id>
</navigation-case>
</navigation-rule>

■MySampleBeanに太字部分を追加
package test.beans;

import java.io.Serializable;

import javax.ejb.EJB;

import test.MySample;
import test.MySampleException;
import test.MySampleSessionLocal;

public class MySampleBean implements Serializable {

private static final long serialVersionUID = 1L;

int id;
String value;

@EJB(name="MySample")
private MySampleSessionLocal mySampleSession;

public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}

public String checkInput() {
MySample ms = mySampleSession.findMySample(id);
if (ms != null) {
this.setValue(ms.getMyFlag());
return "success";
} else {
return "failure";
}
}

public String insertValue() {
try {
mySampleSession.addMySample(id, value);
} catch(MySampleException mse) {
return "failure2";
} catch(Exception e) {
return "failure2-1";
}
return "success2";
}
}

以上です。いや、簡単ですね。
.