2010-05-04 29 views
0

我们在我们的数据库中有数值,表示一个两值状态。当然这会完全匹配一个布尔值,但是oracle没有这样的数据类型。数据库中的NUMBER(1,0)类型与Java中的java.lang.Short类型相匹配(有时它们使用NUMBER(*,0)表示布尔值,它们与java.math.BigDecimal匹配)。如何在JSF中注册自定义渲染器?

由于它在某种程度上是显而易见的,我想提供ice:视图中的selectBooleanCheckbox作为值表示,UIComponent提供给用户。 (我使用IceFaces作为JSF实现)

由于一些指定JSF的人认为总是匹配ice的值:selectBooleanCheckbox或在JSF中h:selectBooleanCheckbox为模型中的布尔值,所以渲染器组件永远不会调用任何转换器,即使你指定一个: Issue disscused at 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中使用)和正确的渲染器类型。

因为这个,我不想编辑完整的模型。任何提示,如何解决这个问题?

回答

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:肯定有更聪明的方法来实现这些信息,但我不够聪明。 ;-)

+0

我正在运行Mojarra 2.0.2,无法从我的类路径中找到'FacesConfigurator'。这是ICEFaces唯一的课程吗? – 2011-01-05 14:10:34

0

你不会说你是否使用Hibernate,但我认为你必须是这个问题。你有没有尝试在你的映射中将数字视为布尔值?

看到这个thread from the Hibernate forums

+0

嗨, thx为提示,但不,我们使用Ibator Ibatis进行数据映射。我不知道如何在hibernate(我喜欢使用!)中执行相同的映射。 – bl4ckb0l7 2010-05-04 08:57:20

相关问题