@SessionScoped bean, введенный как @ManagedProperty из @ViewScoped, действует как @RequestScoped в MyFaces, отлично работает в Mojarra
Вот мой простой пример:
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
становится null сразу после отправки существующей формы. 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>
Сервер: Apache Tomcat 7.0.34
UPDATE: он работает, если мы изменим аннотацию ViewScoped
Index.java bean
на RequestScoped
или SessionScoped
. Но почему?
Ответы
Ответ 1
В настоящее время у меня есть проект JSF 2.1, написанный с помощью Mojarra. Просто для экспериментов я изменил реализацию на MyFaces и запускал приложение только для просмотра проблем, подобных вашим (все мои введенные переменные @ManagedProperty заканчиваются нулевыми после отправки POST). Я переключился на Mojarra, и приложение работает нормально. Итак, в чем-то отличается от реализации MyFaces.
Немного поискового запроса привело меня к этой нерешенной проблеме - MYFACES-3656. Вот выдержка из репортера проблемы о том, как исправить проблему:
Если вы установите org.apache.myfaces.SERIALIZE_STATE_IN_SESSION значение falseи передислоцировать приложение, тогда все работает так, как ожидалось.
Как это помогает? Ответ находится в разделе комментариев:
Я думаю, что описанное поведение ожидается (другое - сказать, что описанное поведение желательно или намеренно сделано таким образом).
Что происходит в сериализации MyFaces, установлено значение true на default (некоторые старые строки из спецификации JSF 1.0 говорят так, , даже если RI не реализуйте его таким образом). В спецификации JSF 2.2 SERIALIZE_STATE_IN_SESSION Параметр будет стандартизован и по умолчанию будет равен false.
Сериализация приводит к тому, что все beans в области просмотра на самом деле "Воссоздан". Если для параметра установлено значение false, beans сохраняются в сеанс и дальнейшие запросы, выглядящие как все нормально, но этот факт неверен, поскольку в конфигурации кластера то же приложение будет терпеть неудачу.
Только в первый раз, когда создается область видимости bean, ссылки из управляемой собственности вступает в силу, но если beanсериализованные/десериализованные, ссылки не восстанавливаются, потому что на этапе сериализации даже область приложения и сеанса beans также сериализованы.
.....
Как его решить? Я не нашел достойного решения этой проблемы. Один мог бы подумать только о восстановлении области видимости bean и повторно применить Аннотации @ManagedProperty или записи, найденные в faces-config.xml, но проблема заключается в том, что область видимости bean все еще хранит информацию, которая не должно быть от начала (только отмечая поля как переходные сделают трюк). Можно определить специальный режим: взломать или какой-то вариант, но это будет только в моих поверхностях, и это по умолчанию не может быть активирована.
Сообщается о подобной проблеме и ответила на это объяснение в этом почтовом расписании
Теперь, поскольку в вашем случае вы явно не устанавливаете STATE_SAVING_METHOD
, он по умолчанию использует сервер. Следовательно, SERIALIZE_STATE_IN_SESSION
вступает в силу и по умолчанию имеет значение true.
Я попробовал свой код с MyFaces на Tomcat и установил SERIALIZE_STATE_IN_SESSION в false, и он работает. Однако в случае, если вы установили для клиента STATE_SAVING_METHOD, ничего не получится, и вы получите состояние представления, не найденное.