来自数据库的 JSF2 Bean 的一些数据在渲染时不可用

Some data of JSF2 Bean from database not available at render time

我在呈现 JSF2 (Facelet) 页面时 运行 遇到了一个奇怪的问题。它是通过 GET 接收 id 并显示对象的普通页面。该对象内部有一个 List<>,问题是有时该列表不打印任何内容,有时我刷新并部分打印列表(所有元素,但不是关于它们的所有信息)。它也会发生在其他对象的属性(某些日期)上。我检查了一些日志记录,信息是从数据库和对象 set 中正确获取的信息。

我很确定这是因为 preRenderView 是在渲染之前完成的,所以当我使用 c:ifc:each 时,bean 偶然不可用。对于第二种情况,也许ui:repeatwould solve my problem?.

我的问题是:

  1. 我该如何解决这个问题?
  2. 在 Facelets 中有没有一种方法来呈现 f.ex。一种 <section><time>(如下面我的 document.xhtml)并且不要 如果渲染计算为假,打印空标签?我知道我可以使用 c:if,但建议在 Facelets 中呈现。
  3. DB Javabean Document 是否也Named(除了 DocumentController)?

此外,如果有更好的方法来完成我正在做的事情(通过 GET 接收 id 并显示对象的页面),请指教。我是 JSF 的新手。

顺便说一句,我已经丢弃它是因为 this problem

DocumentController.java

@Named(value = "DocumentController")
@SessionScoped
public class DocumentController implements Serializable {
    private String id;
    private Document document;

    /**
     * @return the id
     */
    public String getId() {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId(String id) {
        this.id = id;
    }

    /**
     * @return the Document
     */
    public Document getDocument() {
        return document;
    }

    /**
     * @param Document the Document to set
     */
    public void setDocument(Document document) {
        this.document = document;
    }


    public void load() {
        FacesContext ctx = FacesContext.getCurrentInstance();
        if (ctx.isValidationFailed()) {
            ctx.getApplication().getNavigationHandler()
                    .handleNavigation(ctx, "#{DocumentController.load}", "invalid");
            return;
        }

        try (DataStore dst = new DataStore()) {
            dst.connect();
            document = dst.getDocument(id);

        } catch (NoData | ConnectionError | IllegalArgumentException ex) {
            ctx.getApplication().getNavigationHandler()
                    .handleNavigation(ctx, "#{DocumentController.load}", "invalid");
        }
    }

}

document.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:utils="http://java.sun.com/jsf/composite/utils"
                template="template.xhtml">
    <ui:define name="content">
        <f:metadata>
            <f:viewParam name="id" value="#{documentController.id}" required="true"/>
            <f:event type="preRenderView" listener="#{documentController.load}"/>
        </f:metadata>
...
        <section rendered="#{not empty documentController.document.participants}">
            <utils:participants
                participants="#{documentController.document.participants}
                cid="example"/>
....
    </ui:define>
</ui:composition>

participants.xhtml

<ui:component xmlns="http://www.w3.org/1999/xhtml"
              xmlns:h="http://java.sun.com/jsf/html"
              xmlns:f="http://java.sun.com/jsf/core"
              xmlns:cc="http://xmlns.jcp.org/jsf/composite"
              xmlns:c="http://java.sun.com/jsp/jstl/core"
              xmlns:ui="http://java.sun.com/jsf/facelets">
    <cc:interface>
        <cc:attribute name="participants" type="java.util.List" required="true"/>
        <cc:attribute name="cid" type="String" required="true"/>
    </cc:interface>

    <cc:implementation>
        <table>
...
            <tbody>
                <c:forEach items="#{cc.attrs.participants}" var="participant">
                    <tr>
                        <td><a href="#">#{participant.name}</a></td>
                        <td>#{participant.lastName}</td>
                        <td>#{participant.role(cc.attrs.cid)}</td>
                    </tr>
                </c:forEach>
            </tbody>
        </table>
    </cc:implementation>
</ui:component>

1.我该如何解决这个问题?

正如我所怀疑的,这与preRenderView有关。发现这一点的线索是日志显示具有数据的 bean,如果我使用 SessionScoped,在我刷新时数据奇迹般地出现,但无论出现多少次都不会出现 RequestScoped我刷新了——意思是数据确实在bean里面,但是第一时间显示不出来。我通过更改修复了它:

<f:event type="preRenderView" listener="#{documentController.load}"/>

<f:viewAction action="#{projectController.load}" />

另请参阅:When to use f:viewAction / preRenderView versus PostConstruct?

我没有 (2)、(3) 的答案,也没有关于我正在尝试做的事情的最佳实践,但至少我想写下主要问题的解决方案,以备不时之需.

2. 显然有 none,至少在当前的 JSF 版本中是这样。这可以做到,但并不理想:

<ui:fragment rendered="...">

3. 诺普