Jasper Reports and PHP
Update October 27th, 2007: I have written a more recent entry that should make life a lot easier.
I’m sure most of us have come across Jasper Reports at some stage. Jasper gives Java developers a complete reporting infrastructure so dynamic reports can be generated from databases in a pretty, printer friendly format.
It has many similarities to the infamous Crystal Reports. It is however, completely open source and designed from the ground up to be flexible, extendable and valuable.
In short: it rocks.
So, how do we get this cool functionality with PHP? Well the obvious solution is to do it all in Java and use the good ole exec (or similar) to create the report and throw the output back to the browser. There are a couple of issues with this however that make it undesirable:
- It is slow. Every time a report is generated we have to wait for the Java virtual machine to start, execute the code and unload again. Not the best.
- Passing parameters between PHP and Jasper becomes troublesome. You will have to pass things either through the exec command, or use something like popen so you can communicate to and from Java though standard in / out.
Thankfully we can have PHP talk to Java efficiently through the excellent work of the guys at PHP/Java Bridge.
The bridge works by having a Java “server” running in the background. Communication is done between the VM and PHP through a light weight network protocol. This approach has a number of advantages including stability (something that the normal PHP extension has failed to achieve) and it neatly address our two major concerns above.
All is not rosy however. The PHP/Java Bridge comes with its own set of challenges, especially when dealing with Jasper.
- The current directory of the JVM (or “user.dir”) is unknown.
Jasper has a funny way of achieving things. First, it takes a nicely formatted XML file as input and converts this into a temporary Java source file. It then compiles this .java file through javac. After that it loads it up, passes any params to it and gets it to create a report that can be exported to a variety of formats. Sounds complicated but this approach really makes things more flexible.
We run into problems here when jasper comes to creating the java source representation of the XML .jrxml file. By default, jasper will create the temp file in the current working directory. Unfortunately this is usually root (/), which the JVM has no write access to (thankfully) so it dies a horrible screaming death.
This can be overridden by setting the System property “jasper.reports.compile.temp”, however this does not appear to work when setting it through PHP.
- Classpaths are all screwy. I actually have 1 installation of the bridge that by all rights should not be working as the required Jars are not in the classpath of the JVM at all. The issues, unfortunately, are usually the other way around.
This issue raises its head once the java file is created and now needs to be compiled. For some reason, any Jars that are added to the classpath through the java_require command are not available to the javac call when jasper wants to go ahead and compile the java source file.
Once again, there is a system property that can be used as the class path for Jasper, this is “jasper.reports.compile.class.path”. However, as I mentioned above, setting this in PHP does not work.
- Relative directories are a no-no.
Because PHP and java are running separately, each has their own “working” directory. We cannot simply pass java a file and expect it to know what path it is in. Use absolute paths for everything in Java.
Fortunately there are a couple of solutions for the above. The first is altering the way PHP creates a JVM. By modifying the java options in php.ini we can make PHP connect to the java server through a TCP socket. We can then start the java server through a simple java command with the appropriate class path and user.dir settings passed through the command line. The drawback to this approach is that it means we have to start the java server separately to the web server, and the whole thing will come crashing down around us if we start apache without java running.
An alternative is to write another java server based on the standard one that comes with the bridge to have the environment setup the way we want. The problem with this approach is that we are lazy and time is money.
The other option that I thought of and the one I’ve gone with is creating a little wrapper class to set the appropriate system properties before creating the Jasper report.
And here it is: download
To use, compile and package it up into a .jar file for use by the bridge.
This class takes away most of the pain in creating a jasper report. It provides utility functions for retrieving the parameters a report requires and exporting reports to the default supported formats. It also manages a cache of the reports so they don’t have to be recompiled each time they are run, which is the most expensive part of the whole process.
We can then use the following code to run a report. Remember that $javaParams is a Java HashMap of java objects, not a PHP array:
Or this to get a listing of all the params a report requires. Note that I had to convert between the java HashMap and the PHP associative array:
Now, we have to make sure we pass java values back as parameters to the runReport function above. Thankfully there are not that many java types we can use as Jasper parameters and most of them take strings in one form or another. You may find this function useful for converting between PHP and Java values:
Okay, now a few words of wisdom to finish up this little post to help get you to Jasper Reports nirvana:
- Read the PHP/Java Bridge documentation.
- Read the Jasper Tutorial.
- Java errors do not usually print as PHP errors. Check your apache error log!
- I have not tried this on windows, just linux
- You do not need to register with anyone to obtain the releases regardless of what the websites say, get them directly from sourceforge:
http://sourceforge.net/projects/jasperreports/
http://sourceforge.net/projects/ireport/ - A background in crystal or similar will help a lot, alternatively considering purchasing one of the ultimate guides
- Feel free to ask.


