【问题标题】:PropertyNotFoundException: Target Unreachable, 'userObj' returned null with jsf button and request scopePropertyNotFoundException:目标无法访问,“userObj”返回 null,带有 jsf 按钮和请求范围
【发布时间】:2011-12-10 00:56:54
【问题描述】:

情况如下,我有一个页面要添加/更新用户 在 prerender 方法中根据参数创建新对象或获取现有对象

@Component("user")
@Scope("request")
public class UserBean {


    private User userObj;
    private boolean editUser;


    public String addUser() throws Exception {

        if (editUser) {
            userService.updateUser(userObj);
        } else {
            userService.addUser(userObj);
        }
        return "users?faces-redirect=true";
    }

    public void preRender(ComponentSystemEvent event) throws Exception {

            System.out.println("############ PRERENDER #############");
            if (editUser) {
                userObj = userService.getUser(userID);
                pageTitle = "Updating " + userObj.getName();
                buttonTitle = "Save Changes";
            } else {
                userObj = new User();
                pageTitle = "Adding new user";
                buttonTitle = "Add User";

            }

        }

在 jsf 页面中,我将 prerender 称为:

<f:event id="event1" listener="#{user.preRender}" type="javax.faces.event.PreRenderComponentEvent" />

但是当我按下添加按钮时,如下所示:

<h:commandButton value="#{user.buttonTitle}" action="#{user.addUser}" style="width: 105px; "/> 

我遇到了异常,请指教。

【问题讨论】:

  • 我猜你的commandButton 正在向服务器创建一个新请求,这会导致 UserBean 创建一个新实例。因此userObj 为空。
  • @flash 有什么解决办法吗?
  • @Mika 当然,您应该考虑将范围从请求更改为会话。那将是最简单的解决方案。这对你来说不可行,还有其他解决方案。
  • 会话不是一个好的解决方案是的。
  • @Mika 您应该将范围临时设置为会话以确认这是问题所在。

标签: spring jsf jakarta-ee jsf-2


【解决方案1】:

问题是您的h:commandButton 正在向服务器创建一个新请求,这导致UserBeanRequest 范围内创建其自身的一个新实例。

我能想到几种解决方案。

1) 您似乎知道您的页面是否处于编辑模式。然后你可以摆脱你的preRender method,而是在调用userObj的getter时从数据库中获取userObj。然后,如果您的页面是否处于编辑模式,您可以传递给您的add method。因此,您必须修改您的commandButton:(注意:您必须将值更改为您当前的编辑模式)

  <h:commandButton value="#{user.buttonTitle}" action="#{user.addUser}" style="width: 105px; ">
      <f:setPropertyActionListener value="true" target="#{user.editUser}" />
  </h:commandButton>

和你的userBean

@Component("user")
@Scope("request")
public class UserBean {

private User userObj;
private boolean editUser;

public String addUser() throws Exception {
    userObj = getUserObj();
    if (editUser) {
        userService.updateUser(userObj);
    } else {
        userService.addUser(userObj);
    }
    return "users?faces-redirect=true";
}

public void setEditUser(boolean editUser) {
    this.editUser = editUser;
}

public User getUserObj() {
    if (editUser) {
        if(userObj == null) {
            userObj = userService.getUser(userID);
        }
        return userObj;
    } 
    else {
        return userObj = new User();
    }
}

public void setUserObj(User userObj) {
    this.userObj = userObj;
}

这应该让您对它的工作原理有一个基本的了解。诀窍是使用f:setPropertyActionListener

2) 您可以使用视图范围来解决该问题。问题是 spring 没有提供这个开箱即用的功能。好消息是您可以自己构建视图范围。看看那个blog post

【讨论】:

  • 好吧,第二个解决方案工作得很好,但我注意到终端上出现以下警告:WARNING: Setting non-serializable attribute value into ViewMap: (key: user, value class: com.myapp.beans.UserBean) 所以有什么想法吗?顺便说一句,你有没有像上面那样使用 JSF 2 和 spring 3 的好的示例/资源
  • @Mika 尝试让 UserBean 实现 Serializable 接口。
  • 但是我的 UserBean 自动装配其他 bean,例如我不想序列化的 dao 和服务 (singelteon),明白了吗?
  • @Mika 你不必太担心警告。详细解释请见stackoverflow.com/questions/3372687/…
猜你喜欢
  • 2011-04-14
  • 2013-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多