Portals Bridges
  1. Portals Bridges
  2. PB-7

Messages are not displayed, validation errors are ignored

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Blocker Blocker
    • Resolution: Fixed
    • Affects Version/s: 1.0
    • Fix Version/s: 1.0.3
    • Component/s: jsf
    • Labels:
      None
    • Environment:
      Jetspeed2

      Description

      If the JSF page produces messages (explicitly or implicitly due to validation errors) these messages are not displayed.

      Also (and probably related) validation errors are ignored, i.e. the model is changed despite the error.

      1. jsf.patch
        6 kB
        Yasushi Miyazawa
      2. FacesPortlet.java
        25 kB
        Steve Halverson

        Activity

        Hide
        Ronald Holshausen added a comment -

        The reason for this behaviour is that the FacesPortlet receives two different responses, and ActionReponse and then a RenderResponse. During the handling of the ActionResponse, validation occurs and the validation messages are added to the FacesContext. However, the context is released after handling the ActionResponse, causing the messages to be discarded, and as the view is only rendered during the handling of the RenderResponse, there are no messages to display.

        A fix for this would be to save the messages from the context during the handling of the ActionResponse, and then restore them to the context when handling the RenderResonse.

        Show
        Ronald Holshausen added a comment - The reason for this behaviour is that the FacesPortlet receives two different responses, and ActionReponse and then a RenderResponse. During the handling of the ActionResponse, validation occurs and the validation messages are added to the FacesContext. However, the context is released after handling the ActionResponse, causing the messages to be discarded, and as the view is only rendered during the handling of the RenderResponse, there are no messages to display. A fix for this would be to save the messages from the context during the handling of the ActionResponse, and then restore them to the context when handling the RenderResonse.
        Hide
        Michael Lipp added a comment -

        I have by now learned a lot about the requirements for a Portlet/JSF bridge by tracking down problems and patching the MyFaces bridge until it finally does now what I want.

        To summarize, (1) the bridge must carry over request attributes added during action handling to the rendering phase. The portal does not do this, it calls performAction with the ActionRequest and rendering with a RenderRequest and any attributes set on the ActionRequest are lost. JSF does not know about these different requests, it knows only of one request (context) used during the complete cycle. Thus, the bridge must make sure that it looks like this to JSF.

        (2) Request attributes set during performAction (i.e. carried over, see above) or during rendering a JSF-portlet must be removed from the request after rendering the JSF-portlet. This is necessary because only one request instance is used for rendering all portlets. (The portlet specification does not require the attributes of this request to be portlet scoped.) Therefore, if the JSF framework or application uses request attributes, there may be unintended interaction between the JSF applications. Neither the JSF framework nor the application is aware of a requirement to "scope" request attributes, because it does not "know" about the application being a portlet and several application being rendered with the same request (two or more JSF-portlets on one page).

        Show
        Michael Lipp added a comment - I have by now learned a lot about the requirements for a Portlet/JSF bridge by tracking down problems and patching the MyFaces bridge until it finally does now what I want. To summarize, (1) the bridge must carry over request attributes added during action handling to the rendering phase. The portal does not do this, it calls performAction with the ActionRequest and rendering with a RenderRequest and any attributes set on the ActionRequest are lost. JSF does not know about these different requests, it knows only of one request (context) used during the complete cycle. Thus, the bridge must make sure that it looks like this to JSF. (2) Request attributes set during performAction (i.e. carried over, see above) or during rendering a JSF-portlet must be removed from the request after rendering the JSF-portlet. This is necessary because only one request instance is used for rendering all portlets. (The portlet specification does not require the attributes of this request to be portlet scoped.) Therefore, if the JSF framework or application uses request attributes, there may be unintended interaction between the JSF applications. Neither the JSF framework nor the application is aware of a requirement to "scope" request attributes, because it does not "know" about the application being a portlet and several application being rendered with the same request (two or more JSF-portlets on one page).
        Hide
        Ronald Holshausen added a comment -

        I see the MyFaces Portlet implementation does not release the FacesContext after handling the ActionRequest, but saves it in the portlet session, and then restores it during the handling of the RenderRequest. This seems like a good solution to this problem.

        Show
        Ronald Holshausen added a comment - I see the MyFaces Portlet implementation does not release the FacesContext after handling the ActionRequest, but saves it in the portlet session, and then restores it during the handling of the RenderRequest. This seems like a good solution to this problem.
        Hide
        Michael Lipp added a comment -

        This does not solve the issue with request attributes. The FacesContext uses the ExternalContext from the current request to access request attributes and therefore the request attributes are not carried over by simply saving the FacesContext

        Note that part of the portlet support of MyFaces has been coded in MyFaces. The MyFaces portlet bridge sets a special flag to indicate the portlet context (only found this after looking very close). Of course, the generic bridge from this (PB) project cannot do this (or only after making sure that the JSF implementation used in the current request is MyFaces).

        IMHO, this project will not be able to deliver a generic JSF/portlet bridge without talking to the MyFaces project (and maybe others)!

        Show
        Michael Lipp added a comment - This does not solve the issue with request attributes. The FacesContext uses the ExternalContext from the current request to access request attributes and therefore the request attributes are not carried over by simply saving the FacesContext Note that part of the portlet support of MyFaces has been coded in MyFaces. The MyFaces portlet bridge sets a special flag to indicate the portlet context (only found this after looking very close). Of course, the generic bridge from this (PB) project cannot do this (or only after making sure that the JSF implementation used in the current request is MyFaces). IMHO, this project will not be able to deliver a generic JSF/portlet bridge without talking to the MyFaces project (and maybe others)!
        Hide
        Ronald Holshausen added a comment -

        I think a generic JSF/portlet bridge can be created, but as long as you don't do funny things with request parameters but rather bind the JSF controls to backing bean properties. Then the request parameters will be decoded and stored in the view and the data model (backing beans) during the handling of the ActionRequest, and as long as the view and context is restored for the RenderRequest (see issue PB-32), the response should be rendered as normal.

        Show
        Ronald Holshausen added a comment - I think a generic JSF/portlet bridge can be created, but as long as you don't do funny things with request parameters but rather bind the JSF controls to backing bean properties. Then the request parameters will be decoded and stored in the view and the data model (backing beans) during the handling of the ActionRequest, and as long as the view and context is restored for the RenderRequest (see issue PB-32 ), the response should be rendered as normal.
        Hide
        Michael Lipp added a comment -

        Ronald, where do you think MyFaces creates/saves backing beans with request scope? Right, as MyFaces does not know anything about difficulties with portlet requests, it simply uses the request from the external context.

        Before patching the bridge, I spoiled my code with workarounds, saving attributes in session scope and cleaning them after the render phase. But by now I think (and found some confirmation for this on the net) that it is really the bridge's task to carry over the request attributes from the action request to the render request.

        Besides, this is completely independant from the portlet-dependant code in MyFaces. I also believe that you can create a generic bridge, but it won't work while the MyFaces implementation has code sections that depend on a flag being set when MyFaces is used in a portlet. Because as long as the bridge does not set this flag, MyFaces will do things that depend on running as a servlet. This dependency is easy to fix in MyFaces if MyFaces can make certain assumptions about the behaviour of the bridge. That's why it won't work unless the two projects start talking to each other (you'll find an issue in MYFACES that I have submitted with a comment that shows that at least some MyFaces developers don't even know about the PB project!).

        Show
        Michael Lipp added a comment - Ronald, where do you think MyFaces creates/saves backing beans with request scope? Right, as MyFaces does not know anything about difficulties with portlet requests, it simply uses the request from the external context. Before patching the bridge, I spoiled my code with workarounds, saving attributes in session scope and cleaning them after the render phase. But by now I think (and found some confirmation for this on the net) that it is really the bridge's task to carry over the request attributes from the action request to the render request. Besides, this is completely independant from the portlet-dependant code in MyFaces. I also believe that you can create a generic bridge, but it won't work while the MyFaces implementation has code sections that depend on a flag being set when MyFaces is used in a portlet. Because as long as the bridge does not set this flag, MyFaces will do things that depend on running as a servlet. This dependency is easy to fix in MyFaces if MyFaces can make certain assumptions about the behaviour of the bridge. That's why it won't work unless the two projects start talking to each other (you'll find an issue in MYFACES that I have submitted with a comment that shows that at least some MyFaces developers don't even know about the PB project!).
        Hide
        Henryk Paluch added a comment -

        Hi!
        We are currently using a bit brute but working "workaround". It sems to work well for us (we have few jsf pages with dataTable and forms with messages - all seem to work correctly). There are some problems with portlet help mode but I don't mind (messages are more important for me

        • Use org.apache.myfaces.portlet.MyFacesGenericPortlet instead of this bridge, i.e. update your portlet.xml to use that class instead of org.apache.portals.bridges.jsf.FacesPortlet.
        • Also there is need to make new init-param called default-view (value is same as for ViewPage).
        • Last but not least - remove your WEB-INF/lib/portals-bridges-jsf-1.0.jar from web application - they otherwise intercept Jetspeed's PortalContext causing "Unsupporting context exception" in FacesContextFactoryImpl
        Show
        Henryk Paluch added a comment - Hi! We are currently using a bit brute but working "workaround". It sems to work well for us (we have few jsf pages with dataTable and forms with messages - all seem to work correctly). There are some problems with portlet help mode but I don't mind (messages are more important for me Use org.apache.myfaces.portlet.MyFacesGenericPortlet instead of this bridge, i.e. update your portlet.xml to use that class instead of org.apache.portals.bridges.jsf.FacesPortlet. Also there is need to make new init-param called default-view (value is same as for ViewPage). Last but not least - remove your WEB-INF/lib/portals-bridges-jsf-1.0.jar from web application - they otherwise intercept Jetspeed's PortalContext causing "Unsupporting context exception" in FacesContextFactoryImpl
        Hide
        Michael Lipp added a comment -

        Hi Henryk,

        well, using a completly different software is indeed what I'd call a "brute workaround"

        Show
        Michael Lipp added a comment - Hi Henryk, well, using a completly different software is indeed what I'd call a "brute workaround"
        Hide
        Henryk Paluch added a comment -

        Hi!
        Anyway - later found that even MyFacesGenericPortlet intruduces different but equally weird problems (some fields disappearing on panelGrid on every odd request - looks very mysteriously). So unfortunately my "brute workaround" is no workaround anymore...

        Show
        Henryk Paluch added a comment - Hi! Anyway - later found that even MyFacesGenericPortlet intruduces different but equally weird problems (some fields disappearing on panelGrid on every odd request - looks very mysteriously). So unfortunately my "brute workaround" is no workaround anymore...
        Hide
        Terrence Drozdowski added a comment -

        Its been a while since this discussion took place - any movement on this front?

        Show
        Terrence Drozdowski added a comment - Its been a while since this discussion took place - any movement on this front?
        Hide
        Yasushi Miyazawa added a comment -

        poor fix...

        Show
        Yasushi Miyazawa added a comment - poor fix...
        Hide
        Steve Halverson added a comment -

        We are using the MyFaces portlet bridge in a project being developed. Ran into this problem with FacesMessage objects not being carried over into the render phase. I coded up a solution this problem that works nicely. Saves the messaes on the PortletSession and re-establishes them in the render phase. We would like to see these changes integrated into the project. I have attached the FacesPortlet.java source file with the changes in it.

        Show
        Steve Halverson added a comment - We are using the MyFaces portlet bridge in a project being developed. Ran into this problem with FacesMessage objects not being carried over into the render phase. I coded up a solution this problem that works nicely. Saves the messaes on the PortletSession and re-establishes them in the render phase. We would like to see these changes integrated into the project. I have attached the FacesPortlet.java source file with the changes in it.
        Hide
        David Sean Taylor added a comment -

        Patch applied, Steve could you please test it and let me know if it works for you as is

        Show
        David Sean Taylor added a comment - Patch applied, Steve could you please test it and let me know if it works for you as is
        Hide
        David Sean Taylor added a comment -

        Steve, Im getting messages to work here. Going to resolve this one

        Show
        David Sean Taylor added a comment - Steve, Im getting messages to work here. Going to resolve this one

          People

          • Assignee:
            David Sean Taylor
            Reporter:
            Michael Lipp
          • Votes:
            3 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development