来自数据库的 JSF2 Bean 的一些数据在渲染时不可用
Some data of JSF2 Bean from database not available at render time
我在呈现 JSF2 (Facelet) 页面时 运行 遇到了一个奇怪的问题。它是通过 GET
接收 id
并显示对象的普通页面。该对象内部有一个 List<>,问题是有时该列表不打印任何内容,有时我刷新并部分打印列表(所有元素,但不是关于它们的所有信息)。它也会发生在其他对象的属性(某些日期)上。我检查了一些日志记录,信息是从数据库和对象 set
中正确获取的信息。
我很确定这是因为 preRenderView
是在渲染之前完成的,所以当我使用 c:if
或 c:each
时,bean 偶然不可用。对于第二种情况,也许ui:repeat
would solve my problem?.
我的问题是:
- 我该如何解决这个问题?
- 在 Facelets 中有没有一种方法来呈现 f.ex。一种
<section>
或 <time>
(如下面我的 document.xhtml
)并且不要
如果渲染计算为假,打印空标签?我知道我可以使用
c:if
,但建议在 Facelets 中呈现。
- 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. 诺普
我在呈现 JSF2 (Facelet) 页面时 运行 遇到了一个奇怪的问题。它是通过 GET
接收 id
并显示对象的普通页面。该对象内部有一个 List<>,问题是有时该列表不打印任何内容,有时我刷新并部分打印列表(所有元素,但不是关于它们的所有信息)。它也会发生在其他对象的属性(某些日期)上。我检查了一些日志记录,信息是从数据库和对象 set
中正确获取的信息。
我很确定这是因为 preRenderView
是在渲染之前完成的,所以当我使用 c:if
或 c:each
时,bean 偶然不可用。对于第二种情况,也许ui:repeat
would solve my problem?.
我的问题是:
- 我该如何解决这个问题?
- 在 Facelets 中有没有一种方法来呈现 f.ex。一种
<section>
或<time>
(如下面我的document.xhtml
)并且不要 如果渲染计算为假,打印空标签?我知道我可以使用c:if
,但建议在 Facelets 中呈现。 - 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. 诺普