9 Replies Latest reply on Sep 12, 2012 7:29 PM by nishant_k123

    problem with Weld's conversation propagation filter

    marcelkolsteren

      In my JSF applications, I sometimes need to do a programmatic redirect to an external URL, in the following way:


      FacesContext.getCurrentInstance().getExternalContext().redirect("http://www.somesite.com/foo")
      



      Unfortunately, this doesn't work if there is a long-running conversation active. That's because in that case Weld's conversation propagation filter steps in to replace the redirect URL. That filter calls a URL transformer:


      new FacesUrlTransformer(path, FacesContext.getCurrentInstance()).toRedirectViewId().toActionUrl().
         appendConversationIdIfNecessary(conversationContext.getParameterName(), conversation.getId()).encode();
      



      The toRedirectViewId() method of FacesUrlTransformer is causing the problem:


       public FacesUrlTransformer toRedirectViewId() {
              String requestPath = context.getExternalContext().getRequestContextPath();
              if (isUrlAbsolute()) {
                  url = url.substring(url.indexOf(requestPath) + requestPath.length());
              } else if (url.startsWith(requestPath)) {
                  url = url.substring(requestPath.length());
              }
              return this;
          }
      



      If the URL is absolute, this piece of code assumes that the request path of the current request is part of the URL that is being transformed. However, when redirecting to an external site, that assumption is not correct. The result is that the the first N characters (where N is the length of the requestPath) are stripped off the URL, which leads to a corrupted URL, which in the end gives this exception in JSF's MultiViewHandler:


      java.lang.IllegalArgumentException: Illegal view ID [...].  The ID must begin with /
      



      I looked up what the CDI spec (JSR299) says about the conversation propagation in case of a redirect:



      The long-running conversation context associated with a request that results in a JSF redirect (a redirect resulting from a navigation rule or JSF NavigationHandler) is automatically propagated to the resulting non-faces request, and to any other subsequent request to the same URL. This is accomplished via use of a GET request parameter named cid containing the unique identifier of the conversation.

      So, only redirects that result from JSF navigation rules or JSF navigation handlers should lead to an automatic propagation of the conversation. It seems that the Weld implementation is a too enthusiastic propagator.


      To illustrate the problem, I created a sample JSF 2.0 application that contains a simple page with two buttons. Both do a programmatic redirect to www.google.com, one with and one without an active conversation. The first button generates an exception, while the latter works. The application can be downloaded here as a Maven project:


      sample application


      I used it with JBoss AS 7.1.0.CR1b, which contains Weld 1.1.4.Final.