2011-07-29 41 views
5

Tengo un problema para implementar una redirección HTTP simple.Liferay Portlet y JSF: Redirigir durante la fase de procesamiento

utilizo Liferay 6.0.6, nuestros portlets están construidas con JSF2.0/PortletFaces.

Quiero llamar a una redirección cuando se carga una vista (y no cuando se desencadena una acción). Actualmente, mi función es llamada por el oyente PreRenderView.

<f:metadata> 
    <f:event listener="#{myControler.dispatch}" type="preRenderView" /> 
</f:metadata> 

En esta función, puedo comprobar los permisos, hacer otras cosas, y en algunos casos quiero redirigir al usuario a una página nueva (no otra vista).

Intenté varios métodos, sin éxito. Específicamente, pensé que este método funcionaría:

getFacesContext().getExternalContext().redirect(url); 
getFacesContext().responseComplete() 
// => Can only redirect during ACTION_PHASE 

Este error es lógico, pero hay una solución para fuerza la redirección.

Podría ser realizado en otra función, llamada de otro modo, sólo necesito la Session de Hibernate (juego al comienzo de la fase de Render)

tiene ideas para resolver este problema?
Gracias!

ps: <redirect /> o ?faces-redirect no funcionan con los portlets.

Respuesta

9

No puede hacer esto en la fase de procesamiento por diseño. Razones:

  • Es posible que los portlets se prestan de forma asíncrona, por lo que ya es posible que aparezca la página cuando se está representando el portlet
  • Es posible que algunas partes de la página ya se entregan al cliente, por lo que el HTTP Los encabezados ya están enviados, por este motivo, por diseño, no tiene acceso a ellos en la fase de procesamiento
  • ¿Cuál sería el resultado esperado si dos portlets renderizados en la misma página decidieran que les gustaría reenviarlos a ¿otra página? ¿Quién ganaría?

Una solución hacky es hacer que algunos redireccionamiento de JavaScript, pero esto es muuuy un-portal-like y pueden estropear las expectativas de otros (más, partes de la página ya podrían ser prestados, haciendo que sus usuarios a rellenar un formulario sólo para ser redirigido por su rutina Javascript

favor repensar el problema y llegar a una solución diferente -. realmente vale la pena hacer esto en un entorno de portal

+1

Gracias por su explicación.Pensaré en otra solución y refactorizaré la arquitectura de mi portlet si es necesario. –

+0

Otra solución _hacky_ es usar PortalUtil.getHttpServletResponse para encontrar la solicitud HTTP original y usar sendRedirect allí. –

+0

@TobiasLiefke * too * hacky En mi humilde opinión, es posible que la respuesta ya se haya cometido durante el tiempo de renderizado. O el portlet podría entregarse a través de Ajax, ni siquiera como parte de la página completa. Podría funcionar, pero también podría funcionar ahora y fallar en alguna actualización futura del servidor de aplicaciones ... –

0

Utilice el método siguiente que va a funcionar

public static void redirect(final String url) throws IOException { 

      final javax.portlet.PortletResponse portletResponse 
      = getPortletResponse(); 

      if (portletResponse instanceof ActionResponse) { 

       final javax.portlet.ActionResponse actionResponse 
       = (javax.portlet.ActionResponse) portletResponse; 

       actionResponse.sendRedirect(url); 

      } else if (portletResponse instanceof ResourceResponse) { 

       final FacesContext ctx = FacesContext.getCurrentInstance(); 
       if (ctx.getPartialViewContext().isPartialRequest()) { 

        final ResourceResponse portletResResp 
        = (ResourceResponse) portletResponse; 
        PartialResponseWriter pwriter; 
        final ResponseWriter writer = ctx.getResponseWriter(); 
        if (writer instanceof PartialResponseWriter) { 
         pwriter = (PartialResponseWriter) writer; 
        } else { 
         pwriter = ctx.getPartialViewContext() 
         .getPartialResponseWriter(); 
        } 
        portletResResp.setContentType(Constants.CONTENT_TYPE); 
        portletResResp.setCharacterEncoding(Constants.ENCODING_TYPE); 
        // addResponseHeader("Cache-Control", "no-cache"); 
        pwriter.startDocument(); 
        pwriter.redirect(url); 
        pwriter.endDocument(); 
        ctx.responseComplete(); 
       } else { 
        throw new UnsupportedEncodingException(
          "Can only redirect during RESOURCE_PHASE " 
          + "if a Partial-(JSF AJAX)-Request has " 
          + "been triggered"); 
       } 
      } else { 
       throw new UnsupportedEncodingException(
         "Can not redirect during the current phase: " 
         + portletResponse.getClass().getSimpleName()); 
      } 
     } 
.
+0

Lo siento, pero no va a funcionar, porque quiero redirigir durante una RenderPhase (con portletResponse istanceof RenderResponse). Así que obtendré un "No puedo redirigir durante la fase actual" –

0

Lo uso y funciona para mí:

public void preRenderView() throws IOException { 

     if (!checkUtente()) { 

       FacesContext fc = FacesContext.getCurrentInstance(); 

       NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler(); 

       navigationHandler.handleNavigation(fc, null, "errore.xhtml?faces-redirect=true"); 

       fc.renderResponse(); 
     } 

    } 
Cuestiones relacionadas