[英]Custom JSF component renderer: how to render HTML around another element
[英]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,但我認為您必須為此解決問題。 您是否嘗試過在映射中將數字視為布爾值?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.