JSF:selectOneRadio转换器问题

JSF:selectOneRadio转换器问题,jsf,converter,Jsf,Converter,我在使用selectOneRadio组件时遇到问题。我在转换器的getAsString中得到一个NullPointerException。该异常在我看到该组件之前抛出 这就是它的样子: <h:selectOneRadio id="bookA" value="#{bookHandler.compareBookA}"> <f:converter converterId="bookConvert

我在使用selectOneRadio组件时遇到问题。我在转换器的getAsString中得到一个NullPointerException。该异常在我看到该组件之前抛出

这就是它的样子:

            <h:selectOneRadio id="bookA"
                value="#{bookHandler.compareBookA}">
                 <f:converter converterId="bookConverter" />
                <f:selectItems value="#{bookHandler.selectedBooks}"
                    var="book" itemLabel="#{book.shortname}" itemValue="#{book}" />
            </h:selectOneRadio>
我还覆盖了toString()

出于某种原因,如果我将组件更改为selectManyCheckbox(其余部分保持原样),则会呈现该组件

我将JSF2(MyFaces实现)与Tomcat上的Tomahawk一起使用

附加问题:为什么我首先需要一个转换器?如果我不使用转换器,组件将被渲染,但是我想将所选的书传递给某个动作方法,那么它就不会是一本书了

有什么想法吗? 谢谢

显然
{bookHandler.compareBookA}
只是
null

Book
null
时,不应该抛出
ConverterException
,而应该放手

return (book != null) ? book.getShortname() : null;

至于奖金问题,您需要转换器,因为HTML响应基本上是一个大字符串。所有Java对象都需要转换为字符串才能嵌入到HTML响应中。此外,HTTP请求参数默认为字符串。
request.getParameter()
返回
String
。HTML/HTTP完全不知道如何处理和传递完整的Java对象

另见:
显然
{bookHandler.compareBookA}
只是
null

Book
null
时,不应该抛出
ConverterException
,而应该放手

return (book != null) ? book.getShortname() : null;

至于奖金问题,您需要转换器,因为HTML响应基本上是一个大字符串。所有Java对象都需要转换为字符串才能嵌入到HTML响应中。此外,HTTP请求参数默认为字符串。
request.getParameter()
返回
String
。HTML/HTTP完全不知道如何处理和传递完整的Java对象

另见:

转换器提供一种机制,将POJO转换为字符串(HTML)表示形式,然后将该字符串转换回同一POJO的实例。在您的示例中,您不希望抛出异常,而只是在Book为null时返回null

我在应用程序中经常做的一件事是创建一个通用转换器,该转换器适用于我的所有selectItems。如果您的所有实体都实现了一个公共接口,例如id属性,那么这很容易

public interface Entity extends Serializable {

    /**
     * Return the primary key for this entity
     * 
     * @return id
     */
    public BigInteger getId();

}
然后,您可以创建一个约定,规定如何将所有实体转换为字符串并返回到对象。我通常连接类名和id,然后对它们进行Base64编码,以将对象转换为字符串,然后反转转换:

/*
 * (non-Javadoc)
 * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
 */
@SuppressWarnings("unchecked")
public Object getAsObject(FacesContext context, UIComponent component, String value) {

    Object objectValue = null;

    try {            
        BigInteger id = null;

        value = this.unhash(value);            
        String[] array = value.split(CLASS_KEY_SEPARATOR);

        if (array.length == 2) {
            id = new BigInteger(array[1]);
        }

        Collection<UIComponent> childComponents = component.getChildren();

        for (UIComponent childComponent : childComponents) {

            if (childComponent.getClass().equals(UISelectItems.class)) {

                Collection<Entity> values = 
                    (Collection<Entity>) childComponent.getValueExpression("value").getValue(FacesContext.getCurrentInstance().getELContext());

                for (Entity selectItemValue : values) {
                    if (id.equals(selectItemValue.getId())) {
                        return selectItemValue;
                    }
                }
            }
        }            

    } catch (Exception ex) {
        LOGGER.error(ex.getMessage(), ex);
    }

    return objectValue;
}
/*
*(非Javadoc)
*@see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.String)
*/
@抑制警告(“未选中”)
公共对象getAsObject(FacesContext上下文、UIComponent组件、字符串值){
objectValue=null;
试试{
BigInteger id=null;
value=this.unhash(值);
String[]数组=value.split(类\键\分隔符);
if(array.length==2){
id=新的BigInteger(数组[1]);
}
Collection childComponents=component.getChildren();
用于(UIComponent childComponent:childComponents){
if(childComponent.getClass().equals(UISelectItems.class)){
集合值=
(集合)childComponent.getValueExpression(“值”).getValue(FacesContext.getCurrentInstance().getELContext());
对于(实体selectItemValue:values){
if(id.equals(selectItemValue.getId())){
返回selectItemValue;
}
}
}
}            
}捕获(例外情况除外){
LOGGER.error(例如getMessage(),例如);
}
返回objectValue;
}

您的实体结构可能与我的不同,但如果您遵循基本模式,您的应用程序中的所有POJO都会使用一个转换器,该转换器表示为SelectItems。

转换器提供了一种机制,可以将POJO转换为字符串(HTML)表示,然后将该字符串转换回同一POJO的实例。在您的示例中,您不希望抛出异常,而只是在Book为null时返回null

我在应用程序中经常做的一件事是创建一个通用转换器,该转换器适用于我的所有selectItems。如果您的所有实体都实现了一个公共接口,例如id属性,那么这很容易

public interface Entity extends Serializable {

    /**
     * Return the primary key for this entity
     * 
     * @return id
     */
    public BigInteger getId();

}
然后,您可以创建一个约定,规定如何将所有实体转换为字符串并返回到对象。我通常连接类名和id,然后对它们进行Base64编码,以将对象转换为字符串,然后反转转换:

/*
 * (non-Javadoc)
 * @see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext, javax.faces.component.UIComponent, java.lang.String)
 */
@SuppressWarnings("unchecked")
public Object getAsObject(FacesContext context, UIComponent component, String value) {

    Object objectValue = null;

    try {            
        BigInteger id = null;

        value = this.unhash(value);            
        String[] array = value.split(CLASS_KEY_SEPARATOR);

        if (array.length == 2) {
            id = new BigInteger(array[1]);
        }

        Collection<UIComponent> childComponents = component.getChildren();

        for (UIComponent childComponent : childComponents) {

            if (childComponent.getClass().equals(UISelectItems.class)) {

                Collection<Entity> values = 
                    (Collection<Entity>) childComponent.getValueExpression("value").getValue(FacesContext.getCurrentInstance().getELContext());

                for (Entity selectItemValue : values) {
                    if (id.equals(selectItemValue.getId())) {
                        return selectItemValue;
                    }
                }
            }
        }            

    } catch (Exception ex) {
        LOGGER.error(ex.getMessage(), ex);
    }

    return objectValue;
}
/*
*(非Javadoc)
*@see javax.faces.convert.Converter#getAsObject(javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.String)
*/
@抑制警告(“未选中”)
公共对象getAsObject(FacesContext上下文、UIComponent组件、字符串值){
objectValue=null;
试试{
BigInteger id=null;
value=this.unhash(值);
String[]数组=value.split(类\键\分隔符);
if(array.length==2){
id=新的BigInteger(数组[1]);
}
Collection childComponents=component.getChildren();
用于(UIComponent childComponent:childComponents){
if(childComponent.getClass().equals(UISelectItems.class)){
集合值=
(集合)childComponent.getValueExpression(“值”).getValue(FacesContext.getCurrentInstance().getELContext());
对于(实体),请选择ItemValue