Tuesday, January 11, 2011

Jasper Reports Server : PHP PDF Reporting

Reports from PHP using Jasper

I have a PHP web application which needed a new reporting engine. The old engine did nothing more than create html page reports. Yes, it was functional and easy to maintain, but for stylish printable reports that my clients can give to their customers or management, I needed something more.

Enter Jasper Reports (www.jasperforge.org)! I first used Jasper Reports and iReports about 5 years ago in a Java app. My, how it has matured, especially iReports!.

I played around with Jasper for several hours over a week, and with little effort ended up with a reporting system  integrated into my PHP web app.

This is what I ended up with - ok I didn't do it all, JasperForge has all the cool bits. I only had to work out the SOAP client bit in PHP!

Now my reporting system workflow looks like this -

  • I can visually design and test reports locally on my PC.
  • I then upload a report from iReports to the Jasper Server (its on a remote machine)
  • A simple SOAP request from PHP in my web app generates a report as PDF (or other formats).
  • Jasper Server's scheduling system also means I can set up automatic report generating and emailing. Neat!
Basic process to get started

Here is what I did. It's well documented on JasperForge.org. Spend some time reading through the FAQs and Tutorials.
  • Download iReports (Visual Reports Designer) to my windows workstation.
  • Download Jasper Server and install it on my remote linux web server. (I had to open ports in the firewall to get iReports to connect the the Jasper Server).
iReports has a plugin to connect to a Jasper Server to upload and manage reports. I created a report and got it working locally (using a local JDBC/MySQL datasource) first before uploading it to the Jasper Server.

I logged into the Jasper Server Web Interface to configure a data source and parameters (input controls) for the report, but most of this can be done from iReports.

This is the bit I had to figure out myself (I've never worked with SOAP before). I created this PHP code using bits and pieces from similar clients and the sample Jasper code. It creates a SOAP request to the Jasper Server to generate a PDF report, and outputs it to the callers browser.

<?php
  set_time_limit(120); // sets max_execution_time
  ini_set("memory_limit", "8M");

  header('Content-type: application/pdf');
  header("Content-Disposition: attachment; filename=CurrentListings.pdf");

  $wsdl = "http://HOSTNAME:8080/jasperserver/services/repository?wsdl";
  $username = "jasperadmin"; // I'm just using the default here
  $password = "jasperadmin"; // I'm just using the default here
  $format = "PDF"; // Could be HTML, RTF, etc (but remember to update the Content-Type header above)
  $report = "/REPORT/ID"; // Get this from Jasper Server Web Admin
  $imageURL = 'http://HOSTNAME/image'; // This is a report parameter passed in.

  $client = new SoapClient($wsdl, array('login' => $username, 'password' => $password, "trace" => 1, "exceptions" => 0));

  $request = "<request operationName=\"runReport\" locale=\"en\">
      <argument name=\"RUN_OUTPUT_FORMAT\">$format</argument>
      <resourceDescriptor name=\"\" wsType=\"\"
      uriString=\"$report\"
      isNew=\"false\">
      <label>null</label>
      <parameter name='imageURL' isListItem='false'>$imageURL</parameter>
      </resourceDescriptor>
    </request>";

   $client->runReport($request);
   echo $client->__getLastResponse();
?>


Gotchas to Note

PHP (I'm using 5.3) threw an exception at the SOAP request, reporting that it did not get an XML document back.The solution was to add exceptions = 0 to the options, and use $client->__getLastResponse() to get the PDF output. My quick research on php.net and Google leads me to think that PHP is very picky about the XML responses it receives (it cannot have leading spaces in the response for example) and that Jasper Server's XML response somehow upsets the PHP SOAP class. I'll revise this post if/when I learn more.

Its worth noting that you can call a url on the Jasper Server to output a report directly (see Jasper Server User's Guide). I opted for the above method because it give me more control over the request and integrates better to the PHP web app.

Other Alternatives for PHP Reporting

Other alternatives to Jasper I have tried are below. There are not full instructions to get them working, you'll need to do a little research yourself for that.

Using PHP/Java Bridge (http://php-java-bridge.sourceforge.net/pjb/)

PHP/Java Bridge lets you execute Java code (Which JasperReports is written in) from PHP.

My intentions here was to compile and fill a report from PHP using Java.

After installing PHP/Java Bridge (I just ran JavaBridge.jar) I ended up with this php code, copied mostly form JasperForge.org's getting started guide.

<?php

  // Important: Requires allow_url_include = On in php.ini
  require_once "http://HOSTNAME:8081/JavaBridge/java/Java.inc";

  header('Content-type: application/pdf');

  $class = new JavaClass("java.lang.Class");
  $class->forName("com.mysql.jdbc.Driver");
  $driverManager = new JavaClass("java.sql.DriverManager");
  $conn = $driverManager->getConnection("jdbc:mysql://HOSTNAME/DATABASE?  user=USERNAME&password=PASSWORD");

  $compileManager = new JavaClass("net.sf.jasperreports.engine.JasperCompileManager");
  $report = $compileManager->compileReport(realpath("report.jrxml"));
  $fillManager = new JavaClass("net.sf.jasperreports.engine.JasperFillManager");
  $params = new Java("java.util.HashMap");
  $params->put("imageURL", "http://HOSTNAME/image"); // Pass a report parameter
  $emptyDataSource = new Java("net.sf.jasperreports.engine.JREmptyDataSource");
  $jasperPrint = $fillManager->fillReport($report, $params, $conn);
  $exportManager = new JavaClass("net.sf.jasperreports.engine.JasperExportManager");
  $outputPath = realpath(".")."/"."output.pdf";
  $exportManager->exportReportToPdfFile($jasperPrint, $outputPath);
?>

This method worked, but I ended up spending more time mucking around the the PHP/Java Bridge and reports and it did not not add anything of value for me compared to the Jasper Server solution. The biggest headache was identifying all the necessary JAR files required by JasperReports and include them will the bridge. Obviously, JasperServer already takes care of all that for you.


I'm very impressed with this tool. I've been looking for one like it for years! It's a command line tool that renders a web page using WebKit and outputs it as PDF. Using this for a PDF generating reporting engine worked, but because it's base on a web page you don't have control over headers, footers, grouping etc.

After installing the toolkit, I used this PHP code to generate a PDF report. It took a little effort to get the command line and file redirections working (wkhtmltopdf also has link to a PHP extension (source code), but I did not try it.)

<?php
  header('Content-type: application/pdf');
  header("Content-Disposition: attachment; filename=PropertyViewsReport.pdf");

  $tempDir = "C:/tmp";
  $tmpFileSrc = tempnam($tempDir, "report");
  $tmpFileDest = tempnam($tempDir, "report");

  ob_start();
  include "propertyViewsReport.report.html.php"; // This script generates the HTML report.
  $c = ob_get_contents();
  ob_end_clean();

  $cmd = "\"C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe\" \"$tmpFileSrc\" \"$tmpFileDest\"";

  $retVal = null;
  system($cmd, $retVal);

  readfile($tmpFileDest);

  unlink($tmpFileSrc);
  unlink($tmpFileDest);
?>

Other PHP SOAP Clients


I tried other PHP Jasper SOAP clients, including one from JasperForge.org, but looked for other solutions when I could not get them to easily work. Try Googling "Jasper PHP Soap Client"

5 comments:

  1. Hello I wana integrate jasper report with mysql.

    I have followed steps as per installation document.but i am not able to see anything on when I tried to http://localhost:8080/jasperserver/login.html

    it's redirect to home.html. i am not able to find any solution.

    ReplyDelete
  2. Look at Reportico.... ( http://www.reportico.org/site/index.php) You don't require jasper server or jasper ireport. A complete reporting engine in php which requires minimum resources.

    ReplyDelete
  3. Hi thanks for your tutorial, i've been working with Ireports+JavaBridge+php and Extjs 4.x , (win winXp) but recently i acquired a laptop with win8, but now the javabridge give error, maybe for the OS, my question is: Can i run the jasperserver and ireports in the same machine with no problems? thanks

    ReplyDelete
  4. I like to work on PHP rather than .NET, though .NET presents the ability of drag and drop elements, however I like PHP a lot.

    TOP 10 Podiatry Website Design, Click to view examples.

    ReplyDelete