【问题标题】:Conversion Error setting value "UserID" for 'null Converter''null Converter' 的转换错误设置值“UserID”
【发布时间】:2012-10-31 09:06:52
【问题描述】:

尝试从我的应用程序的表中删除或编辑用户时出现转换错误。该值正在元数据中从listUser.xhmtl 传递到deleteUser.xhtml 页面。该值正在元数据中传递,但由于某种原因,在调用删除操作时,我得到了Conversion Error setting value "someemail@somedomain.com" for 'null Converter'。用户 id 是一个字符串。

这是请求userDelete.xhmtl后的url:

http://localhost:8080/lavpWebApp/user/deleteUser.xhtml?user=someemail%40somedomain.com

这是 userList.xhmtl 的简化版:

<h:column>
                            <f:facet name="header">Edit</f:facet>
                            <h:link outcome="/user/editUser.xhtml" value="Edit User">
                                <f:param name="user" value="#{item.email}"/>
                            </h:link>                            
                        </h:column>

                        <h:column>
                            <f:facet name="header">Delete</f:facet>
                            <h:link outcome="/user/deleteUser.xhtml" value="Delete User">
                                <f:param name="user" value="#{item.email}"/>
                            </h:link>
                        </h:column>

这是 userDelete.xhtml 的简化版:

<f:metadata>
        <f:viewParam name="user" value="#{userController.user}" converter="#{userConverter}"/>
    </f:metadata>

    <h:body>
        Do you want to delete #{userController.user.name}?
        <h:form>
            <h:commandButton action="#{userController.deleteUser()}"
                             value="Delete"/>
            <h:commandButton action="#{userController.doCancelDeleteUser()}"
                             value ="Cancel"/>
        </h:form>
    </h:body>

这是转换器类:

@ManagedBean
@FacesConverter(value="userConverter")
public class UserConverter implements Converter{

    @EJB
    private UserSellerEJB userEjb;

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null || value.isEmpty())
        {
            return null;
        }
        if(!value.matches("\\d+"))
        {
            throw new ConverterException("The value is not a valid email: " + value);
        }

        String id = value.toString();
        return userEjb.findUserById(id);

    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        if(value == null)
        {
            return null;
        }

        if(!(value instanceof UserSeller))
        {
            throw new ConverterException("The value is not a User: " + value);            
        }

        String id = ((UserSeller) value).getEmail();
        return (id != null) ? id.toString() : null;
    }

}

这是 userController 类的简化:

@Named
@RequestScoped
public class UserController{

    @EJB
    private UserSellerEJB userEJB;

    private UserSeller user = new UserSeller(); 
    private List<UserSeller> usersList = new ArrayList<UserSeller>();

    // ------------------------------------------------------------- Constructor
    public UserController() {
    }

    // -------------------------------------------------------- Business Methods

    public String doCreateUser()
    {
        user = userEJB.createSeller(user);
        usersList = userEJB.findAllSellers();
        return "listUser?faces-redirect=true";        
    }

        // update user

        public void PreRenderView()
        {
            if(user == null)
            {
                user = new UserSeller();
            }            
        }

        public String doUpdateUser()
        {
            if(user.getEmail() != null)
            {
                userEJB.updateSeller(user);
            }
            else
            {
                userEJB.createSeller(user);
            }

            return "listUser?faces-redirect=true";
        }

    public String deleteUser()
    {
        userEJB.deleteSeller(user);
        return "listUser?faces-redirect=true";
    }

    public String doCancelDeleteUser()
    {
        return "listUser?faces-redirect=true";
    }


    @PostConstruct
    public void init()
    {
        usersList = userEJB.findAllSellers();       
    }

【问题讨论】:

  • 尝试将name 分配给@ManagedBean 注释并使用它来访问转换器。确保它与您在@FacesConverter中使用的不同
  • @ManagedBean 不能有 @FacesConverter 注释。删除 @ManagedBean 注释,代码将起作用。顺便说一句,您将 JSF 与 CDI 混合使用,最好同时研究两者及其差异。相关:Inject a EJB into a JSF converter with JEE6.
  • @kolossus 谢谢。我已将name 添加到@ManagedBean,我使用了@ManagedBean(name="userSellerConverter"),但它仍然给出相同的错误。
  • @LuiggiMendoza,这不准确。转换器也可以用@ManagedBean 注释。我知道,因为我已经做过好几次了。这是转换器可以访问@Inject 类型资源的唯一方式
  • 从技术上讲,Luiggi 是正确的,@ManagedBean 不能有 @FacesConverter 注释。通常是两者之一,而不是两者。

标签: jsf jakarta-ee metadata javabeans converter


【解决方案1】:

异常消息中的null converter 表示找不到转换器实例。由于您通过converter="#{userConverter} 将转换器引用为托管bean,因此只有在使用@javax.faces.bean.ManagedBean 注释并且该类位于WAR 中(因此不在EJB/EAR 或其他地方!)时才能找到它.

@FacesConverter 注释没有用在这个结构中,实际上是多余的——只会让初学者感到困惑。删除该注释。 @EJB 确实只在托管 bean 中有效。

如果真的徒劳无功(但我无法解释原因),请尝试通过 CDI 来管理它:将 JSF @ManagedBean 注释替换为 CDI @Named 注释。您显然已经通过 CDI 成功管理了前端控制器 bean。


与具体问题无关,转换器似乎被设计为基于技术 ID(数据库主键)而不是电子邮件地址进行转换。电子邮件地址永远不能匹配\d+(这是“仅限数字”的正则表达式)。确保您没有将电子邮件地址与 ID 混淆。

【讨论】:

  • 非常感谢您的详细建议。我已按照您的指示删除了@FacesConverter 注释,我还将@ManagedBean 注释替换为@Named("userConverter")。我还删除了正则表达式条件。我使用电子邮件作为User 的 ID,这就是我使用电子邮件的原因。问题现已解决。非常感谢。
  • BalusC - 一个问题:我是 JSF 的新手,并且已经读过 @FacesConverter 是必需的,并且想完全理解为什么我需要在这种情况下删除它。您能否稍微解释一下为什么我们为此转换器删除了它? - 提前致谢。
  • 那是因为你想在其中注入一个@EJB。但是,@FacesConverter(和@FacesValidator)不是受支持的注入目标。这种疏忽在即将到来的 JSF 2.2 中得到修复。
  • 非常感谢,我知道了。
猜你喜欢
  • 2013-03-17
  • 1970-01-01
  • 2012-10-22
  • 2021-05-12
  • 1970-01-01
  • 2011-09-23
  • 2012-06-06
  • 2011-10-31
  • 2017-09-01
相关资源
最近更新 更多