如何实现在Liferay Portal 6.1中点击按钮生成Jasper Report PDF

时间:2015-04-24 14:57:05

标签: pdf jasper-reports reporting

我需要在按钮点击时提供报告生成功能。我使用Liferay Portal 6.1和Tomcat 7作为Web门户,Liferay Developer Studio(Eclipse Indigo)IDE,iReport(用于创建报告模板)和JasperReports库来生成PDF。门户网站是一个票证管理系统,具有两个实体(票证和文档),这些实体通过各自的自定义portlet输入。处于编辑模式时,这两个实体都需要查看报告'功能。我已经广泛地搜索了这个问题的答案,在这里和那里拿起一个片段,但我找到的并不是我的情况。点击“查看报告”后,按钮,用户需要呈现格式化的PDF,然后用户可以决定“保存”,“打印”或“关闭”。从。我还需要将数据传递给报告,以便可以检索打开的实体(即documentId,ticketId,docType等)的信息,但是这篇文章可以在以后添加;一旦我得到一个PDF打开。

不知道如何实现这一点,我决定使用jQuery Modal来打开' viewReport.jsp'页面并处理报告。但是,此方法会产生JRException IllegalState:无法获取OutputStream,因为writer已在使用中。我在我的搜索中读到Liferay布局使用OutputStream,这可能是作者已经在使用的原因。这是我正在使用的代码:

edit_document.jsp (按钮和jQuery模态)

<!-- View Report Button at bottom of form -->
<aui:button type="button" id="viewReportBtn" value="View Report" />



<!-- URL declaration for PDF popup window -->
<portlet:renderURL var="viewReportURL" windowState="<%= LiferayWindowState.EXCLUSIVE.toString() %>" >
    <portlet:param name="mvcPath" value="/html/document/viewReport.jsp" />
    <portlet:param name="documentId" value="<%= Long.toString(documentID) %>" />
    <portlet:param name="ticketId" value="<%= Long.toString(ticketID) %>: />
    <portlet:param name="docType" value="<%= docType %>" /> <!-- This is already a String value -->
</portlet:renderURL>


<!-- jQuery to open popup window for PDF -->
<aui:script use="aui-dialog, aui-overlay-manager, dd-constrain" >

    var reportDialogOptions = {
        title : 'Dialog',
        bodyContent : '',
        centered : true,
        group : default,
        height : 800,
        width : 1000,
        modal : true,
        };


$('#viewReportBtn').on('click', finction(event) {
    var editFeelingDialog = new A.Dialog(
        A.merge(reportDialogOptions, {
                title : 'Document View Report'
                })
                ).plugin(A.Plugin.IO,{uri : '<%= viewReportURL %>'}).render();
});

</aui:script>
  

viewReport.jsp (处理jrxml模板并打开PDF的页面)

&#13;
&#13;
<!-- viewReport.jsp page to render PDF -->
<%@ page contentType = "application/pdf" %>

<%@ page trimDirectiveWhitespaces = "true" %>

<%@ page import = "net.sf.jasperreports.engine.*" %>

<%@ page import = "java.io.File" %>
<%@ page import = "java.io.FileInputStream" %>
<%@ page import = "java.io.FileNotFoundException" %>
<%@ page import = "java.io.InputStream" %>

<%@ page import = "java.sql.Connection" %>
<%@ page import = "java.sql.SQLException" %>

<%

	Connection conn = null;
	
	try
	{
		String url = "jdbc:oracle:thin:@myDBSRV:1521:myDatabase";
		String userName = "myUsername";
		String password = "myPassword";
		
		// Connecting to the Oracle database
		Class.forName("oracle.jdbc.driver.OracleDriver");
		conn = DriverManager.getConnection(url, username, password);
		
		// Loading the Jasper Report file from local file system\
		String jrxmlFile = session.getServletContext().getRealPath(request.getContextPath())+"\\report5.jrxml";
		InputStream input = new FileInputStream(new File(jrxmlFile));
		
		// Generate the report
		JasperReport jasperReport = JasperCompileManager.compileReport(input);
		JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPrint, null, conn);
		
		// Export the report as a PDF
		JasperExportManager.exportReportToPdfStream(jasperPrint, response.getOutputStream());
		
	}
	catch (FileNotFoundExcecption ex)
	{
		System.out.println(ex.getMessage());
		ex.printStakeTrace();
	}
	catch (JRException ex)
	{
		System.out.println(ex.getMessage());
		ex.printStakeTrace();
	}
	catch (ClassNotFoundException ex)
	{
		System.out.println(ex.getMessage());
		ex.printStakeTrace();
	}
	catch (SQLException ex)
	{
		System.out.println(ex.getMessage());
		ex.printStakeTrace();
	}
	finally
	{
		if (conn != null)
		{
			conn.close();
		}
	}

%>
&#13;
&#13;
&#13;   

我还尝试将java方法添加到我的DocumentPortlet.java类中,并在单击按钮时调用方法,但是我对ajax的熟悉程度不是很正确:
DocumentPortlet.java

&#13;
&#13;
public class DocumentPortlet extends MVCPortlet{

	
Connection conn = null;


// More methods for saving, editing, and deleting documents are here...



public void generateReport()
	{

		initConnection();
		showReport();

	}
	
	public void initConnection()
	{

		String host = "jdbc:oracle:thin:@ncimsdbsrv:1521:ncimsdev";
		String userName = "lportal";
		String password = "NSS4207itnp";
	
		try
		{
			Class.forName("oracle.jdbc.driver.OracleDriver");
		}
		catch(ClassNotFoundException ex)
		{
		ex.printStackTrace();
		}
	
		try
		{
			conn = DriverManager.getConnection(host, userName, password);
		}
		catch (SQLException ex)
		{
			ex.printStackTrace();
		}

	}	



	public void showReport()
	{

		//Path to your .jrxml file
		String reportName = "[path to file]";
	
		//Get a stream to read the file
		InputStream is = this.getClass().getClassLoader().getResourceAsStream(reportName);
	
		try
		{
			//Fill the report with parameter, connection, and stream reader
			JasperPrint jp = JasperFillManager.fillReport(is, null, session);
		
			//Viewer for Jasper report
			JRViewer jv = new JRViewer(jp);
		
			//Insert viewer to a JFrame to make it showable
			JFrame jf = new JFrame();
			jf.getContentPane().add(jv);
			jf.validate();
			jf.setVisible(true);
			jf.setSize(new Dimension(800, 600));
			jf.setLocation(300, 100);
			jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		}
		catch (JRException ex)
		{
			ex.printStakeTrace();
		}
		finally
		{
			closeSession(session);
		}

	}

}
&#13;
&#13;
&#13;

如何以用户点击按钮并在屏幕上生成PDF的方式提供此功能?我需要一个清晰简洁的解决方案来解决这个问题。谢谢!

1 个答案:

答案 0 :(得分:0)

如果有人有兴趣,我在Liferay论坛上找到答案。我的实施不正确。所以现在我在我的

中有这个

<强> viewDocument.jsp:

&#13;
&#13;
<!-- View Report button at bottom of form -->
<aui:button id="viewReportBtn" value="View Report" />

<!-- URL declaration for PDF generation -->
<portlet:resourceURL id="generatePDF" var="generateReportURL" >
  <portlet:param name="jspPage" value="/html/document/viewReport.jsp" />  
  <portlet:param name="docType" value="<%= docType %>" />
</portlet:resourceURL>


<!-- AJAX call to resource request handler in DocumentPortlet.java file -->
<aui:script use="aui-dialog, aui-overlay-manager, dd-constrain" >
  
  $(document).ready(function()
  {
      
        $('#viewReportBtn').click(function(event)
        {
            
          $.ajax('<%= generateReportURL %>');
          
        }  
  
  });
&#13;
&#13;
&#13;

我还在我的Portlet java文件中创建了ResourceRequestHandler,如下所示:

<强> DocumentPortlet.java:

&#13;
&#13;
public class DocumentPortlet extends MVCPortlet{

  Connection conn = null;

  // More methods to add, update, and delete here


  @Override
  public void serveResource(ResourceRequest request, ResourceResponse response)
      throws IOException, PortletException
  {
      String url = "jdbc:oracle:thin:@myDatabaseSrv:1521:myDatabaseSid";
      String user = "myUserName";
      String pass = "myPassword";

      String docType = ParamUtil.getString(request, "docType");

      try
      {

          // Connect to database
          Class.forName("oracle.jdbc.driver.OracleDriver");
          conn = DriverManager.getConnection(url, user, pass);

          // Load JRXml file from local file system
          String jrxmlFile = "C:\\Reports\\report5.jrxml";
          InputStream input = new FileInputStream(new File(jrxmlFile));

          // Generate report
          JasperReport jasperReport = JasperCompileManager.compileReport(input);
          JasperPrint jasperPrint = JasperFillManager.fillReport(jasperPrint, null, conn);

          
          /***** Display PDF in Adobe Reader *****/
         
          // Create new OutputStream where data is written to byte array[]
          ByteArrayOutputStream output = new ByteArrayOutputStream();

          // Export the report to PDF format
          JasperExportManager.exportReportToPdfStream(jasperPrint, output);

          // Create a String for thr report title
          final String fileName = docType + ".pdf";

          //Create a new stream and call the report
          OutputStream pdfFile = new FileOutputStream(new File(fileName));

          //Write the PDF
          pdfFile.write(output.toByteArray());
 
 
          //Clean the PDF
          pdfFile.flush();
 
          //Close it
          pdfFile.close();
 
          //Run the brand new PDF report
          final String PDF_RUN = "rundll32 url.dll, FileProtocolHandaler " + fileName; 
 
          //Execute the command
          Runtime.getRuntime().exec(PDF_RUN); 

      }
      catch(FileNotFoundException ex)
      {
          System.out.println("File not found on file system, check file path!!" + ex.getMessage());
          ex.printStackTrace();
      }
      catch(JRException ex)
      {
          System.out.println("Error in Jasper Report!!" + ex.getMessage());
          ex.printStackTrace();
      }
      catch(ClassNotFoundException ex)
      {
          System.out.println("Oracle Class for driver not found!!" + ex.getMessage());
          ex.printStackTrace();
      }
      catch(SQLException ex)
      {
          System.out.println("Error getting connection to database!!" + ex.getMessage());
          ex.printStackTrace();
      }

    }

}
&#13;
&#13;
&#13;

这消除了我得到的IllegalStateException,并且会在Adobe Reader中打开pdf,但是,它会在服务器上打开它。因此,问题仍然存在。有人知道如何在客户机上打开这个pdf吗?