Удаление сообщений JSF из флэш-памяти
У меня есть одна страница, которая что-то делает, и когда пользователь нажимает кнопку, пользователь перенаправляется на другую страницу и отображается сообщение. Вот мой код:
public String confirm() {
FacesContext context = FacesContext.getCurrentInstance();
Flash flash = context.getExternalContext().getFlash();
flash.setKeepMessages(true);
FacesMessage msg = new FacesMessage("Succesful", "Release is confirmed!");
context.addMessage(null, msg);
return "/prot/expert/releases?faces-redirect=true";
}
Я использую компонент ap: growl, который отображает мое сообщение на странице "релизы". Все идет нормально.
Но затем на любой последующей странице, которая имеет p: growl (или если я перейду на другую страницу и вернусь назад), сообщение отображается снова и снова, и я не могу его убить.
Я попробовал что-то вроде:
<c:set target="#{flash}" property="keepMessages" value="false" />
на странице, содержащей p: рычание, я попытался очистить вспышку от бобов и т. д.
Сообщение сохраняется и отображается снова. Если я удалю flash.setKeepMessages(true); из кода выше, то ничего не отображается.
Что я делаю неправильно?
3 ответа
Я получил точно такую же проблему на JBoss AS 6 с Mojarra 2.0.3 и Mojarra 2.1.1. Вспышка должна выдержать только одно перенаправление, но на практике это не всегда так.
В методе действия у меня есть в основном тот же код:
// [add global faces message]
FacesContext.getCurrentInstance().getExternalContext().getFlash().setKeepMessages(true);
return "/someView.xhtml?faces-redirect=true";
Я видел три симптома проблемы:
- После выполнения обратной передачи в someView сообщение о флеш-гранях продолжает отображаться
- После чистого запроса на совершенно другую страницу, также отображается сообщение лица
- После повторного прохождения кода, который добавляет сообщение лиц, вы получите два одинаковых сообщения на someView.
Проблема 2 может быть объяснена пониманием того, что область действия флэш-памяти основана на использовании файлов cookie (по крайней мере, в Моджарре). Относительно мало людей, кажется, понимают врожденную проблему с этим. Я нашел этот связанный вопрос, но у него нет ответов: свободна ли область видимости Flash от условий гонки?
Кроме того, когда я пытаюсь воспроизвести проблему, у меня есть примерно 2/3 шанса ее воспроизвести. Иногда он действительно выживает только после одного перенаправления, иногда он исчезает после нескольких обновлений (основанных на времени или около того?), А иногда он просто застревает, и единственный способ избавиться от него - перезапустить мой сервер (!).
Может я что-то не так делаю?
Наблюдая за установкой файлов cookie, я заметил следующее:
После первоначального запуска действия, которое выполняет перенаправление:
POST Response
Set-Cookie csfcfc=_50Xfr
GET Response
Set-Cookie csfcfc=50Xfn_51Xfn
Здесь следует отметить, что ответ на запрос GET для перенаправления снова устанавливает cookie. Вы хотите думать, что для флеш-области cookie необходимо удалить здесь.
Если я отправляю форму с указанием на перенаправление, происходит следующее:
POST Response
Set-Cookie csfcfc=_50Xfn
Сообщение сейчас пропало.
Однако, когда я отправляю форму еще раз, происходит следующее:
POST Response
Set-Cookie csfcfc=_52Xfn
И сообщение вернулось:(
Если я снова отправлю форму:
POST Response
Больше нет заголовка Set-Cookie, и сообщение снова исчезло. Если я продолжу отправлять форму, последний файл cookie (csfcfc=_52Xfn) будет отправляться на сервер, но новые файлы cookie не устанавливаются и сообщения не отображаются.
Редактировать:
Во время отладки я наткнулся на критический раздел в ELFlash.java (Mojarra 2.0.3):
void saveAllMessages(FacesContext context) {
// take no action on the GET that comes after a REDIRECT
Map<Object, Object> contextMap = context.getAttributes();
PreviousNextFlashInfoManager flashManager;
if (null == (flashManager = getCurrentFlashManager(contextMap, true))) {
return;
}
if (flashManager.getPreviousRequestFlashInfo().isIsRedirect()) {
return;
}
}
В контексте запроса GET после перенаправления можно предположить, что isIsRedirect вернет true, но вернул false. Это может быть локальной проблемой, которую я собираюсь исследовать дальше.
Интересно отметить, что, возможно, значения cookie действительно имеют некоторое значение, согласно следующему:
FirstTimeThru("f"),
SecondTimeThru("s"),
IsRedirect("r"),
IsNormal("n");
Таким образом, первое печенье (_50Xfr), является FirstTimeThru
и IsRedirect
,
Ваша конкретная проблема вызвана ошибкой в старых версиях Mojarra, в частности, проблема 1751. Тем не менее, было много сообщений о проблемах для области флеш-памяти впоследствии. Область применения флэш-памяти представлена в более старых версиях Mojarra, известных по следующим основным проблемам:
- проблема 1751 - сообщения в формате Flash живут дольше, чем следующий запрос - исправлено в 2.0.7 / 2.1.4
- проблема 2126 - Flash cookie позволяет использовать данные - исправлено в 2.1.24 / 2.2.1
- проблема 2136 - Flash cookie недоступен при перенаправлении на другой путь - исправлено в 2.1.14 / 2.2.0
- проблема 2902 - Flash cookie использует неверный путь для приложений в корне - исправлено в 2.1.24 / 2.2.1
- проблема 2955 - Flash иногда создает файлы cookie версии 1, которые не работают в IE<=10 - исправлено в 2.1.25 / 2.2.2
- проблема 2973 - Flash вызывает NPE для устаревших файлов cookie после истечения срока действия сеанса - исправлено в 2.1.25 / 2.2.2
- проблема 2862 - Flash cookie не очищается при устаревании - исправлено в 2.1.27 / 2.2.5
В общем, можно заключить, что вам нужно обновить Mojarra до минимума 2.1.27 / 2.2.5 (срок исполнения 2 января 2014 г.), чтобы избавиться от всех этих проблем.
Попробуйте установить свойство redisplay в false:
<p:growl redisplay="false"/>