MyFaces Core
  1. MyFaces Core
  2. MYFACES-2516

Allow any child for f:event in the case of a PreRenderViewEvent

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0.0-alpha, 2.0.0-beta
    • Fix Version/s: 2.0.0-beta-2
    • Component/s: JSR-314
    • Labels:
      None

      Description

      f:event currently only supports the UIViewRoot as a child for the PreRenderViewEvent

        Activity

        Hide
        Leonardo Uribe added a comment -

        This patch changes the way it is setViewRoot is called. I don't think we can apply that part as is, because the algorithm to setViewRoot is clear (see RestoreViewExecutor and section 2.2 of jsf 2.0 spec)

        Anyway, I think it is valid apply the remaining part of the patch so I'll commit that one.

        Show
        Leonardo Uribe added a comment - This patch changes the way it is setViewRoot is called. I don't think we can apply that part as is, because the algorithm to setViewRoot is clear (see RestoreViewExecutor and section 2.2 of jsf 2.0 spec) Anyway, I think it is valid apply the remaining part of the patch so I'll commit that one.
        Hide
        Bernd Bohmann added a comment - - edited

        That is the reason why i don't apply the patch.

        If f:event is a direct child of f:metadata you don't get the UIViewRoot from the parent or from the FacesContext.

        How we can get the ViewRoot in this case?

        Show
        Bernd Bohmann added a comment - - edited That is the reason why i don't apply the patch. If f:event is a direct child of f:metadata you don't get the UIViewRoot from the parent or from the FacesContext. How we can get the ViewRoot in this case?
        Hide
        Leonardo Uribe added a comment -

        Note the committed code uses ComponentSupport.getViewRoot instead facesContext.getViewRoot(). If f:event is inside f:metadata we don't have a NullpointerException, but if we have f:event inside a component inside f:metadata we have it. Does this apply for your use case?

        Show
        Leonardo Uribe added a comment - Note the committed code uses ComponentSupport.getViewRoot instead facesContext.getViewRoot(). If f:event is inside f:metadata we don't have a NullpointerException, but if we have f:event inside a component inside f:metadata we have it. Does this apply for your use case?
        Hide
        Bernd Bohmann added a comment -

        I see it.
        If f:event is inside f:metadata i get a NullpointerException. The metadata facet of UIViewRoot is set after nextHandler.apply because of ComponentHandler.isNew() should return true.
        Where is the metadata contract defined? Which kind of tags are allowed in the metadata tag?

        Show
        Bernd Bohmann added a comment - I see it. If f:event is inside f:metadata i get a NullpointerException. The metadata facet of UIViewRoot is set after nextHandler.apply because of ComponentHandler.isNew() should return true. Where is the metadata contract defined? Which kind of tags are allowed in the metadata tag?
        Hide
        Leonardo Uribe added a comment -

        In theory it is expected f:metadata could contains f:viewParam and f:event tags. UIViewParameter extends from UIInput, so it also f:viewParam could contains converter and validator tags. f:metadata is a facet with multiple components, so in theory inside UIViewRoot.METADATA_FACET_NAME there should be only one UIPanel (optional) and one or many UIViewParameter instances.

        With the latest code (using ComponentSupport.getViewRoot), use f:event inside f:metadata should work without problem.

        Show
        Leonardo Uribe added a comment - In theory it is expected f:metadata could contains f:viewParam and f:event tags. UIViewParameter extends from UIInput, so it also f:viewParam could contains converter and validator tags. f:metadata is a facet with multiple components, so in theory inside UIViewRoot.METADATA_FACET_NAME there should be only one UIPanel (optional) and one or many UIViewParameter instances. With the latest code (using ComponentSupport.getViewRoot), use f:event inside f:metadata should work without problem.
        Hide
        Bernd Bohmann added a comment -

        Have you try it?

        I get a
        java.lang.NullPointerException
        at org.apache.myfaces.view.facelets.tag.jsf.core.EventHandler.apply(EventHandler.java:114)
        at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:51)
        at org.apache.myfaces.view.facelets.tag.jsf.core.ViewMetadataHandler.apply(ViewMetadataHandler.java:69)
        at org.apache.myfaces.view.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:57)
        at org.apache.myfaces.view.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:45)
        at org.apache.myfaces.view.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:103)
        at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage$FaceletViewMetadata.createMetadataView(FaceletViewDeclarationLanguage.java:1854)
        at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:148)
        at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:138)

        Once again

        You can not get the UIViewRoot from the parent in ComponentSupport.
        The metadata facet of UIViewRoot is set after nextHandler.apply in ViewMetadataHandler because ComponentHandler.isNew() should return true in EventHandler.

        Show
        Bernd Bohmann added a comment - Have you try it? I get a java.lang.NullPointerException at org.apache.myfaces.view.facelets.tag.jsf.core.EventHandler.apply(EventHandler.java:114) at javax.faces.view.facelets.CompositeFaceletHandler.apply(CompositeFaceletHandler.java:51) at org.apache.myfaces.view.facelets.tag.jsf.core.ViewMetadataHandler.apply(ViewMetadataHandler.java:69) at org.apache.myfaces.view.facelets.compiler.NamespaceHandler.apply(NamespaceHandler.java:57) at org.apache.myfaces.view.facelets.compiler.EncodingHandler.apply(EncodingHandler.java:45) at org.apache.myfaces.view.facelets.impl.DefaultFacelet.apply(DefaultFacelet.java:103) at org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage$FaceletViewMetadata.createMetadataView(FaceletViewDeclarationLanguage.java:1854) at org.apache.myfaces.lifecycle.RestoreViewExecutor.execute(RestoreViewExecutor.java:148) at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:138) Once again You can not get the UIViewRoot from the parent in ComponentSupport. The metadata facet of UIViewRoot is set after nextHandler.apply in ViewMetadataHandler because ComponentHandler.isNew() should return true in EventHandler.
        Hide
        Leonardo Uribe added a comment -

        Ouch, that's true. To solve this one we have to change the current ViewMetadataHandler implementation.

        The implementation of FacetHandler looks like this:

        public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException,
        ELException
        {
        if (parent == null)

        { throw new TagException(this.tag, "Parent UIComponent was null"); }

        parent.getAttributes().put(KEY, this.name.getValue(ctx));
        try

        { this.nextHandler.apply(ctx, parent); }

        finally

        { parent.getAttributes().remove(KEY); }

        }

        There is no creation of panel here (it is done indirectly from ComponentTagHandlerDelegate). Maybe we can set and remove FacetHandler.KEY like in FacetHandler, also create a panel like it is present, then change the call of call

        this.nextHandler.apply(ctx, parent);

        instead

        this.nextHandler.apply(ctx, metadataFacet);

        And in theory that should work.

        Show
        Leonardo Uribe added a comment - Ouch, that's true. To solve this one we have to change the current ViewMetadataHandler implementation. The implementation of FacetHandler looks like this: public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, ELException { if (parent == null) { throw new TagException(this.tag, "Parent UIComponent was null"); } parent.getAttributes().put(KEY, this.name.getValue(ctx)); try { this.nextHandler.apply(ctx, parent); } finally { parent.getAttributes().remove(KEY); } } There is no creation of panel here (it is done indirectly from ComponentTagHandlerDelegate). Maybe we can set and remove FacetHandler.KEY like in FacetHandler, also create a panel like it is present, then change the call of call this.nextHandler.apply(ctx, parent); instead this.nextHandler.apply(ctx, metadataFacet); And in theory that should work.
        Hide
        Leonardo Uribe added a comment -

        The final code looks like this:

        UIComponent metadataFacet = parent.getFacet(UIViewRoot.METADATA_FACET_NAME);
        if (metadataFacet == null)

        { metadataFacet = ctx.getFacesContext(). getApplication().createComponent(UIPanel.COMPONENT_TYPE); metadataFacet.setId(UIViewRoot.METADATA_FACET_NAME); parent.getFacets().put(UIViewRoot.METADATA_FACET_NAME, metadataFacet); }

        parent.getAttributes().put(FacetHandler.KEY, UIViewRoot.METADATA_FACET_NAME);
        try

        { this.nextHandler.apply(ctx, parent); }

        finally

        { parent.getAttributes().remove(FacetHandler.KEY); }

        Does that work?

        Show
        Leonardo Uribe added a comment - The final code looks like this: UIComponent metadataFacet = parent.getFacet(UIViewRoot.METADATA_FACET_NAME); if (metadataFacet == null) { metadataFacet = ctx.getFacesContext(). getApplication().createComponent(UIPanel.COMPONENT_TYPE); metadataFacet.setId(UIViewRoot.METADATA_FACET_NAME); parent.getFacets().put(UIViewRoot.METADATA_FACET_NAME, metadataFacet); } parent.getAttributes().put(FacetHandler.KEY, UIViewRoot.METADATA_FACET_NAME); try { this.nextHandler.apply(ctx, parent); } finally { parent.getAttributes().remove(FacetHandler.KEY); } Does that work?
        Hide
        Bernd Bohmann added a comment -

        My code looks like this:

        UIComponent metadataFacet = parent.getFacet(UIViewRoot.METADATA_FACET_NAME);
        if (metadataFacet == null)

        { metadataFacet = ctx.getFacesContext().getApplication().createComponent(UIPanel.COMPONENT_TYPE); metadataFacet.setId(UIViewRoot.METADATA_FACET_NAME); metadataFacet.getAttributes().put(ComponentSupport.FACET_CREATED_UIPANEL_MARKER, true); parent.getFacets().put(UIViewRoot.METADATA_FACET_NAME, metadataFacet); }

        parent.getAttributes().put(FacetHandler.KEY, UIViewRoot.METADATA_FACET_NAME);
        try

        { this.nextHandler.apply(ctx, parent); }

        finally

        { parent.getAttributes().remove(FacetHandler.KEY); }
        Show
        Bernd Bohmann added a comment - My code looks like this: UIComponent metadataFacet = parent.getFacet(UIViewRoot.METADATA_FACET_NAME); if (metadataFacet == null) { metadataFacet = ctx.getFacesContext().getApplication().createComponent(UIPanel.COMPONENT_TYPE); metadataFacet.setId(UIViewRoot.METADATA_FACET_NAME); metadataFacet.getAttributes().put(ComponentSupport.FACET_CREATED_UIPANEL_MARKER, true); parent.getFacets().put(UIViewRoot.METADATA_FACET_NAME, metadataFacet); } parent.getAttributes().put(FacetHandler.KEY, UIViewRoot.METADATA_FACET_NAME); try { this.nextHandler.apply(ctx, parent); } finally { parent.getAttributes().remove(FacetHandler.KEY); }
        Hide
        Bernd Bohmann added a comment -

        Should I commit?

        Show
        Bernd Bohmann added a comment - Should I commit?
        Hide
        Matthias Weßendorf added a comment -

        +1 yes, please commit it

        Show
        Matthias Weßendorf added a comment - +1 yes, please commit it
        Hide
        Leonardo Uribe added a comment -

        Thanks Bernd for check it and commit that one. I'm glad that solution works.

        Show
        Leonardo Uribe added a comment - Thanks Bernd for check it and commit that one. I'm glad that solution works.

          People

          • Assignee:
            Bernd Bohmann
            Reporter:
            Bernd Bohmann
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development