【问题标题】:JSF converter Validation Error: value is not valid for SelectOneMenu UIComponent [duplicate]JSF 转换器验证错误:值对 SelectOneMenu UIComponent 无效 [重复]
【发布时间】:2011-10-31 04:36:22
【问题描述】:

我在 requestScope 中使用 managedBean userHome,实体 'user' 将在其中持久存在。 用户具有映射在多对一关系中的领导列。我的代码如下所示

@ManagedBean
@RequestScoped
public class UserHome {
    private User user = new User();
        // Getters and Setters

    private List<SelectItem> selectItems = new ArrayList<SelectItem>();

    public UserHome() {
        for(User user: availableLeaders) {
            selectItems.add(new SelectItem(user.getName(), user));
        }
    }

    public void persis();
}

用户.java

public class User {
    @Id
    @Column
    private Integer id;

    @Column
    privat String name;

    @ManyToOne
    private User leader;
}

我想通过h:selectOneMenu这样的方式获取这位领导者的价值

<h:selectOneMenu value="#{userHome.user.leader}" converter="userConverter">
    <f:selectItems value="#{userHome.selectItems}"/>
</h:selectOneMenu>

我的转换器是这样的

@FacesConverter(forClass = User.class, value="userConverter")
public class UserConverter implements Converter {

    private  Map<String, User> userValues = new HashMap<String, User>();

    public UserConverter() {
        init();
    }

    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
            String value) {
        return userValues.get(value);
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        System.out.println("RAJASEKARAN "+value);
        return ((User)value).getName();
    }

    public void init() {
        UserHome userHome = new UserHome();
        for(User user:userHome.availableLeaders()) {
            userValues.put(user.getName(), user);
        }
    }
}

在尝试保存用户时,我收到错误 UserEdit:j_idt18: Validation Error: Value is not valid

【问题讨论】:

    标签: jsf jpa


    【解决方案1】:

    添加到 BalusC 的答案:在回发之后,您需要确保 User 实例与您用于呈现选择项的实例完全相同,或者您为 User 类实现 equals。

    代码没有显示availableLeaders 的来源,但如果这是从数据库按需获取的,那么转换器将不会转换为 JSF 通过@987654323 解析的列表中完全相同的对象实例@。

    转换后,JSF 将使用equals() 方法检查是否可以在该列表中找到转换后的实例。

    【讨论】:

    • 嗨,它在 mojarra 代码中的确切位置,这等于检查发生。我正在编写一个自定义组件,我遇到了这个问题,我想调试 mojarra 代码以查看发生了什么。谢谢
    • 这发生在UISelectMany#validateValue,而对equals的实际调用发生在SelectUtils#matchValue
    • 是的,经过大量调试,我能够弄清楚这一点,这是否认为不验证是一种不好的做法?我的自定义组件是从 UISelectOne 扩展而来的,而这个方法 validateValue 让我非常伤心,如果我用空内容覆盖这个方法,那么事情就会正常工作。但我有一种感觉,这是我不应该做的事情。有什么想法吗?
    • 不让它进行检查会使您面临类似的攻击,例如批量分配漏洞允许发生的攻击。 Github(见infoq.com/news/2012/03/GitHub-Compromised
    • 谢谢,经过一番思考,我想我对如何进行验证工作有了一个想法。感谢您的帮助。
    【解决方案2】:

    您以错误的方式构建了SelectItem。根据class' documentation,第一个参数应该代表项目值(要转换和提交),第二个参数应该代表项目标签(要显示在列表中)。但是你反过来指定了它们。

    相应地修复它:

    selectItems.add(new SelectItem(user, user.getName()));
    

    如果仍然不能解决问题,则意味着User 类的equals() 方法没有(正确)实现。 JSF 将使用它来验证所选的User 与转换后列表的任何项目值。


    与具体问题无关,了解 JSF2 中的 &lt;f:selectItems&gt; 为您提供了构建列表的可能性而无需手动构建 SelectItem 列表可能很有用。这是一个实现完全相同的示例:

    <f:selectItems value="#{userHome.availableLeaders}" var="user" 
        itemValue="#{user}" itemLabel="#{user.name}" />
    

    这允许您摆脱额外的selectItems 属性和 bean 构造函数中的循环。

    【讨论】:

    • +1 用于将 SelectItem 类型排除在支持 bean 之外并让它使用简单的域对象列表;)
    猜你喜欢
    • 2011-06-01
    • 2012-11-25
    • 2013-04-09
    • 2013-05-20
    • 2011-09-13
    • 2013-08-04
    • 2012-05-23
    • 2013-08-27
    相关资源
    最近更新 更多