Поддельный 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.

0 ответов

Другие вопросы по тегам