Tag component instantiation and EL strict or alwaysRecompile modes
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-nameorg.apache.myfaces.CACHE_EL_EXPRESSIONS/param-name param-valuestrict/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
Submit form after disabling an input element via javascript?
Hi, my app recently upgraded from JSF 1.2 had a broken page with this in the log: WARNING: There should always be a submitted value for an input if it is rendered, its form is submitted, and it was not originally rendered disabled or read-only. You cannot submit a form after disab ling an input element via javascript. Consider setting read-only to true instead or resetting the disabled value back to false prior to form submission. Component : {Component-Path : [Class: javax.fa ces.component.UIViewRoot,ViewId: /pages/main.xhtml][Class: javax.faces.component.html.HtmlBody,Id: j_id_10][Class: javax.faces.component.html.HtmlForm,Id: f][Class: javax.faces.component.html.HtmlPane lGroup,Id: body][Class: javax.faces.component.html.HtmlPanelGroup,Id: contentBody][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id_2b_p][Class: javax.faces.component.html.HtmlInputText,Id: im portName] Location: /WEB-INF/facelets/admin/profileUploadForm.xhtml at line 88 and column 73} I don't understand this limitation. Is there some global flag I could use to make sure not included inputs are seen as unchanged or something? cheers
Re: Submit form after disabling an input element via javascript?
Karl, if Javascript was written to enable field, why is there not Javascript to disable before submit? On Jun 4, 2014 8:33 AM, Karl Kildén karl.kil...@gmail.com wrote: Hi, my app recently upgraded from JSF 1.2 had a broken page with this in the log: WARNING: There should always be a submitted value for an input if it is rendered, its form is submitted, and it was not originally rendered disabled or read-only. You cannot submit a form after disab ling an input element via javascript. Consider setting read-only to true instead or resetting the disabled value back to false prior to form submission. Component : {Component-Path : [Class: javax.fa ces.component.UIViewRoot,ViewId: /pages/main.xhtml][Class: javax.faces.component.html.HtmlBody,Id: j_id_10][Class: javax.faces.component.html.HtmlForm,Id: f][Class: javax.faces.component.html.HtmlPane lGroup,Id: body][Class: javax.faces.component.html.HtmlPanelGroup,Id: contentBody][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id_2b_p][Class: javax.faces.component.html.HtmlInputText,Id: im portName] Location: /WEB-INF/facelets/admin/profileUploadForm.xhtml at line 88 and column 73} I don't understand this limitation. Is there some global flag I could use to make sure not included inputs are seen as unchanged or something? cheers
Re: Submit form after disabling an input element via javascript?
Howard, To do that one would need a purpose. I fail to see the benefit other than bending the knee to a JSF limitation. On 4 June 2014 16:48, Howard W. Smith, Jr. smithh032...@gmail.com wrote: Karl, if Javascript was written to enable field, why is there not Javascript to disable before submit? On Jun 4, 2014 8:33 AM, Karl Kildén karl.kil...@gmail.com wrote: Hi, my app recently upgraded from JSF 1.2 had a broken page with this in the log: WARNING: There should always be a submitted value for an input if it is rendered, its form is submitted, and it was not originally rendered disabled or read-only. You cannot submit a form after disab ling an input element via javascript. Consider setting read-only to true instead or resetting the disabled value back to false prior to form submission. Component : {Component-Path : [Class: javax.fa ces.component.UIViewRoot,ViewId: /pages/main.xhtml][Class: javax.faces.component.html.HtmlBody,Id: j_id_10][Class: javax.faces.component.html.HtmlForm,Id: f][Class: javax.faces.component.html.HtmlPane lGroup,Id: body][Class: javax.faces.component.html.HtmlPanelGroup,Id: contentBody][Class: javax.faces.component.html.HtmlPanelGrid,Id: j_id_2b_p][Class: javax.faces.component.html.HtmlInputText,Id: im portName] Location: /WEB-INF/facelets/admin/profileUploadForm.xhtml at line 88 and column 73} I don't understand this limitation. Is there some global flag I could use to make sure not included inputs are seen as unchanged or something? cheers
Re: Tag component instantiation and EL strict or alwaysRecompile modes
Hi Use the standard vdl.createComponent(...) included since JSF 2.2. It has the necessary code to do the trick properly. Please note in Myfaces this method has been extend to support facelet tags too. It should work with the view pool. regards Leonardo Uribe On Jun 4, 2014 12:37 PM, l.pe...@senat.fr l.pe...@senat.fr wrote: 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-nameorg.apache.myfaces.CACHE_EL_EXPRESSIONS/param-name param-valuestrict/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.