簡體   English   中英

如何在JSF中注冊自定義渲染器?

[英]How to register a custom renderer in JSF?

我們的數據庫中有數值,代表兩個值的狀態。 當然,這將完全匹配布爾值,但是oracle沒有這種數據類型。 數據庫中的NUMBER(1,0)類型與Java中的java.lang.Short類型匹配(有時他們使用NUMBER(*,0)表示布爾值,它們與java.math.BigDecimal匹配)。

由於它以某種方式顯而易見,因此我想在視圖中提供ice:selectBooleanCheckbox作為值表示形式和UIComponent給用戶。 (我將IceFaces用作JSF實現)

由於某些指定了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);
 }

因此,這會導致IllegalArgumentException,因為在UpdateModelValues階段嘗試將布爾值應用於數值(請忽略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中查找了我使用的組件)和正確的渲染器類型。

因此,我不想編輯完整的模型。 有什么提示,如何解決?

我們可以解決問題並正確注冊我們的自定義渲染器。

問題在於為目標渲染器找到正確的屬性。 我們的嘗試是錯誤的,因為我發現了如何獲取適當的信息。 這需要一些工作和搜索,但最終成功了。

只需在調試模式下啟動容器,然后在類級別上將斷點添加到自定義渲染器所基於的派生類中(在我的情況下為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:當然,獲得此信息的方法更聰明,但我還不夠聰明。 ;-)

您沒有說您是否正在使用Hibernate,但我認為您必須為此解決問題。 您是否嘗試過在映射中將數字視為布爾值?

在Hibernate論壇中查看此主題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM