ICEfaces
  1. ICEfaces
  2. ICE-2527

Seam jBPM redirects causing redirect loop.

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7DR#2
    • Fix Version/s: 1.7
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      ICEfaces + Seam

      Description

      When Seam jBPM does page navigation using redirects, there's a mismatch in Pageflow.validatePageflow(Seam code)

      //now check that the restored view id matches what we expect
               //from the pageflow node
               //TODO: we need some way to disable this check, since users
               // might want some adhoc nav in and out of a pageflow?
               String viewId = Pages.getViewId(facesContext);
               if ( !viewId.equals( getPage().getViewId() ) )
               {
                  illegalNavigationError();
               }


      In my example, the viewId from the facesContext object is pageD.seam, whereas the viewId from getPage().getViewId() is pageD.xhtml. This mismatch causes illegalNavigationError to be called, which does page navigation to the current page (in my case) which causes the redirection loop.

      We need to understand why the difference in page viewID representation.

        Activity

        Hide
        Greg Dick added a comment -

        This appears to be a bit of left over hack-ness related to the viewId.

        The JSF spec states the following:

        Derive the view identifier that corresponds to this request, as follows:

        ? If prefix mapping (such as "/faces/*") is used for FacesServlet, the viewId is set
        from the extra path information of the request URI.
        ? If suffix mapping (such as "*.faces") is used for FacesServlet, the viewId is set
        from the servlet path information of the request URI, after replacing the suffix with the
        value of the context initialization parameter named by the symbolic constant
        ViewHandler.DEFAULT_SUFFIX_PARAM_NAME (if no such context initialization
        parameter is present, use the value of the symbolic constant
        ViewHandler.DEFAULT_SUFFIX as the replacement suffix).
        ? If no view identifier can be derived, throw an exception.

        The viewId is being set on the viewRoot in two places in ICEfaces code. Namely, in the D2DViewHandler in createView(), and in the D2DFaceletViewHandler in renderView().

        It looks as if recent check ins to the D2DFaceletView handler have it correct. The code that determines the suffix is:

        protected String getRenderedViewId(FacesContext context, String actionId) {
        ExternalContext extCtx = context.getExternalContext();
        String viewId = actionId;
        if (extCtx.getRequestPathInfo() == null) {
        String viewSuffix = context.getExternalContext().getInitParameter(
        ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
        if (viewSuffix == null) {
        if (log.isErrorEnabled())

        { log.error( "The " + ViewHandler.DEFAULT_SUFFIX_PARAM_NAME + " context parameter is not set in web.xml. " + "Please define the filename extension used for " + "your source JSF pages. Example:\n" + "<context-param>\n" + " <param-name>javax.faces.DEFAULT_SUFFIX</param-name>\n" + " <param-value>.xhtml</param-value>\n" + "</context-param>"); }

        } else {
        int lastPeriod = actionId.lastIndexOf('.');
        if (lastPeriod < 0)

        { viewId = actionId + viewSuffix; }

        else

        { viewId = actionId.substring(0, lastPeriod) + viewSuffix; }

        }
        }
        return viewId;
        }

        But the code in the createView method is using the viewId obtained by this code:

        viewId = facesContext.getExternalContext().getRequestPathInfo();

        There was some legacy code added early on to get Seam to work, stuff to do with the ActionURLParam parameter in web.xml. This is probably redundant now that the D2DFaceletViewHandler is doing the right thing. This code meant that all pages requested in a Seam environment would be terminated by a .seam suffix (in most examples that is, it was configurable) hence the mismatch.

        Replacing the code in D2DViewHandler.createView with a call to setViewId(mungeView(viewID)) causes the viewId with the correct suffix to wind up in the viewRoot, and redirection with jBPM works properly at this point, but I think the correct thing to do is to completely strip out the ActionURLSuffix code and servlet-param and to strictly operate according to the JSF parameters, as in the spec.

        Show
        Greg Dick added a comment - This appears to be a bit of left over hack-ness related to the viewId. The JSF spec states the following: Derive the view identifier that corresponds to this request, as follows: ? If prefix mapping (such as "/faces/*") is used for FacesServlet, the viewId is set from the extra path information of the request URI. ? If suffix mapping (such as "*.faces") is used for FacesServlet, the viewId is set from the servlet path information of the request URI, after replacing the suffix with the value of the context initialization parameter named by the symbolic constant ViewHandler.DEFAULT_SUFFIX_PARAM_NAME (if no such context initialization parameter is present, use the value of the symbolic constant ViewHandler.DEFAULT_SUFFIX as the replacement suffix). ? If no view identifier can be derived, throw an exception. The viewId is being set on the viewRoot in two places in ICEfaces code. Namely, in the D2DViewHandler in createView(), and in the D2DFaceletViewHandler in renderView(). It looks as if recent check ins to the D2DFaceletView handler have it correct. The code that determines the suffix is: protected String getRenderedViewId(FacesContext context, String actionId) { ExternalContext extCtx = context.getExternalContext(); String viewId = actionId; if (extCtx.getRequestPathInfo() == null) { String viewSuffix = context.getExternalContext().getInitParameter( ViewHandler.DEFAULT_SUFFIX_PARAM_NAME); if (viewSuffix == null) { if (log.isErrorEnabled()) { log.error( "The " + ViewHandler.DEFAULT_SUFFIX_PARAM_NAME + " context parameter is not set in web.xml. " + "Please define the filename extension used for " + "your source JSF pages. Example:\n" + "<context-param>\n" + " <param-name>javax.faces.DEFAULT_SUFFIX</param-name>\n" + " <param-value>.xhtml</param-value>\n" + "</context-param>"); } } else { int lastPeriod = actionId.lastIndexOf('.'); if (lastPeriod < 0) { viewId = actionId + viewSuffix; } else { viewId = actionId.substring(0, lastPeriod) + viewSuffix; } } } return viewId; } But the code in the createView method is using the viewId obtained by this code: viewId = facesContext.getExternalContext().getRequestPathInfo(); There was some legacy code added early on to get Seam to work, stuff to do with the ActionURLParam parameter in web.xml. This is probably redundant now that the D2DFaceletViewHandler is doing the right thing. This code meant that all pages requested in a Seam environment would be terminated by a .seam suffix (in most examples that is, it was configurable) hence the mismatch. Replacing the code in D2DViewHandler.createView with a call to setViewId(mungeView(viewID)) causes the viewId with the correct suffix to wind up in the viewRoot, and redirection with jBPM works properly at this point, but I think the correct thing to do is to completely strip out the ActionURLSuffix code and servlet-param and to strictly operate according to the JSF parameters, as in the spec.
        Hide
        Greg Dick added a comment -

        This case also appears to be the problem in this forum posting:
        http://www.icefaces.org/JForum/posts/list/6657.page

        Show
        Greg Dick added a comment - This case also appears to be the problem in this forum posting: http://www.icefaces.org/JForum/posts/list/6657.page
        Hide
        Greg Dick added a comment -

        This has been fixed for some time. I had changed the D2DViewHandler to get rid of the mungeViewId method and moved the getRenderedViewId method from the D2DFaceletViewHandler into the D2DViewHandler superclass. This implementation did the right thing, and Mark's fix for 2871 did the right thing at the proper time so navigation rules can now be written with both the 'from' and 'to' viewId's being written with 'jspx' or 'xhtml' extensions, rather than one field being '.iface' and the other being 'xhtml', etc.

        Show
        Greg Dick added a comment - This has been fixed for some time. I had changed the D2DViewHandler to get rid of the mungeViewId method and moved the getRenderedViewId method from the D2DFaceletViewHandler into the D2DViewHandler superclass. This implementation did the right thing, and Mark's fix for 2871 did the right thing at the proper time so navigation rules can now be written with both the 'from' and 'to' viewId's being written with 'jspx' or 'xhtml' extensions, rather than one field being '.iface' and the other being 'xhtml', etc.

          People

          • Assignee:
            Unassigned
            Reporter:
            Greg Dick
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: