2011-07-29 6 views
5

간단한 HTTP 리디렉션을 구현하는 데 문제가 있습니다. Liferay 포틀릿 및 JSF : 렌더링 도중 리디렉션

나는 JSF2.0/ PortletFaces에 구축되어있는 Liferay 6.0.6, 우리의 포틀릿를 사용합니다.

보기가로드 될 때 (작업이 트리거 될 때가 아니라) 리디렉션 을 호출하려고합니다. 현재, 내 기능은 PreRenderView 리스너에 의해 호출됩니다. 이 기능에

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

, 내가 다른 물건을 할, 권한을 확인 할 수 있으며, 어떤 경우에 나는 새 페이지 (다른보기)로 사용자를 리디렉션 할.

여러 방법을 시도했지만 실패했습니다. 은 특히,이 방법이 작동 것이라고 생각 :

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

이 오류는 논리적이지만, 리디렉션에 대한 해결책이있다.

나는 단지

이 문제를 해결하기 위해 당신에게 아이디어를 가지고 최대 절전 모드 세션 (렌더링 단계의 시작 부분에 세트)가 필요합니다, 그렇지 않으면라는 다른 함수에서 실현 될 수

?
감사!

ps : <redirect /> 또는 ?faces-redirect은 포틀릿과 작동하지 않습니다.

답변

9

의도적으로 렌더링 단계에서이를 수행 할 수 없습니다. 이유 :

  • 그것은 페이지가 이미 표시 될 수 있도록 포틀릿가 렌더링 될 때 포틀릿이 비동기 적으로 렌더링되는 것을 가능
  • 이 페이지의 일부가 이미 있도록 클라이언트로 전달되는 것을 가능은 HTTP 헤더가 이미 전송되었습니다. 이러한 이유로 렌더링 단계에서 디자인에 액세스 할 수 없습니다.
  • 동일한 페이지에 렌더링 된 두 개의 포틀릿이 전달할 것인지 결정할 경우 예상되는 결과는 무엇입니까? 다른 페이지? 누가 이길 것입니까?

해키 해결 방법은 리디렉션 일부 자바 스크립트 렌더링하는 것입니다, 그러나 이것은 veeeery 않은 포털과 같은 수 있습니다 엉망의 다른 기대 (플러스, 페이지의 일부는 이미 렌더링 할 수있는, 사용자를 일으키는 것은 양식을 작성하는 것입니다 만 자바 스크립트 루틴에 의해 리디렉션하는

문제를 재고하고 다른 해결책을 마련하십시오 -. 그건 포털 환경에서이 일을 정말 가치

+1

당신의 설명에 감사드립니다.필요하다면 다른 솔루션으로 생각하고 내 포틀릿 아키텍처를 리팩터링합니다. –

+0

또 다른 _hacky_ 해결 방법은 PortalUtil.getHttpServletResponse를 사용하여 원본 HTTP 요청을 찾고 sendRedirect를 사용하는 것입니다. –

+0

@TobiasLiefke * too hacky IMHO - 응답이 이미 렌더링 시간 동안 커밋되었을 수 있습니다. 또는 포틀릿은 Ajax를 통해 전달 될 수 있으며 전체 페이지의 일부로 제공되지는 않습니다. 그것은 작동 할 수도 있지만, 그것은 또한 지금 작동하고 appserver의 미래의 업데이 트에서 휴식 수도 ... –

0

를 사용하여 아래의 방법이

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

RenderPhase (portletResponse istanceof RenderResponse) 중에 리디렉션하고 싶기 때문에 미안하지만 작동하지 않습니다. 그래서 "현재 단계에서 리디렉션 할 수 없습니다" –

0

나는 이것을 사용하며 나를 위해 일한다 :

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(); 
     } 

    } 
관련 문제