JSF 2:ViewScoped问题,重新显示同一页面时bean没有保留

ber*_*tie 4 jsf primefaces jsf-2

我知道为什么,但重新显示同一页面时,我的viewscoped-bean不会被持久化.我想知道这是否是因为使用了facelet模板?

以下是我帮助我解决问题的方法:

  1. 添加@PostConstruct方法并从那里进行调试
  2. 在setter和getter方法中添加一些调试
  3. ViewScoped调试似乎有很多PostConstruct方法调用
  4. 是的,状态不是持久的(提交,将标志设置为true,但重新显示标志时再次返回false)
  5. 尝试将范围更改为会话,在重新启动我的glassfish时出现错误"org.glassfish.deployment.common.DeploymentException:WELD-000072管理bean声明钝化范围必须具有钝化能力".不得不让我的bean序列化可以跳过这个错误.
  6. 在会话范围bean中,PostConstruct只调用一次,状态保持不变

我想知道我的ViewScope案例出了什么问题?

这是我的facelet文件:"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<h:head>
    <title>#{msgs.title}</title>
    <h:outputStylesheet library="css" name="main.css" />
</h:head>
<h:body>
    <ui:composition template="/template/masterlayout.xhtml">
        <ui:define name="windowTitle">Checkbox Lab</ui:define>
        <ui:define name="heading">Checkbox Lab</ui:define>
        <ui:define name="content">
            <h:form>
                <p:messages id="messages" globalOnly="true"/>
                <h:panelGrid columns="3" styleClass="bordered">
                    <h:outputLabel for="Married" value="Married" />
                    <h:selectBooleanCheckbox label="Married" id="Married" 
                         value="#{checkboxLabBean.married}" />
                    <p:message for="Married"/>

                    <p:panel header="debug info" id="debugPanel"
                        toggleable="true" toggleSpeed="300" >
                            <h:panelGrid columns="2">
                            <h:outputText value="rendered :"/> 
                            #{checkboxLabBean.submitted}

                            <h:outputText value="married status :"/> 
                            #{checkboxLabBean.married}
                            </h:panelGrid>
                    </p:panel>
                </h:panelGrid>
                <h:commandButton value="Refresh"
                    action="#{checkboxLabBean.submit}"/>
            </h:form>
        </ui:define>
    </ui:composition>
</h:body>
</html>
Run Code Online (Sandbox Code Playgroud)

这是我的豆子:

package user.ui;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.bean.ViewScoped;
import javax.inject.Named;

@Named
@ViewScoped
public class CheckboxLabBean implements Serializable {
    private boolean married = true;
    private boolean submitted;

    @PostConstruct
    public void debugPostConstruct() {
        System.out.println("Post Construct !");
    }

    public boolean isMarried() {
        return married;
    }
    public void setMarried(boolean married) {
        this.married = married;
    }
    public boolean isSubmitted() {
        System.out.println("returning submit : " + this.submitted);
        return submitted;
    }
    public void setSubmitted(boolean submitted) {
        this.submitted = submitted;
    }

    public String submit() {
        System.out.println("setting submit to true");
        this.submitted = true;
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的viewscope和sessionscope日志的输出:

视图作用域 在重新启动Web应用程序后首先打开:

[#| 2010-12-24T11:01:11.307 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 34; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:01:11.310 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 34; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:01:11.310 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 34; _ThreadName =线程1 ; |返回提交:false |#]

[#| 2010-12-24T11:01:11.311 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 34; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:01:11.322 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 34; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:01:11.322 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 34; _ThreadName =线程1 ; | Post Construct!|#]

单击刷新按钮后查看作用域

[#| 2010-12-24T11:02:46.129 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.130 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.131 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.131 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.131 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; |设置提交为true |#]

[#| 2010-12-24T11:02:46.133 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.134 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.134 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; |返回提交:false |#]

[#| 2010-12-24T11:02:46.134 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.136 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T11:02:46.136 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; | Post Construct!|#]

重新启动Web应用后首次打开会话作用域:

[#| 2010-12-24T10:58:54.610 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 32; _ThreadName =线程1 ; | Post Construct!|#]

[#| 2010-12-24T10:58:54.612 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 32; _ThreadName =线程1 ; |返回提交:false |#]

单击刷新按钮后的会话范围:

[#| 2010-12-24T10:59:14.613 + 0700 | INFO | glassfish3.0.1 | org.hibernate.validator.engine.resolver.DefaultTraversableResolver | _ThreadID = 37; _TreadName = Thread-1; |实例化组织的实例. hibernate.validator.engine.resolver.JPATraversableResolver |#]

[#| 2010-12-24T10:59:14.615 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; |设置提交为true |#]

[#| 2010-12-24T10:59:14.617 + 0700 | INFO | glassfish3.0.1 | javax.enterprise.system.std.com.sun.enterprise.v3.services.impl | _ThreadID = 37; _ThreadName =线程1 ; |返回提交:true |#]

Arj*_*jms 6

问题似乎是你声明你的bean是一个CDI托管bean,而不是一个JSF托管bean.@ViewScoped是一个特定于JSF的范围,CDI本身不支持该范围.

CDI允许您创建自定义范围,因此您可以为其构建支持.事实上,这已经完成了.请参阅:http://seamframework.org/Community/JSF2ViewScopeInCDI

不使用任何扩展,以下代码非常有效:

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;

@ManagedBean
@ViewScoped
public class MyBean {

    String state = "";

    @PostConstruct
    public void test() {
        System.out.println("pc called");
        state = "state set";
    }

    public String getState() {
        return state;
    }

    public String action() {
        return "";
    }
}
Run Code Online (Sandbox Code Playgroud)

以下Facelet:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">
    <h:body>

        #{myBean.state}

        <h:form>
            <h:commandButton value="test" action="#{myBean.action}"/>
        </h:form>
    </h:body>
</html>
Run Code Online (Sandbox Code Playgroud)

post构造方法现在只调用一次,按下命令按钮后页面将刷新,但状态将被保留.