@SessionScoped bean注入@ViewScoped的@ManagedProperty就像MyFaces中的@RequestScoped一样,在Mojarra中运行正常

时间:2013-08-25 03:03:17

标签: jsf myfaces mojarra

以下是我的简单示例:

root中的

Index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Title</title>
    </h:head>
    <h:body>
        <h:form>
            <h:inputText value="#{index.variable}"></h:inputText>
            <h:commandButton action="#{index.submit()}" type="submit"></h:commandButton>
        </h:form>
    </h:body>
</html>

其ManagedBean:

import java.io.IOException;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;

@ManagedBean
@ViewScoped
public class Index implements Serializable {

    @ManagedProperty("#{sessionBean}")
    private SessionBean sessionBean; /*getter&setter*/
    private String variable; /*getter&setter*/

    public void submit() {
        sessionBean.setAsd(variable);
        ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
        try {
            context.redirect("next");
        } catch (IOException ex) {
        }
    }
}

/next/index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>Check variable</title>
    </h:head>
    <h:body>
        #{sessionBean.asd}
    </h:body>
</html>

SessionBean.java

import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean
@SessionScoped
public class SessionBean implements Serializable {

    private String asd;

    public String getAsd() {
        return asd;
    }

    public void setAsd(String asd) {
        this.asd = asd;
    }
}

如果我使用mojarra实现,一切都按预期工作:在表单提交后,用户被重定向到root/并看到以index.xhtml形式打印的值。

但是如果我使用myfaces,asd会在提交现有表单后立即变为空。 SessionScoped bean的行为类似于RequestScoped

为什么吗


这是我的web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <context-param>
        <param-name>javax.faces.PROJECT_STAGE</param-name>
        <param-value>Development</param-value>
    </context-param>
    <listener>
        <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
        <!--listener-class>com.sun.faces.config.ConfigureListener</listener-class-->
    </listener>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>
            30
        </session-timeout>
    </session-config>
</web-app>

enter image description here

  

服务器:Apache Tomcat 7.0.34

更新:如果我们将ViewScoped注释Index.java bean更改为RequestScopedSessionScoped,则此方法有效。但为什么呢?

1 个答案:

答案 0 :(得分:6)

我目前在Mojarra的帮助下编写了一个JSF 2.1项目。仅仅为了进行实验,我将实现更改为MyFaces并仅运行应用程序以查看与您类似的问题(我提交的@ManagedProperty变量在POST提交后最终为null)。我切换回Mojarra,应用运行良好。所以,MyFaces的实现基本上有所不同。

一些谷歌搜索引发了我这个未解决的问题 - MYFACES-3656。以下是问题记者关于如何解决问题的摘录:

  

如果您将org.apache.myfaces.SERIALIZE_STATE_IN_SESSION设置为 false   并重新部署应用程序,然后一切都按预期工作。

这有什么用?答案在comments section

  

我认为所描述的行为是预期的(不同于说   所描述的行为是有意或有意地以这种方式完成的。)

     

这里发生的事情是在MyFaces中将序列化设置为true   默认(JSF 1.0规范中的一些旧行表示如此,即使RI没有   以这种方式实现它)。在JSF 2.2规范中,SERIALIZE_STATE_IN_SESSION   param将被标准化并默认设置为false。

     

序列化导致视图范围内的所有bean实际上都是   &#34;重新创建&#34 ;.如果param设置为false,则存储bean   会话和进一步的请求被使用,看起来像一切   好吧,但事实并非如此,因为群集配置中的   相同的申请将失败

     

仅在第一次创建视图范围bean时引用   来自托管属性会生效,但如果是的话   序列化/反序列化,引用不会恢复,因为   在序列化步骤,甚至是应用程序和会话范围   bean也被序列化了。

     

.....

     

如何解决?我还没有找到解决这个问题的合适方案。一   可以考虑恢复视图范围bean并重新应用   在faces-config.xml中找到的@ManagedProperty注释或条目,但是   问题是视图范围bean仍然存储信息   不应该从一开始就存在(仅将字段标记为瞬态   会做的伎俩)。这可能是定义一种特殊模式   黑客或某些变体已经完成,但它只会在myfaces和它   默认情况下无法启用。

已报告类似问题,并在此mailing-list archive

中回复了上述说明

现在,因为在您的情况下,您没有明确设置STATE_SAVING_METHOD,它默认为服务器。因此,SERIALIZE_STATE_IN_SESSION生效,默认为true。

我在Tomcat上使用MyFaces尝试了您的代码,并将SERIALIZE_STATE_IN_SESSION设置为false并且它可以正常工作。但是,在这种情况下,您将STATE_SAVING_METHOD设置为 client ,没有任何工作,您将获得视图状态未找到错误。