Dear all,

I am doing something dirty in my code. I dynamically instantiate and add tag components to my component tree, according to some information that I have at runtime.

My instantiation method looks like :

public static UIComponent instantiateTagComponent(Location loc, String namespace, String localPrefix, String componentName, TagComponentParam params[]) { final String ERROR_MESSAGE = "Erreur lors de l'instanciation d'un tag component";
        FacesContext ctx = FacesContext.getCurrentInstance();
AbstractFaceletContext fctx = (AbstractFaceletContext) ctx.getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
        fctx.pushPageContext(new PageContextImpl());

FaceletViewDeclarationLanguage vdl = new FaceletViewDeclarationLanguage(ctx);

UIPanel panel = (UIPanel) ctx.getApplication().createComponent( UIPanel.COMPONENT_TYPE );

        try {
Method createCompiler = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createCompiler",FacesContext.class); Method createFaceletFactory = FaceletViewDeclarationLanguage.class.getDeclaredMethod("createFaceletFactory",FacesContext.class,org.apache.myfaces.view.facelets.compiler.Compiler.class);
            createCompiler.setAccessible(true);
            createFaceletFactory.setAccessible(true);
org.apache.myfaces.view.facelets.compiler.Compiler compiler = (org.apache.myfaces.view.facelets.compiler.Compiler) createCompiler.invoke(vdl, ctx); FaceletFactory ff = (FaceletFactory) createFaceletFactory.invoke(vdl, ctx, compiler);
            TagLibrary tl = compiler.createTagLibrary();
TagConfig tc = new JSFUtilsTagUnit(tl, namespace, localPrefix, componentName,params,loc); TagHandler th = tl.createTagHandler(namespace, componentName, tc); Field declaredField = FaceletCompositionContext.class.getDeclaredField("FACELET_COMPOSITION_CONTEXT_KEY");
            declaredField.setAccessible(true);
FaceletCompositionContextImpl faceletCompositionContextImpl = new FaceletCompositionContextImpl(ff,ctx); Class<?> dfcClass = Class.forName("org.apache.myfaces.view.facelets.impl.DefaultFaceletContext");
            Field fMCTX = dfcClass.getDeclaredField("_mctx");
            fMCTX.setAccessible(true);
            fMCTX.set(fctx, faceletCompositionContextImpl);
FacesContext.getCurrentInstance().getAttributes().put((String)declaredField.get(null),faceletCompositionContextImpl);
FaceletCompositionContext mctx = (FaceletCompositionContext) FaceletCompositionContext.getCurrentInstance(fctx);
            mctx.startComponentUniqueIdSection();
            th.apply( fctx, panel );
        } catch (IOException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (InvocationTargetException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (NoSuchMethodException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (NoSuchFieldException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (SecurityException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (ClassNotFoundException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (IllegalArgumentException ex) {
            log.error(ERROR_MESSAGE, ex);
        } catch (IllegalAccessException ex) {
            log.error(ERROR_MESSAGE, ex);
        }
        finally {
            fctx.popPageContext();
        }
        return panel;
    }

This is dirty, but this perfectly works for quite some time now, at least until I stick to

    <context-param>
<param-name>org.apache.myfaces.CACHE_EL_EXPRESSIONS</param-name>
        <param-value>strict</param-value>
    </context-param>


if I change it to alwaysRecompile, the state is "not properly restored" and I end with and NPE like :

04/06/2014 12:29:41 ERROR [http-bio-8443-exec-56] - Exception occur!
java.lang.NullPointerException
at org.apache.myfaces.view.facelets.el.FaceletStateValueExpression.getValue(FaceletStateValueExpression.java:107)
    at org.apache.el.parser.AstIdentifier.getValue(AstIdentifier.java:68)
at org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:185) at org.apache.myfaces.view.facelets.el.ContextAwareTagValueExpression.getValue(ContextAwareTagValueExpression.java:96) at javax.faces.component._DeltaStateHelper.eval(_DeltaStateHelper.java:360)
    at javax.faces.component.UIParameter.getValue(UIParameter.java:85)
at org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.addChildParametersToHref(HtmlLinkRendererBase.java:762) at org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.renderOutputLinkStart(HtmlLinkRendererBase.java:861) at org.apache.myfaces.shared.renderkit.html.HtmlLinkRendererBase.encodeBegin(HtmlLinkRendererBase.java:144) at javax.faces.component.UIComponentBase.encodeBegin(UIComponentBase.java:596) at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:526) at org.primefaces.component.panelgrid.PanelGridRenderer.encodeDynamicBody(PanelGridRenderer.java:89) at org.primefaces.component.panelgrid.PanelGridRenderer.encodeBody(PanelGridRenderer.java:60) at org.primefaces.component.panelgrid.PanelGridRenderer.encodeEnd(PanelGridRenderer.java:49) at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:674) at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:554) at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:550) at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:635) at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:541) at org.primefaces.component.datatable.DataTableRenderer.encodeCell(DataTableRenderer.java:963) at org.primefaces.component.datatable.DataTableRenderer.encodeRow(DataTableRenderer.java:923) at org.primefaces.component.datatable.DataTableRenderer.encodeRows(DataTableRenderer.java:834) at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:781) at org.primefaces.component.datatable.DataTableRenderer.encodeTbody(DataTableRenderer.java:744) at org.primefaces.component.datatable.feature.FilterFeature.encode(FilterFeature.java:119) at org.primefaces.component.datatable.DataTableRenderer.encodeEnd(DataTableRenderer.java:77) at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:674)
    at javax.faces.component.UIData.encodeEnd(UIData.java:1721)
