JSFでカスタムレンダラーを登録する方法は?
-
02-10-2019 - |
質問
データベースには数値値があり、2価値状態を表しています。もちろん、これはブール値と完全に一致しますが、Oracleにはそのようなデータ型はありません。データベースからの数(1,0)タイプは、Java.lang.shortタイプに一致します(Java.math.bigdecimalに一致するブール付けを表すために数字(*、0)を使用した場合があります)。
それはどういうわけか、私はICEを提供したいです:selectbooleancheckboxは、ユーザーに値表現とuicomponentとしてビュー内のビューにあります。 (JSF実装としてアイスフェイスを使用しています)
JSFを指定した人の中には、氷の値を常に一致させることは明らかだと思う人の中には、selectbooleancheckboxまたはjsf h:selectbooleancheckboxにモデルのブール値に合わせて、コンポーネントのレンダラーがコンバーターを呼び出すことはありません。java.netで発行されます
したがって、私は次のことを試しました:
UIComponentで指定するコンバーターを作成しました。
public class BooleanBigDecimalConverter implements Converter {
public Object getAsObject(FacesContext context, UIComponent component, String str) {
if (StringUtils.isEmptyString(str)) {
return new BigDecimal(0);
}
if (str.equals("true")) {
return new BigDecimal(1);
} else {
return new BigDecimal(0);
}
}
public String getAsString(FacesContext context, UIComponent component, Object obj) {
if (obj != null) {
String str = obj.toString();
if (str.equalsIgnoreCase("1")
|| str.equalsIgnoreCase("yes")
|| str.equalsIgnoreCase("true")
|| str.equalsIgnoreCase("on")) {
return "true";
} else {
return "false";
}
}
return "false";
}
}
コンバーターはレンダリングフェーズ(getAsstring-methodは正しく呼ばれます)で正常に動作しますが、getasObject-method(とにかく呼ばれていないため、現時点では正しくないことを無視してください。 uicomponentのレンダラーでは、ここで見ることができるように、コンバーターが予見されていないため、呼び出されることはありません(com.icesoft.faces.renderkit.dom_html_basic.checkboxRendererからSnip)
public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue) throws ConverterException
{
if(!(submittedValue instanceof String))
throw new ConverterException("Expecting submittedValue to be String");
else
return Boolean.valueOf((String)submittedValue);
}
したがって、これにより、違法なメモン化が発生します。なぜなら、updatemodeluesフェーズでは、ブール値を数値に適用しようとするためです(大きな混乱/短い混乱を無視してください...それはいずれにしても数値タイプです!)。
それで、私はレンダラーをこのような新しいもので上書きしようとしました:
import com.icesoft.faces.component.ext.renderkit.CheckboxRenderer;
public class CustomHtmlSelectBooleanCheckbox extends CheckboxRenderer {
public Object getConvertedValue(FacesContext context, UIComponent component, Object submittedValue) throws ConverterException {
Converter converter = ((ValueHolder) component).getConverter();
return converter.getAsObject(context, component, (String) submittedValue);
}
}
そして、このようにfacesconfig.xmlに登録しました:
<render-kit>
<renderer>
<component-family>com.icesoft.faces.HtmlSelectBooleanCheckbox</component-family>
<renderer-type>com.icesoft.faces.Checkbox</renderer-type>
<renderer-class>com.myapp.web.util.CustomHtmlSelectBooleanCheckbox</renderer-class>
</renderer>
</render-kit>
これは正しいはずだと思いますが、オーバーライドされたメソッド「getConvertedValue」は決して呼び出されず、getasobject() - メソッドでもないので、カスタムレンダラーの登録に間違えたと思いますが、ドキュメントやこれ以上は見つかりません。これを適切に行う方法と、特に正しいコンポーネントファミリー(Icefaces.taglib.xmlで使用するコンポーネントを調べる)と正しいレンダラータイプを見つける方法をヒントします。
このため、完全なモデルを編集したくありません。ヒントはあり、これをどのように解決できるのでしょうか?
解決
問題を修正し、カスタムレンダラーを正しく登録できます。
問題は、意図したレンダラーの正しいプロパティを見つけることでした。適切な情報を取得する方法を見つけたので、私たちの試みは間違っていました。それはちょっとした作業と検索ですが、ついにトリックを行いました。
コンテナをデバッグモードで起動し、クラスレベルのブレークポイントを派生クラスに追加するだけです。カスタムレンダラーは(私の場合はcom.icesoft.faces.renderkit.dom_html_basic.checkboxRenderer)に基づいています。
コンテナの起動中、このブレークポイントに到達し、StacktraceにメソッドFACESCONFIGURATOR.CONFIGURERENDENDKITS()の呼び出しがあります。
このオブジェクトには、登録されたレンダラーの配列が含まれています。上書きしたいレンダラーのリストを検索し、カスタムレンダラーを登録するために必要な情報を見つけることができました。私の場合、これはfacesconfig.xmlの正しいエントリです:
<render-kit>
<description>The ICEsoft Renderers.</description>
<render-kit-id>ICEfacesRenderKit</render-kit-id>
<render-kit-class>com.icesoft.faces.renderkit.D2DRenderKit</render-kit-class>
<renderer>
<component-family>javax.faces.SelectBoolean</component-family>
<renderer-type>com.icesoft.faces.Checkbox</renderer-type>
<renderer-class>com.myapp.web.util.CustomHtmlSelectBooleanCheckbox</renderer-class>
</renderer>
</render-kit>
これで、getAsObject() - コンバーターのメソッドがカスタムレンダラーによって呼び出されます。すべてのselectbooleancheckboxオブジェクトにコンバーターを必要としない場合に備えて、メソッドを正しく上書きしてください。
public Object getConvertedValue(FacesContext context,
UIComponent component, Object submittedValue)
throws ConverterException {
Converter converter = ((ValueHolder) component).getConverter();
if (converter == null) {
if(!(submittedValue instanceof String))
throw new ConverterException("Expecting submittedValue to be String");
else
return Boolean.valueOf((String)submittedValue);
}
return converter.getAsObject(context, component,
(String) submittedValue);
}
それ以外の場合は、nullpointerexceptionを取得します。
PS:この情報を達成するためのより賢明な方法は確かにありますが、私は十分に賢くありません。 ;-)
他のヒント
冬眠を使用しているかどうかは言わないが、これが問題である必要があると思う。数値をマッピングのブール値として扱ってみましたか?
これを参照してください Hibernateフォーラムからのスレッド