February 13th, 2007 at 7:37 pm
what do you mean with $jasperClassPath? I don’t understand.
Where do you put jasper class?Thanks b4
February 13th, 2007 at 7:45 pm
how about with $tempFile = tempnam(TMP, ”);. Please help me.
February 15th, 2007 at 4:07 pm
$jasperClassPath is a string with the absoulte paths to all the required Jasper jar files. It is passed directly to java as the classpath to use when compiling jasper report.
$tempFile = tempnam(TMP, “); generates a test filename in the TMP directory. TMP is a constant that can be declared like:
define(’TMP’, ‘/tmp’);
More info on the tempnam command here: http://au3.php.net/tmpname
July 6th, 2007 at 2:23 pm
is it gonna run well on PHP 5 and mysql 5?
Thank U.
July 6th, 2007 at 2:56 pm
Is it gonna run well on PHP 5 and mysql 5?
I’ve already try it manytimes but still not work.Help me please…..
Thanks
July 8th, 2007 at 7:20 pm
Yes, it does work on PHP 5 and MySQL 5.
Be sure to check your Apache error log as the Java related errors do not generally appear in your browser through PHP.
October 24th, 2007 at 6:43 pm
The issues related to report compilation (#1 and #2, if I understand correctly) might be resolved by dropping the javac-based report compiler in favor of the JDT-based one.
The JDT-based report compiler has two advantages:
1. It does not need to use temp files to compile a report, it can do so by only using in-memory data.
2. It uses the context classloader (as in Thread.getContextClassLoader()) to resolve classes while compiling reports, so it doesn’t need jasper.reports.compile.class.path to be set.
Given these features, we recommend the JDT-based compiler as it’s easier to use in almost any situation. The compiler is automatically used when the jdt-compiler jar is present on the application’s classpath (and no compiler is explicitly used).
I don’t guarantee that using the JDT compiler would solve the first two issues as I don’t know how the PHP bridge works, but it’s worth trying.
Regards,
Lucian
October 27th, 2007 at 2:52 pm
Thanks Lucian, removes a lot of the frustration.
I have added a new entry with a simpler approach that makes use of the JDT compiler.
February 19th, 2008 at 3:31 pm
[...] Jasper Reports and PHP It is a very good article which brings already a certain abstraction of complexity To marble Carryforward in PHP. It is necessary I think of going even further. But it is a very good beginning. http://www.rjohnson.id.au/wordpress/2007/02/04/jasper-carryforwards-and-php/ [...]
July 6th, 2008 at 7:29 pm
[...] so I got a fair bit of traffic about my last entry where I attempted to explain how I managed to get PHP to talk to Jasper through use of the PHP/Java [...]
August 26th, 2008 at 4:47 pm
Hi !
I try to export a jasperreport to excel from php…
my code :
$sPar = new JavaClass(”net.sf.jasperreports.engine.export.JRXlsExporterParameter”);
$sJem = new JavaClass(”net.sf.jasperreports.engine.export.JRXlsExporter”);
$sJem->setParameter($sPar->JASPER_PRINT, $print);
$sJem->setParameter($sPar->OUTPUT_FILE_NAME, $reportsPath .$reportFileName.”.xls”);
$sJem->setParameter($sPar->IS_ONE_PAGE_PER_SHEET, false);
$sJem->exportReport();
but i get this error:
java stack trace: java.lang.Exception: Invoke failed: [c(JRXlsExporter)]->setParameter(o(JRExporterParameter), o(JasperPrint)). Cause: java.lang.NoSuchMethodException: setParameter(o(JRExporterParameter), o(JasperPrint)). Candidates: [] Responsible VM: 1.5.0_10@http://java.sun.com/ at php.java.bridge.JavaBridge.Invoke(JavaBridge.java:1096) at php.java.bridge.Request.handleRequest(Request.java:342) at php.java.bridge.Request.handleRequests(Request.java:388) at php.java.bridge.JavaBridge.run(JavaBridge.java:200) at php.java.bridge.BaseThreadPool$Delegate.run(BaseThreadPool.java:66) Caused by: java.lang.NoSuchMethodException: setParameter(o(JRExporterParameter), o(JasperPrint)). Candidates: [] … 5 more
i apreciated you help…
(sorry por my poor english)
Thanks guys
October 20th, 2008 at 10:13 pm
Hey, I’ve got a
java.security.AccessControlException
it’s thrown when on first line of the constructor of the ReportGenerator object when it tries to
System.setProperty(”jasper.reports.compile.class.path”)
How can i solve this?
November 3rd, 2008 at 8:23 pm
Hi, I am unable to pass the database connection thus am getting an empty (null) result. Someone pls help me to get this working
March 12th, 2009 at 9:10 pm
Hi Richard,
I am facing problem in jasper report.
i am getting date field from data base as Long.
I want to display it as dd-mm-yyyy, how can i do this conversion in jrxml.Please help.
regards,
Vikas
March 20th, 2009 at 9:03 am
Hi Richard,
I am facing a problem ..would be gr8 if you could provide some help. I am new to jasper reports and I am trying to integrae jasper with eclipse IDE. I have php-java bridge up . Initially had unzipped into a seperate folder but now have put the contents of Java folder and javaBridge.jar in the eclipse project folder . Now could you please tell me how can I proceed with Jasper integration with eclipse.
Thanks
Nisha
March 30th, 2009 at 10:06 am
HI Richard,
I am trying to use jasperreports and php. While I call the method compile manager by passing a test.jrxml following error is thrown. Have been trying from days but not getting any clue.. Could u plzzzzz help.
Errors were encountered when compiling report expressions class file: D:\wamp\bin\php\php5.2.8\ext\HI_1238371884860_172091.java:4: package net.sf.jasperreports.engine does not exist import net.sf.jasperreports.engine.*; ^ D:\wamp\bin\php\php5.2.8\ext\HI_1238371884860_172091.java:5: package net.sf.jasperreports.engine.fill does not exist import net.sf.jasperreports.engine.fill.*; ^ D:\wamp\bin\php\php5.2.8\ext\HI_1238371884860_172091.java:18: cannot resolve symbol symbol : class JREvaluator location: class HI_1238371884860_172091 public class HI_1238371884860_172091 extends JREvaluator ^ D:\wamp\bin\php\php5.2.8\ext\HI_1238371884860_172091.java:25: cannot resolve symbol symbol : class JRFillParameter location: class HI_1238371884860_172091 private JRFillParameter parameter_REPORT_LOCALE = null; ^ D:\wamp\bin\php\php5.2.8\ext\HI_1238371884860_172091.java:26: cannot resolve symbol symbol : class JRFillParameter location: class HI_1238371884860_172091 private JRFillParameter parameter_REPORT_TIME_ZONE = null; ^
September 19th, 2009 at 12:45 am
Hi Richard,
I managed to make the report produce! But not passing the archive *.jrxml to compile how in the code down:
$compileManager = new JavaClass (” net.sf.jasperreports.engine. JasperCompileManager “);
$report = $compileManager-> compileReport (realpath (”relatorio.jrxml”));
It would like what knowledge *.jar what I put to work with this class or even it might be in charge for the email or to put in annexe for us!
Thank you!
November 18th, 2009 at 11:22 pm
Hi Richard,
I use xampp as Apache and Tomcat installed xampp’s own I wonder where I put the Java Bridge it will run on the server or Apache Mark up, not really clear you could help me?
March 1st, 2010 at 12:15 am
We have a PHP project we have to create jasper report, how to integrate java with PHP to produce jasper report.Please let me know ur suggestions soon and i have no idea about jasper report and PHP