NullPointerException in MyFaces facelet inclusion

2020-04-30 03:37发布

问题:


I'm trying to migrate simple JSF2.2 prototype from Mojarra 2.2.5 (... where works fine ...) to MyFaces 2.2.3 but a NullPointerException occurs.
What I normally do using Mojarra is to include (inject) programmatically a JSF page within a container.

The sample inclusion page (inclusion.xhtml) is:

<h:panelGroup id="container">
</h:panelGroup>
<h:form>
    <h:commandButton value="Include page" action="#{inclusion.include('included.xhtml')}" />
</h:form>

The included page (included.xhtml) contains something like:

    <h:outputText value="INCLUDED TEXT ..." />

This is the managed bean:

    @ManagedBean(name="inclusion")
    @RequestScoped
    public final class Inclusion {

    public void include(String contentUrl) throws IOException{
        FacesContext fc = FacesContext.getCurrentInstance();        
        FaceletContext f2ctx = (FaceletContext) fc.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
        UIComponent uic = fc.getViewRoot().findComponent("container");
        if (uic != null && f2ctx != null) {
            f2ctx.includeFacelet(uic, contentUrl);              
        }
    }

This is the Exception:

javax.el.ELException: java.lang.NullPointerException

viewId=/inclusion.xhtml location=/opt/jbdevstudio7/workspace/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/jsf2test/inclusion.xhtml phaseId=INVOKE_APPLICATION(5)

Caused by: java.lang.NullPointerException - java.lang.NullPointerException at org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl.generateUniqueId(FaceletCompositionContextImpl.java:1045)

/inclusion.xhtml at line 15 and column 91 action="#{inclusion.include('included.xhtml')}" - State size:0 bytes

This is the stacktrace:

org.apache.myfaces.view.facelets.el.ContextAwareELException: javax.el.ELException: java.lang.NullPointerException at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:108) at org.apache.myfaces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:74) at org.primefaces.application.DialogActionListener.processAction(DialogActionListener.java:45) at javax.faces.component.UICommand.broadcast(UICommand.java:120) at javax.faces.component.UIViewRoot._broadcastAll(UIViewRoot.java:1172) at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:365) at javax.faces.component.UIViewRoot._process(UIViewRoot.java:1656) at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:862) at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:42) at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:196) at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:143) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:198) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:145) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at jplus.web.filters.FlowFilter.doFilter(FlowFilter.java:215) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408) at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023) at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589) at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:662) Caused by: javax.el.ELException: java.lang.NullPointerException at org.apache.el.parser.AstValue.invoke(AstValue.java:291) at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:274) at org.apache.myfaces.view.facelets.el.ContextAwareTagMethodExpression.invoke(ContextAwareTagMethodExpression.java:96) ... 33 more Caused by: java.lang.NullPointerException at org.apache.myfaces.view.facelets.impl.FaceletCompositionContextImpl.generateUniqueId(FaceletCompositionContextImpl.java:1045) at org.apache.myfaces.view.facelets.impl.DefaultFaceletContext.generateUniqueId(DefaultFaceletContext.java:322) at org.apache.myfaces.view.facelets.compiler.UIInstructionHandler.apply(UIInstructionHandler.java:87) at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:46) at org.apache.myfaces.view.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:59) at org.apache.myfaces.view.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:48) at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:514) at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:568) at org.apache.myfaces.view.facelets.impl.DefaultFacelet.include(DefaultFacelet.java:546) at org.apache.myfaces.view.facelets.impl.DefaultFaceletContext.includeFacelet(DefaultFaceletContext.java:240) at Inclusion.include(Inclusion.java:27) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.apache.el.parser.AstValue.invoke(AstValue.java:278) ... 35 more

What do you think about ?
Is there a bug ?
Thanks.

回答1:

It is not a bug. Use FaceletContext is the wrong way to do it, because later it causes duplicate id and state management issues, that does not have solution because from start the code is wrong. Instead, try use this way:

        ViewDeclarationLanguage vdl = facesContext.getApplication().
            getViewHandler().getViewDeclarationLanguage(
                facesContext, facesContext.getViewRoot().getViewId());

        Map<String, Object> attributes = new HashMap<String, Object>();
        attributes.put("src", "/addSimpleIncludeVDL_1_1.xhtml");
        UIComponent component = vdl.createComponent(facesContext, 
            "http://java.sun.com/jsf/facelets", 
            "include", attributes);
        getChildren().add(component);

vdl.createComponent(...) was added in JSF 2.2, and in MyFaces it was improved to allow this usage. You can even add composite components programmatically in this way. In MyFaces users list it has been reported that this way works very well.