Using dynamic ui:include inside ui:repeat results in NullPointerException

前提是你 提交于 2019-12-23 03:39:13

问题


I want to create dynamic dialog windows by using <ui:repeat> and <p:dialog> with <ui:include>. But there's an exception when I tried like below.

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

The exception:

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)

回答1:


The <ui:include> is a tag handler which runs during view build time, while the <ui:repeat> is an UI component which runs during view render time. Tag handlers produces the JSF UI component tree. JSF UI components produces HTML. They do not run in sync.

So, when the <ui:include> runs, the #{item} which is specified by <ui:repeat var> is simply not available in the scope, because the <ui:repeat> hasn't run at that time. You need an iterating tag handler instead of an iterating JSF UI component. The JSTL <c:forEach> is such one. Replacing <ui:repeat> by <c:forEach> should fix this issue. It may however have undesireable side effects. It's hard to tell beforehand as your concrete functional requirements are not fully clear.

See also:

  • JSTL in JSF2 Facelets... makes sense? (discusses lifecycle of tag handlers vs UI components)



回答2:


If you have say a limited no of cases (say for e.g 4-5 cases) to dynamically choose from & include for an item within ui:repeat then it may be worth doing it this way, as it would save you from building huge component trees with c:forEach if your list to iterate is bigger. This'll conditionally just render one out of several cases to include xhtml from. These cases wont be repeated multiple times in the component tree, for each time in your list. Hopefully, this should give better performance & also save from concerns of mixing JSF with 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>


来源:https://stackoverflow.com/questions/9603233/using-dynamic-uiinclude-inside-uirepeat-results-in-nullpointerexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!