at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:554) at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.processRenderComponent(PartialViewContextImpl.java:823) at org.apache.myfaces.context.servlet.PartialViewContextImpl$PhaseAwareVisitCallback.visit(PartialViewContextImpl.java:784) at org.apache.myfaces.component.visit.PartialVisitContext.invokeVisitCallback(PartialVisitContext.java:213)
    at org.primefaces.component.api.UIData.visitTree(UIData.java:692)
at fr.senat.faces.components.SenatDataTableCtrl.visitTree(SenatDataTableCtrl.java:239)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1032)
at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:1191)
    at javax.faces.component.UIForm.visitTree(UIForm.java:345)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1032)
at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:1191)
    at javax.faces.component.UIComponent.visitTree(UIComponent.java:1032)
at javax.faces.component.UIComponentBase.visitTree(UIComponentBase.java:1191) at org.apache.myfaces.context.servlet.PartialViewContextImpl.processPartialRendering(PartialViewContextImpl.java:536) at org.apache.myfaces.context.servlet.PartialViewContextImpl.processPartial(PartialViewContextImpl.java:415) at org.primefaces.context.PrimePartialViewContext.processPartial(PrimePartialViewContext.java:60) at javax.faces.context.PartialViewContextWrapper.processPartial(PartialViewContextWrapper.java:85)
    at javax.faces.component.UIViewRoot.encodeChildren(UIViewRoot.java:516)
at javax.faces.component.UIComponentBase.encodeAll(UIComponentBase.java:541) at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage.renderView(FaceletViewDeclarationLanguage.java:1891) at org.apache.myfaces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:313) at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:57) at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:57) at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:57) at org.apache.myfaces.lifecycle.RenderResponseExecutor.execute(RenderResponseExecutor.java:116) at org.apache.myfaces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:267) at org.apache.deltaspike.jsf.impl.listener.request.DeltaSpikeLifecycleWrapper.render(DeltaSpikeLifecycleWrapper.java:111) at javax.faces.lifecycle.LifecycleWrapper.render(LifecycleWrapper.java:31)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:200)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at fr.senat.faces.filters.HibernateNoCacheFilter.doFilter(HibernateNoCacheFilter.java:123) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at fr.senat.faces.filters.HibernateSessionConversationFilter.doFilter(HibernateSessionConversationFilter.java:128) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at fr.senat.faces.filters.HibernateUserFromPrincipalFilter.doFilter(HibernateUserFromPrincipalFilter.java:43) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) at fr.senat.faces.filters.SessionCreationTrackingFilter.doFilter(SessionCreationTrackingFilter.java:48) 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:581) 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:947) 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:1009) 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.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:744)

In this case, the tag file is :

<html
      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://java.sun.com/jsf/facelets";
      xmlns:p="http://primefaces.org/ui";
      xmlns:sc="http://www.senat.fr/taglib/sencommons";
      xmlns:sf="http://www.senat.fr/taglib/senfunctions";>
    <p:panelGrid columns="3" rendered="#{empty rendered or rendered}">
<h:outputLink value="#{facesContext.externalContext.requestContextPath}/elections/rapportElections">
            <f:param name="code" value="#{circonum}"/>
            <f:param name="format" value="pdf"/>
            <f:param name="phase" value="#{phase}"/>
<p:graphicImage value="#{resource['pdf_petit.png']}" alt="PDF" title="PDF"/>
        </h:outputLink>

<h:outputLink value="#{facesContext.externalContext.requestContextPath}/elections/rapportElections">
            <f:param name="code" value="#{circonum}"/>
            <f:param name="format" value="docx"/>
            <f:param name="phase" value="#{phase}"/>
<p:graphicImage value="#{resource['word_petit.png']}" alt="DOCX (Word)" title="DOCX (Word)"/>
        </h:outputLink>

<h:outputLink value="#{facesContext.externalContext.requestContextPath}/elections/rapportElections">
            <f:param name="code" value="#{circonum}"/>
            <f:param name="format" value="rtf"/>
            <f:param name="phase" value="#{phase}"/>
<p:graphicImage value="#{resource['rtf_petit.png']}" alt="RTF" title="RTF"/>
        </h:outputLink>
    </p:panelGrid>
</html>

And the exception is raised when the #{circonum} parameter is evaluated.

In FaceletStateValueExpression#getWrapped, line 73 :

root.getAttributes().get(ComponentSupport.FACELET_STATE_INSTANCE);

returns null, thus the NPE

I know I do dirty things and understand that you have to cleaner things to do, but if one of the guru of this list could drop and eye and give me a hint on what to add...

My apps work fine with org.apache.myfaces.CACHE_EL_EXPRESSIONS=strict, but alwaysRecompile is required to enable view pooling, and I would like to enable this.

Thanks in advance,

Ludovic
|
| AVANT D'IMPRIMER, PENSEZ A L'ENVIRONNEMENT.
|

Reply via email to