Tag component instantiation and EL strict or alwaysRecompile modes

2014-06-04 Thread l.pe...@senat.fr

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?

2014-06-04 Thread Karl Kildén
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?

2014-06-04 Thread Howard W. Smith, Jr.
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?

2014-06-04 Thread Karl Kildén
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

2014-06-04 Thread Leonardo Uribe
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.