2011-07-29 14 views
5

Mam problem z zaimplementowaniem prostego przekierowania HTTP.Liferay Portlet i JSF: Przekierowanie podczas fazy renderowania

używam Liferay 6.0.6, nasze portletów budowane są z JSF2.0/PortletFaces.

Chcę wywołać przekierowanie po załadowaniu widoku (a nie po wywołaniu działania). Obecnie moja funkcja jest wywoływana przez detektor PreRenderView.

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

W tej funkcji można sprawdzić uprawnienia, robić inne rzeczy, a w niektórych przypadkach Chcę przekierować użytkownika do nowej strony (nie inny widok).

Próbowałem kilku metod, bez powodzenia. Konkretnie, myślałem, że ta metoda będzie działać:

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

Ten błąd jest logiczne, ale czy istnieje rozwiązanie życie przekierowania.

To może być realizowane w innej funkcji, zwany inaczej, muszę tylko Hibernate Session (ustawiony na początku fazy renderowania)

masz pomysły, aby rozwiązać ten problem?
Dzięki!

ps: <redirect /> lub ?faces-redirect nie działają z portletami.

Odpowiedz

9

Nie można tego zrobić w fazie renderowania według projektu. Przyczyny:

  • Jest możliwe, że portletom świadczone są asynchronicznie, więc może już być wyświetlane na stronie, gdy portlet jest renderowany
  • Jest możliwe, że części strony zostały już dostarczone do klienta, tak, że HTTP Nagłówki są już wysłane - z tego powodu, według projektu nie masz do nich dostępu w fazie renderowania.
  • Jaki byłby oczekiwany wynik, jeśli dwa portlety wyrenderowane na tej samej stronie zdecydowałyby, że chcesz je przekazać dalej? inna strona? Kto by wygrał?

hacky obejście jest świadczenie niektórych JavaScript przekierowanie, ale to veeeery un-portal-podobne i może zepsuć nawzajem oczekiwania (plus części strony może już być renderowane, powodując użytkowników do wypełnienia formularza tylko być przekierowywane przez JavaScript rutyny

proszę przemyśleć problem i wymyślić inne rozwiązanie. - to naprawdę warto robić to w portalu środowiska

+1

Dziękuję za wyjaśnienia.Pomyślę o innym rozwiązaniu i jeśli to konieczne, zmienię architekturę portletu. –

+0

Innym _ackim_ rozwiązaniem jest użycie portalu PortalUtil.getHttpServletResponse w celu znalezienia oryginalnego żądania HTTP i użycia sendRedirect. –

+0

@TobiasLiefke * też * hacky IMHO - odpowiedź mogła już zostać zatwierdzona podczas renderowania. Lub portlet może być dostarczany za pośrednictwem Ajax, nawet jako część całej strony. To może zadziałać, ale może również zadziałać teraz i przerwać jakąś przyszłą aktualizację appserver ... –

0

Użyj poniżej metoda będzie działać

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

Przepraszam, ale to nie zadziała, ponieważ chcę przekierować podczas RenderPhase (z portletResponse istanceof RenderResponse). Więc otrzymam komunikat "Nie mogę przekierować w obecnej fazie" –

Powiązane problemy