Saturday, November 8, 2008

Jasper Reports and legacy formats

I'm not sure when exactly or between which versions, but at some point Jasper Report designs moved from being based on legacy DTD to the more modern XSD schema. It turns out that most tools today, i.e. the iReport plugin for NetBeans, are now overwriting the DTD information of legacy designs in favor of XSD information.
This can cause problems if and when you are not able to change the Jasper engine itself that fills out the template designs. It also did not seem possible to simply plug-in another XML parser and I found it rather hard in general to find information about this and support forums to turn to. So I sought another solution.

If you try to run an XSD based design against the Jasper engine that can only deal with DTD, you will get an error along the line of this:

net.sf.jasperreports.engine.JRException: org.xml.sax.SAXParseException: Document root element "jasperReport", must match DOCTYPE root "null".


By using a legacy designer which favors DTD's (iReport 3.0 standalone) and the recent NetBeans plugin which favors XSD's, it becomes apparent what the exact differences are. Obviously the DTD version has a doctype clause:

<!DOCTYPE jasperReport PUBLIC "//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">


Furthermore, the jasperReport root element has the extra attributtes:

xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd


One could just edit the files manually, but seriously, what fun is that. Instead, we can create a decorator to perform this job on-the-fly as we send the design off to the Jasper engine to be compiled. We would need to do the following:
  1. Read the InputStream into a DOM tree
  2. Add the missing DTD doctype
  3. Remove the undesired attributtes
  4. Write the dom back out to an InputStream
The result of doing the above I've placed in LegacyJasperInputStream.java.

An example on how to use it:


JasperDesign design = JRXmlLoader.load(
       
new LegacyJasperInputStream(new FileInputStream("MyXsdBasedDesign.jrxml"))
       
);



Probably I am not the only one facing this issue, which is why I chose to write a small entry about it and hopefully helping others. Be advised, you're going to need the slf4j logging facility, or modify the source slightly to make use of the standard java.util.Logger.

Friday, November 7, 2008

Congratulations America!

I think it's only in order to congratulate the USA for what has happened. While oddly 47% of Americans still haven't noticed, the last 8 years of an illiterate republican doctrine "if you're not with us, you're against us" has hurt their country incredibly much. As evident right from the beginning to most of us, Bush will go over in history as the worst president of all time - only elected for his second term I suppose due to that fuzzy term called "American patriotism".

The only sad part will be missing someone to laugh at when watching Letterman, The Colbert Report or The Daily Show. Ah for a while at least, we'll always have Gucci Palin. ;)



Best of luck Obama, you sure have your work cut out for you! The future just got a lot brighter in the prospect of regaining an America so many of us used to admire once! With a new dawn near and a fresh breeze blowing from the west, let the healing begin.