私のコードベースの古き良き時代には、イベントの再キューイングにかなり依存していました。これは、標準で指定された動作ではなく、ICEfacesまたはMyFacesの実装の詳細が原因で機能したと思われます。私たちが頻繁に行っていたのは、この種のことでした。
<ice:inputText value="#{bb.frequency}" valueChangeListener="#{bb.valueChanged}"/>
目標は、頻度が変わるたびretune
に呼び出されるように手配することです。setFrequency
次に、イベントを再キューイングするかなり嫌なコードがバッキングBeanに含まれていました。通常は次のようになります。
class BB {
// this happens first, thanks to UPDATE_MODEL_VALUES
public void setFrequency(Frequency f) {
this.model.f = f;
}
public void valueChanged(ValueChangeEvent event) {
if (event.getOldValue().equals(event.getNewValue())
return; // nothing changed, so leave
if (FacesContext.getCurrentInstance().getPhaseId() != INVOKE_APPLICATION) {
OurMagicEventUtils.requeueEvent(event, INVOKE_APPLICATION);
}
else {
// do the post-setter work here (the setter happened recently during
// UPDATE_MODEL_VALUES so we're up-to-date by here
this.model.retune();
}
}
}
これは生きるのに良い方法ではありません。後のフェーズでイベントを再キューイングするための信頼できる方法を見つけられませんでした。それは明らかに、人々が行うようなことではありません。私は2つの解決策を見ます:
リチューンインテリジェンスを
BB#setFrequency
メソッドに移動します。私は下位レベルのモデルクラスに直接対応しており、他のクライアントの動作を妨げたくないため、多くの場合、これを回避することはできません。
カスタムコンポーネントを作成し、ロジックを
setFoo
そこのメソッドに移動します。他のコンテナに埋め込むと、Mojarraやカスタムコンポーネントに多くの問題があるため、これは好きではありません。また、私がしなければならないことにはやり過ぎのようです。文字通り、
retune
いくつかのプロパティを設定した後に呼び出す必要があります。すべてのバッキングBeanを作成します。ほとんどのメソッドを直接内部に委任しますが
setFoo
、そこで再調整をキャッチして実行します。これは私たちが以前行っていたものと非常に似ており、ボイラープレート、ラッパー、グルーコードがたくさんあることを意味するので、私はそれが好きではありません。
私の頭の中で私はこのようなものを想像します:
<ice:inputText value="#{bb.frequency}" afterChange=#{bb.retune}"/>
しかし、それは明らかに機能しません。また<f:actionListener>
、クラス名が必要ですが、現在行っていることとは関連付けられていないため、アタッチすることもできません。さらに、そうでないものにのみ設定できUICommand
ますUIInput
。
このジレンマを解決するためのエレガントで正しい方法は何ですか?