Tuesday, June 18, 2013

 

This Blog has been replaced by

http://blogs.smart-itc.com.au


Wednesday, January 12, 2011

Windows network PDF Printing (as as service) with PDF Creator

Here are some instructions for a Windows network PDF printer using PDF Creator. It installs and works out of the box, but I wanted PDF Creator to start as a service when the server was started/rebooted. This took a bit of research.

The following instructions relate to a Windows domain network, where each user has a home directory on a central file server. When a user prints to the shared PDF Printer, the PDF document is saved in their Home Directory.

Here are the steps -

Download PDF Creator (http://sourceforge.net/projects/pdfcreator) and perform the *Server* install on your print server. If you're upgrading, uninstall the old version and remove the service (next step)

Register PDF Creator as a service
At the command prompt, execute the following. The 1st line removes the service if you're upgrading -
sc delete "PDF Creator"
sc create "PDF Creator" start= auto binpath= "srvany.exe"
sc description "PDF Creator" "PDFs Printing"

Update  Registry
You need to update the registry on the server to associate PDFCreator.exe with srvany.exe
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\PDF Creator\Parameters]
"Application"="C:\\Program Files\\PDFCreator\\PDFCreator.exe"

Start the service
Open windows services and start the PDF Creator service. Make sure the start-up type is automatic.

Configure PDF Creator
Start PDF Creator Print Monitor (Under start menu) and open the options (Printer menu -> Options). On the Auto-Save tab check 'Use Auto-save" and "User this directory for auto-save". I used the following. The directory saves the PDF in the user's home directory. The time stamp in the file name is to ensure each PDF has a unique name. NB: Emailing will not work. If you enable it on the shared printer, its the server that will open outlook and attach the PDF, not the user's PC.
Filename: <REDMON_DOCNAME>-<DateTime>
Directory: \\fileserver\users\<REDMON_USER>\

Connect from a remote PC
Install your PDF shared printer on another pc and print a test page. If you open the PDF Creator Print Monitor on the server you should see the document listed, and disappear if the print is successful.

Troubleshooting
In PDF Creator Print Monitor (on the server) the first icon (of the printer) should have a green dot to indicate it's running. If the dot is red try restarting the service, PDF Creator Server Monitor or it all else fails, reboot the server.

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"