Почему flash.keep() удаляет ключ, если он находится в бине, а не в EL на странице Facelets?
Итак, у меня есть очень маленький пример JSF:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Index</title>
</h:head>
<h:body>
<h:form>
<h:commandButton action="#{reqScopedBackingBean.foo()}" value="Submit"/>
</h:form>
</h:body>
</html>
и foo реализуется, как показано ниже:
package biz.tugay.jsftags;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
@ManagedBean
@RequestScoped
public class ReqScopedBackingBean {
public String foo() {
FacesContext.getCurrentInstance().getExternalContext().getFlash().put("message", "Success!!");
return "hello?faces-redirect=true";
}
}
и наконец hello.xhtml
как следует:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Hello</title>
</h:head>
<h:body>
<h:outputText value="#{flash.keep.message}"/>
</h:body>
</html>
в приведенном выше примере, когда я нажму "Отправить", я буду перенаправлен в hello.xhtml и увижу "Успех!!" текст просто отлично. И когда я обновлю страницу, я все равно увижу сообщение, потому что я вызываю метод keep, как показано ниже:
#{flash.keep.message}
Теперь перейдем к другому примеру:
index.xhtml и ReqScopedBackingBean одинаковы, однако на этот раз hello.xhtml выглядит следующим образом:
<!DOCTYPE html>
<html xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Hello</title>
</h:head>
<h:body>
#{otherBean.pullValuesFromFlash()}
<h:outputText value="#{otherBean.message}"/>
</h:body>
</html>
а также OtherBean.java
как следует:
@ManagedBean
@RequestScoped
public class OtherBean {
private String message;
public void pullValuesFromFlash() {
final Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
flash.keep("message");
final String message = (String) flash.get("message");
setMessage(message);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Я ожидаю, что поведение будет таким же, как в первом примере. Однако, когда я нахожусь на hello.xhtml, я не увижу сообщение об успехе. Однако, если я закомментирую строку:
// flash.keep("message");
тогда появится сообщение (но обновление hello.xhtml не отобразит сообщение об успехе, как в первом примере).
У меня вопрос, в чем здесь разница? Как
#{flash.keep.message}
и отличается от
flash.keep("message");
final String message = (String) flash.get("message");
?
1 ответ
Вы попали в ошибку Мохарры Flash#keep()
, По сути, Mojarra излишне удаляет запись из текущей области флэш-памяти, прежде чем поместить ее в следующую область флэш-памяти.
Это будет работать, если вы измените порядок логики, как показано ниже.
public void pullValuesFromFlash() {
Flash flash = FacesContext.getCurrentInstance().getExternalContext().getFlash();
String message = (String) flash.get("message");
flash.keep("message");
setMessage(message);
}
Я исправил эту ошибку согласно проблеме 4167.
Не связанные с конкретной проблемой, те, <h:outputText>
с не нужны. Вы можете безопасно удалить их, чтобы уменьшить шаблон. См. Также Предлагается ли использовать h:outputText для всего?