JSF 2.1 — Динамические компоненты пользовательского интерфейса и ссылки

Я использую JSF 2.1 на Tomcat6 с библиотеками el2.2.

Я создал макет шаблона с общим для всех страниц заголовком, панелью меню и нижним колонтитулом, при этом меняется только содержимое. Каждый раздел находится в своих тегах div. Все работает нормально, и ссылки в строке меню правильно перемещаются на новые страницы, используя правила навигации Faces-config.

Теперь я создал страницу контента, которая содержит динамически создаваемые UIComponents. При рендеринге панели панель с одним пунктом отображается корректно, но все пункты меню уже не работают!

Если я удалю тег panelgrid из xhtml и обновлю его, то пункты меню снова будут работать правильно. ЕДИНСТВЕННАЯ разница в сгенерированном HTML в этом случае заключается в наличии/отсутствии тега table для панели.

В следующих примерах я урезал его до одного HtmlPanelGrid с одним дочерним элементом.

My Bean: (Все, что делает BaseBean, это реализация Serializable).

package org.gwl.chart;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.html.HtmlOutputLabel;
import javax.faces.component.html.HtmlPanelGrid;

import com.praxism.iims.web.BaseBean;

@ManagedBean
@SessionScoped
public class DashBacker extends BaseBean {

    private static final long serialVersionUID = -894246439580172432L;

    HtmlPanelGrid _dash;

    public DashBacker() {
    }

    @PostConstruct
    public void init() {
        _dash = new HtmlPanelGrid();
        _dash.setColumns(3);
        _dash.setId("dashboard");

        HtmlOutputLabel label1 = new HtmlOutputLabel();
        label1.setId("label1");
        label1.setValue("Label 1");
        _dash.getChildren().add(label1);
    }

    public HtmlPanelGrid getDash() {
        return _dash;
    }
}

Мой контент 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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:iims-chart="http://java.sun.com/jsf/composite/components/chart">
    <ui:composition>    
        <h:outputText styleClass="h1" value="#{msgs_dash.heading}"/>
        <h:messages errorClass="errorMessage" infoClass="infoMessage" warnClass="warnMessage"/>
        <h:panelGrid binding="#{dashBacker.dash}" />
    </ui:composition>
</html>

Мой MenuBar xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui">
    <ui:composition>
        <h:form id="menuBarFrm" styleClass="my-menubar">
            <p:menubar>
                <p:menuitem rendered="#{request.isUserInRole('user')}" value="Home" action="home"/>
                <p:submenu rendered="#{request.isUserInRole('user')}" label="Help">
                    <p:menuitem rendered="#{request.isUserInRole('user')}" value="About" action="about"/>
                </p:submenu>
            </p:menubar>
        </h:form>
    </ui:composition>   
</html> 

И, наконец, мой шаблон макета

<!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:f="http://java.sun.com/jsf/core"
        xmlns:ui="http://java.sun.com/jsf/facelets"
        xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title><ui:insert name="windowTitle">DEFAULT_TITLE</ui:insert></title>
    </h:head>
    <h:body>
        <div id="layout-header">
            <ui:insert name="header">No define for "header"!</ui:insert>
        </div>
        <div id="layout-menubar">
            <ui:insert name="menubar">No define for "menu"!</ui:insert>
        </div>
        <div id="layout-content">
            <div id="layout-scrollable">
                <div id="layout-margin">
                    <ui:insert name="content">No define for "content"!</ui:insert>
                </div>
            </div>
        </div>
        <h:messages/>
        <div id="layout-footer">
            <ui:insert name="footer">No define for "content"!</ui:insert>
        </div>
    </h:body>
</html> 

person Gordon Little    schedule 23.10.2013    source источник
comment
Когда вы нажимаете «Домой», он перенаправляет его правильно, и после загрузки работают ли пункты меню.   -  person BholaVishwakarma    schedule 23.10.2013
comment
Если бы я перешел на страницу «Справка/О программе» по явному URL-адресу, то элементы меню работали бы, и я мог бы вернуться туда или перейти на «Домой». Только при рендеринге Home меню перестает работать. (Он реагирует на наведение мыши и всплывающие подменю, но ссылки не работают)   -  person Gordon Little    schedule 23.10.2013


Ответы (1)


Вы не можете хранить компоненты ни в чем выше области запроса.

person Freddy    schedule 23.10.2013
comment
Я перешел на SessionScoped только потому, что мой первоначальный ViewScoped привел к NonSerializableException для HtmlPanelGrid. Я никогда не думал о снижении масштаба. RequestScoped работает. Любое объяснение странного поведения, влияющего на ссылки в строке меню, особенно когда сгенерированный HTML был идентичен? - person Gordon Little; 23.10.2013
comment
Это требует много пояснений. Достаточно сказать, что это запрещено спецификацией (по крайней мере, в 2.2) и, таким образом, является недокументированным поведением. Сохраняя ссылку на что-либо в дереве представления JSF в сеансе, вы также неявно сохраняете ссылку на ViewRoot в сеансе (который воссоздается для каждого запроса), вызывая утечку памяти и множество непреднамеренных побочных эффектов. Почему странное поведение? Поскольку JSF не смог правильно восстановить представление при обратной передаче (из-за этого), трудно сказать, что именно пошло не так, без отладки. Однако причина ошибки ясна. - person Freddy; 23.10.2013