2011-04-14 30 views
7

我試圖轉換並將JSF頁導出爲PDF。我嘗試了以下方式:JSF 2.0使用Flying Saucer將XHTML頁轉換爲PDF:java.lang.IllegalStateException

豆:

public void createPDF() { 
    try { 
     ITextRenderer renderer = new ITextRenderer(); 
     renderer.setDocument(new URL(url).toString()); 
     renderer.layout(); 
     HttpServletResponse response = (HttpServletResponse) externalContext.getResponse(); 
     response.reset(); 
     response.setContentType("application/pdf"); 
     response.setHeader("Content-Disposition", "inline; filename=\"" +PDF_FILE_NAME+ "\""); 
     OutputStream browserStream = response.getOutputStream(); 
     renderer.createPDF(browserStream); 
    } catch (Exception ex) { 
     Logger.getLogger(PdfBean.class.getName()).log(Level.SEVERE, null, ex); 
    } 
} 

頁與創建PDF按鈕/home.xhtml

<ui:define name="content"> 
    <center> 
     <h:form id="pdfgen"> 
      <h:panelGrid columns="2"> 
       <h:outputText value="Enter Name:"/> 
       <h:inputText value="#{pdfBean.name}"/> 
      </h:panelGrid> 
      <h:commandButton value="Create PDF" action="#{pdfBean.createPDF()}"/> 
     </h:form> 
    </center> 
</ui:define> 

,我要轉換的頁面:

<ui:define name="content"> 
    <center> 
     <h:outputText value="Hello #{pdfBean.name}"/> 
    </center> 
</ui:define> 

當我嘗試只獲得一次PDF時,那麼永遠不會。我有以下Facelet異常:

SEVERE: Error Rendering View[/home.xhtml] 
java.lang.IllegalStateException: PWC3991: getOutputStream() has already been called for this response 
... 
WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception 
java.lang.IllegalStateException: PWC3991: getOutputStream() has already been called for this response 

我在做什麼錯?

更新豆:看到BalusC的回答是:

public void createPDF() { 
    FacesContext facesContext = FacesContext.getCurrentInstance(); 
    ExternalContext externalContext = facesContext.getExternalContext(); 
    String servername = externalContext.getRequestServerName(); 
    String port = String.valueOf(externalContext.getRequestServerPort()); 
    String appname = externalContext.getRequestContextPath(); 
    String protocol = externalContext.getRequestScheme(); 
    this.url = protocol + "://" + servername + ":" + port + appname + PDF_PAGE; 
    try { 
     ITextRenderer renderer = new ITextRenderer(); 
     renderer.setDocument(new URL(url).toString()); 
     renderer.layout(); 
     HttpServletResponse response = (HttpServletResponse) externalContext.getResponse(); 
     response.reset(); 
     response.setContentType("application/pdf"); 
     response.setHeader("Content-Disposition", "inline; filename=\"" + PDF_FILE_NAME + "\""); 
     OutputStream browserStream = response.getOutputStream(); 
     renderer.createPDF(browserStream); 

    } catch (Exception ex) { 
     Logger.getLogger(PdfBean.class.getName()).log(Level.SEVERE, null, ex); 
    } 
    facesContext.responseComplete(); 
} 

回答

8

您需要指示JSF,你已經採取了應對你的手在處理和JSF不能處理默認導航時的動作方法完成。這增加了操作方法的末尾:

facesContext.responseComplete(); 

更新按照該意見,你所訪問ExternalContext作爲一個實例變量,這表明您分配它和FacesContext爲類變量,可以是static或作爲會話範圍的bean的屬性。這絕對是一個壞主意。你應該通過FacesContext#getCurrentInstance()得到他們的手在本地方法內分配它們作爲類變量。它們被綁定到一個特定的請求線程,而這個線程在下一個請求中不再存在。

+0

我仍然在行中得到非法狀態錯誤(PdfBean.java:58)。這正是我把facesContext.responseComplete();也許我的做法是錯誤的? – reen 2011-04-14 14:32:22

+0

如果它拋出'IllegalStateException',那麼這意味着在那個時候不再有'FacesContext'。然而,我並沒有看到任何可能的原因。在你的問題中,你是否有更多的代碼? – BalusC 2011-04-14 14:40:27

+1

我現在看到它。查看答案更新。 – BalusC 2011-04-14 14:56:18