Поддельный PreDestroyViewMapEvent с includeViewParams="true" на h:link
У меня 2 просмотра (a.xhtml
а также b.xhtml
) один из которых содержит ссылку на другой. Первый вид:
- использует текущую карту вида, задав ей какое-то значение;
- указывает на
b.xhtml
сh:link
с помощьюincludeViewParams="true"
для автоматического включения параметров просмотра в строку запроса ссылки.
a.xhtml
:
<f:view >
<f:metadata>
<f:viewAction>
<!-- just set any value to force view map creation... -->
<f:setPropertyActionListener target="#{viewScope.username}" value="John" />
</f:viewAction>
</f:metadata>
<h:link id="alink" value="Go to B" outcome="b" includeViewParams="true" />
<h:form>
<h:commandButton id="away" action="b" value="Navigate away" immediate="false" />
</h:form>
</f:view>
</html>
а также b.xhtml
:
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view >
<f:metadata>
<f:viewParam id="id" name="userid" value="1" />
</f:metadata>
</f:view>
</html>
Также я создаю здесь ViewMapListener
чтобы продемонстрировать "ложные" вызовы событий уничтожения карты вида, которые происходят один раз a.xhtml
посещается. В моем faces-config.xml
У меня есть эта запись:
<system-event-listener>
<system-event-listener-class>org.my.TestViewMapListener</system-event-listener-class>
<system-event-class>javax.faces.event.PreDestroyViewMapEvent</system-event-class>
<source-class>javax.faces.component.UIViewRoot</source-class>
</system-event-listener>
где TestViewMapListener
это так:
public class TestViewMapListener implements ViewMapListener {
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
if (event instanceof PreDestroyViewMapEvent) {
PreDestroyViewMapEvent viewMapEvent = (PreDestroyViewMapEvent)event;
UIViewRoot viewRoot = (UIViewRoot)viewMapEvent.getComponent();
System.out.println("PreDestroyViewMapEvent: "+viewRoot.getViewId());
}
}
...
После того, как страница a.xhtml
отображается, слушатель выводит следующую строку:
PreDestroyViewMapEvent: /b.xhtml
что странно, потому что b.xhtml
никогда не был в гостях. Когда я ухожу с "Navigate away"
Кнопка правильное событие печатается как ожидалось:
PreDestroyViewMapEvent: /a.xhtml
Неправильное событие вызывается, только если я использую includeViewParams="true"
по ссылке. Отладка, я вижу, что это происходит потому, что com.sun.faces.application.view.ViewMetadataImpl.createMetadataView(FacesContext)
временно устанавливается на FacesContext
UIViewRoot для b.xhtml
где создается мелкая копия исходной карты вида и устанавливается временный вид корня. Вероятно, это сделано для того, чтобы правильно определить значения параметров строки запроса для ссылки; он также временно отключает события на время манипуляций, однако он включает их слишком рано (см. блок "finally"), поэтому событие уничтожения карты просмотра "неправильно" запускается для временной копии карты просмотра, в то время как никаких событий нет. для исходного вида карта сама ожидается в это время. Это головная боль, потому что мне нужно предпринять некоторые дополнительные действия, чтобы определить, уничтожена ли исходная карта или это ложное событие для ее "призрака".
Это ошибка или желаемое поведение? Я использую Мохарру 2.2.12.