5 Replies Latest reply on Nov 24, 2009 9:17 AM by wesleyhales

    Using PortletRequestDispatcher within a JSF Component

    s.cindric

      We are just about to switch from OpenPortal Portlet Bridge to JBoss Portet Bridge. Now we have problems using a PortletRequestDispatcher within the encodeBegin-method in the Renderer of a custom JSF component.

      The code within the Renderer-class looks like this (simplified):

      public void encodeBegin(FacesContext context, UIComponent component) throws IOException
      {
       [...]
       ExternalContext externalContext = context.getExternalContext();
       RenderRequest req = (RenderRequest) externalContext.getRequest();
       PortletContext cxt = (PortletContext) externalContext.getContext();
       try
       {
       PortletRequestDispatcher dispatcher = cxt.getRequestDispatcher("/jsp/testredirect.jsp");
       dispatcher.include(req, (RenderResponse) externalContext.getResponse());
       }
       catch (Exception e)
       {
       e.printStackTrace();
       }
       [...]
      }



      The component is used in a JSP file named "/jsp/user/userRenderer.jsp"

      This leads to the following exception:

      Caused by: javax.servlet.ServletException: File "/jsp/users/userRenderer.faces" not found
       at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
       at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:265)
       at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)


      The portlet and even the custom component are rendered correctly. Only the dispatcher.include() throws this ServletException.

      Does anyone know what goes wrong here?

      Thanx, Sandra

        • 1. Re: Using PortletRequestDispatcher within a JSF Component
          wesleyhales

          This looks like a problem with your faces servlet mapping in web.xml... Can you post your XML configuration?

          • 2. Re: Using PortletRequestDispatcher within a JSF Component
            s.cindric

            Here is my web.xml (actually a part of it):

            <?xml version="1.0" encoding="UTF-8"?>
            <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
             <context-param>
             <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
             <param-value>server</param-value>
             </context-param>
             <context-param>
             <param-name>javax.faces.CONFIG_FILES</param-name>
             <param-value>/WEB-INF/faces-config.xml</param-value>
             </context-param>
            
             <!-- RICHFACES -->
             <context-param>
             <param-name>org.jboss.jbossfaces.WAR_BUNDLES_JSF_IMPL</param-name>
             <param-value>true</param-value>
             </context-param>
             <context-param>
             <param-name>javax.portlet.faces.RENDER_POLICY</param-name>
             <param-value>NEVER_DELEGATE</param-value>
             </context-param>
             <context-param>
             <param-name>org.ajax4jsf.RESOURCE_URI_PREFIX</param-name>
             <param-value>rfRes</param-value>
             </context-param>
             <context-param>
             <param-name>org.ajax4jsf.cache.LRU_MAP_CACHE_SIZE</param-name>
             <param-value>2048</param-value>
             </context-param>
             <context-param>
             <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
             <param-value>.jsp</param-value>
             </context-param>
             <context-param>
             <param-name>org.richfaces.LoadStyleStrategy</param-name>
             <param-value>DEFAULT</param-value>
             </context-param>
             <context-param>
             <param-name>org.richfaces.LoadScriptStrategy</param-name>
             <param-value>DEFAULT</param-value>
             </context-param>
            
             <servlet>
             <servlet-name>FacesServlet</servlet-name>
             <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
             <load-on-startup>1</load-on-startup>
             </servlet>
             <servlet-mapping>
             <servlet-name>FacesServlet</servlet-name>
             <url-pattern>*.faces</url-pattern>
             </servlet-mapping>
            
             <filter>
             <display-name>Ajax4jsf Filter</display-name>
             <filter-name>ajax4jsf</filter-name>
             <filter-class>org.ajax4jsf.Filter</filter-class>
             <init-param>
             <param-name>createTempFiles</param-name>
             <param-value>true</param-value>
             </init-param>
             <init-param>
             <param-name>maxRequestSize</param-name>
             <param-value>10485760</param-value>
             </init-param>
             </filter>
            
             <filter-mapping>
             <filter-name>ajax4jsf</filter-name>
             <servlet-name>FacesServlet</servlet-name>
             <dispatcher>FORWARD</dispatcher>
             <dispatcher>REQUEST</dispatcher>
             <dispatcher>INCLUDE</dispatcher>
             <dispatcher>ERROR</dispatcher>
             </filter-mapping>
             <!-- RICHFACES -->
            
             <listener>
             <listener-class>
             com.liferay.portal.kernel.servlet.PortletContextListener</listener-class>
             </listener>
             <servlet>
             <servlet-name>userRenderer</servlet-name>
             <servlet-class>com.liferay.portal.kernel.servlet.PortletServlet</servlet-class>
             <init-param>
             <param-name>portlet-class</param-name>
             <param-value>com.empolis.portlet.EmpolisFacesPortlet</param-value>
             <!-- Subclass of GenericFacesPortlet -->
             </init-param>
             </servlet>
             <servlet-mapping>
             <servlet-name>userRenderer</servlet-name>
             <url-pattern>/userRenderer/*</url-pattern>
             </servlet-mapping>
             <welcome-file-list>
             <welcome-file>index.jsp</welcome-file>
             </welcome-file-list>
             <login-config>
             <auth-method>BASIC</auth-method>
             <realm-name>PortalRealm</realm-name>
             </login-config>
            </web-app>


            • 3. Re: Using PortletRequestDispatcher within a JSF Component
              wesleyhales

               

              The component is used in a JSP file named "/jsp/user/userRenderer.jsp"


              The exception you are getting shows
              ServletException: File "/jsp/users/userRenderer.faces" not found
              


              So there is a typo is the "/user" or "/users"?

              OR

              Why are you trying to manually dispatch to a jsp? This is already done for you in the bridge.
              You have the correct mapping, but I have no idea what you are trying to do with this component. Check the typo and play around with removing the dispatch.

              • 4. Re: Using PortletRequestDispatcher within a JSF Component
                s.cindric

                Thank you very much for your reply!

                Unfortunately the typo is only in this posting, so this is not the problem.
                Removing the dispatch is not that simple because the JSF component is a bit more complex and does much more than just including another JSP file.

                So, if the dispatch is not possible anymore in this place, we have to drop a feature from our product.

                I have only one more question. Is it just not intended (and thus not supported) to use a dispatcher within a component or could this be a bug in the portlet bridge?

                • 5. Re: Using PortletRequestDispatcher within a JSF Component
                  wesleyhales

                  The weird thing here is that you are mixing the 2 lifecycles. The portlet bridge specifically handles a facesRequest during Action, Resource and Render phases, so it would take some debugging to see what exactly is going on. The bridge handles the dispatch automatically.
                  The goal of the bridge is to hide the underlying api of the portlet world and let developers write once and run in both servlet and portlet without any specific handling like this.
                  What exactly are you trying to do with this component? include a jsp in encodeBegin? I'm not sure of your usecase, but this seems like you could find another way to handle this without touching the requestDispatcher.