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.
|