0

データベースには、2 つの値の状態を表す数値があります。もちろん、これはブール値に完全に一致しますが、オラクルにはそのようなデータ型はありません。データベースの NUMBER(1,0) 型は、Java の java.lang.Short 型に一致します (Java.math.BigDecimal に一致するブール値を表すために NUMBER(*,0) を使用することもありました)。

なんとなく明らかなので、ビューで ice:selectBooleanCheckbox を値表現と UIComponent としてユーザーに提供したいと思います。(私はJSF実装としてIceFacesを使用しています)

JSF を指定した一部の人々は、常に ice: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 メソッドは正しく呼び出されます)、getAsObject メソッド (現時点では正しくないことは無視してください。とにかく呼び出されないため、呼び出されれば修正されます!)ここでわかるように、UIComponent のレンダラーではコンバーターが予見されないため、呼び出されませんでした (com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer から抜粋):

 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);
 }

そのため、UpdateModelValues フェーズではブール値を数値に適用しようとするため、IllegalArgumentException が発生します (BigDecimal/Short の混乱は無視してください... いずれにしても単なる数値型です!)。

そこで、次のような新しいレンダラーでレンダラーを上書きしようとしました。

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);  
   }
 }

そして、faces-config.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 で使用するものを調べました) と正しいレンダラー タイプを見つける方法を示します。

このため、完全なモデルを編集したくありません。ヒント、これをどのように解決できますか?

4

2 に答える 2

5

問題を修正し、カスタム レンダラーを正しく登録することができました。

問題は、目的のレンダラーの正しいプロパティを見つけることでした。適切な情報を取得する方法を見つけたので、私たちの試みは間違っていました。ちょっとした作業と検索ですが、最終的にうまくいきました。

コンテナをデバッグ モードで起動し、カスタム レンダラーのベースとなる派生クラス (私の場合は com.icesoft.faces.renderkit.dom_html_basic.CheckboxRenderer) にクラス レベルのブレークポイントを追加するだけです。

コンテナーの起動中にこのブレークポイントに到達し、スタックトレースで FacesConfigurator.configureRenderKits() メソッドの呼び出しを見つけることができます。

このオブジェクトには、登録済みレンダラーの ArrayList が含まれています。上書きしたいレンダラーのリストを検索したところ、カスタム レンダラーを登録するために必要な情報を見つけることができました。私の場合、これはfaces-config.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: 確かに、この情報を取得するためのよりスマートな方法はありますが、私は十分にスマートではありません。;-)

于 2010-05-04T09:49:47.793 に答える
0

Hibernateを使用しているかどうかはわかりませんが、これが問題になるには、Hibernateを使用している必要があると思います。マッピングで数値をブール値として扱ってみましたか?

Hibernateフォーラムからこのスレッドを参照してください

于 2010-05-04T08:40:25.037 に答える