在ui:repeat中使用动态ui:include会导致NullPointerException



我想通过使用<ui:repeat><p:dialog>以及<ui:include>来创建动态对话框窗口。但当我像下面这样尝试时,有一个例外。

main.xhtml

<p:outputPanel id="windowsPanel" layout="block" style="width:100%;">
    <p:outputPanel rendered="#{mainView.dynamicWindows ne null}">
        <ui:repeat var="item"  value="#{mainView.dynamicWindows}">
            <p:dialog binding="#{item.dialog}">
                <ui:include src="#{item.includedWindowPath}" />
            </p:dialog>
        </ui:repeat>
    </p:outputPanel>
</p:outputPanel>

MainView.java

@ManagedBean(name = "mainView")
@SessionScoped
public class MainView extends BaseView {
private static final long serialVersionUID = -6291834350102049312L;
private List<Window> dynamicWindows;
@PostConstruct
public void init() {
    fillWindows();
}
private void fillWindows() {
    dynamicWindows = new ArrayList<Window>();
    for (int i = 0; i < 3; i++) {
        Window window = new Window("Header " + i);
        window.getDialog().setId("_dynamicWindow" + i);
        window.getDialog().setWidgetVar("_dynamicWindowWidget" + i);
        dynamicWindows.add(window);
    }
}
// getters & setters

例外:

javax.servlet.ServletException: /main.xhtml @33,42 binding="#{item.dialog}": Target Unreachable, identifier 'item' resolved to null
    javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)
    org.primefaces.webapp.filter.FileUploadFilter.doFilter(FileUploadFilter.java:79)
    org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:369)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
    org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
    org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
    org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168)
    org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
    org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
    org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)

<ui:include>是在视图构建时运行的标记处理程序,而<ui:repeat>是在视图渲染时运行的UI组件。标记处理程序生成JSF UI组件树。JSF UI组件生成HTML。它们不同步运行。

因此,当<ui:include>运行时,<ui:repeat var>指定的#{item}在作用域中根本不可用,因为<ui:repeat>当时还没有运行。您需要一个迭代标记处理程序,而不是一个迭代JSF UI组件。JSTL <c:forEach>就是这样一个。用<c:forEach>替换<ui:repeat>应该可以解决此问题。然而,它可能有不可取的副作用。事先很难判断,因为您的具体功能需求还不完全清楚。

另请参阅:

  • JSF2 Facelets中的JSTL。。。有道理吗?(讨论标记处理程序与UI组件的生命周期)

如果你有有限数量的案例(比如4-5个案例),可以从&对于ui:repeat中的一个项目,include,那么这样做可能是值得的,因为如果要迭代的列表更大,它将避免使用c:forEach构建巨大的组件树。这将有条件地只呈现几个案例中的一个,以包含来自的xhtml。这些情况不会在组件树中重复多次,每次都在您的列表中。希望这能提供更好的性能&除了将JSF与JSTL混合之外。

    <ui:repeat var="item"  value="#{mainView.dynamicWindows}">
         <h:panelGroup rendered="#{booleancase1}">
            <ui:include src="case1.xhtml" />
         </h:panelGroup>
         <h:panelGroup rendered="#{booleancase2}">
            <ui:include src="case2.xhtml" />
         </h:panelGroup>
         <h:panelGroup rendered="#{booleancase3}">
            <ui:include src="case3.xhtml" />
         </h:panelGroup>
         <h:panelGroup rendered="#{booleancase4}">
            <ui:include src="case4.xhtml" />
         </h:panelGroup>
    </ui:repeat>

相关内容

  • 没有找到相关文章

最新更新