Jump to content
We've recently updated our Privacy Statement, available here ×

atomatically compile subreports


dusca

Recommended Posts

I have an app that has as input jrxml file names, and outputs the pdf reports. So I am given a "mainReport.jrxml" string, and should output the pdf.

 

I can easily compile "mainReport" to compiledDirectory, load it into a JasperReport object and then call JasperFillManager.fillReport ()

 

But in the case of a report having subreports, how do I find that mainReport subreports (and what are their filenames) to compile those also?

there is no JasperReport.getSubeports() or something similar... any ideas?

 

I hope I was explicit enough

Link to comment
Share on other sites

  • Replies 18
  • Created
  • Last Reply

Top Posters In This Topic

Yeah we had this issue, so we implemented this

 

Code:

<subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[JasperCompileManager.compileReport(getClass().getResource("/templates/subreport.jrxml"«»).openStream())]]></subreportExpression>

 

within the mainReport thereby compiling the subreport jrxml everytime the main report is run.

 

We have since changed this to compile and jar up all our jrxml files in a ant script, which then also handles all the fonts and customizer classes we have to go with our reports.

Link to comment
Share on other sites

dusca wrote:

But in the case of a report having subreports, how do I find that mainReport subreports (and what are their filenames) to compile those also?
there is no JasperReport.getSubeports() or something similar... any ideas?

 

If you use JR 2.0.3 or newer, you can iterate on all the subreports in a report via JRElementsVisitor:

Code:

JRElementsVisitor.visitReport(jr, new JRVisitorSupport() {
@Override
public void visitSubreport(JRSubreport subreport) {
..do whatever you have to do with the subreport..
}
});

 

Note that if you want to determine the "filename" of the subreport, you'll have to make some assumptions on the subreport expressions, since such expressions can be arbitrarily complex and don't necessarily consists of a static filename.

 

HTH,

Lucian

Link to comment
Share on other sites

thanks lucian, greylimbo.

tried first the greylimbo approach but didn't quite work as i needed, so i am using lucian's solution

 

so now I have something along the lines of:

 

Code:
JasperCompileManager.compileReportToFile(jrxmlPath,jasperPath);
ret = (JasperReport) JRLoader.loadObject(jasperPath);
JRElementsVisitor.visitReport(ret, new SubreportVisitor(sourcePath, destinationPath));

 

and in my visitor I get the subreport path and also

 

JasperCompileManager.compileReportToFile(subReportJrxmlPath, jasperPath);

 

 

but at runtime I get a

Code:
[code]net.sf.jasperreports.engine.JRException: Could not load object from location : MySubReport.jasper
at net.sf.jasperreports.engine.util.JRLoader.loadObjectFromLocation(JRLoader.java:267)
at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:308)

 

 

am I supposed to do a JRLoader.loadObject for the supreport too,or what am I missing?

the jasper files exist and are all in the same dir.

 

thanks

Link to comment
Share on other sites

to answer my own question, loadObject has no effect.

 

so it's not that

 

later edit:

 

this is killing me now!

 

I have a report that has one subreport. the subreport expression is something like "SubraportulMeu.jasper"

 

that works perfectly with the code explained above.

 

then another report, but with two subreports, with the same expression - gives me the "cannot load" exception.

 

i quadruple checked but just can't figure out what the heck is the difference, why one works but the other doesn't. to the first i only send $P{} params, to the second i send $P{} and $F{}. that is the only thing that is different, but shouldn't be relevant.

Post edited by: dusca, at: 2008/05/14 15:19

Link to comment
Share on other sites

Subreport locations are interpreted at runtime as a filename, a classloader resource or a URL.

 

So for "MySubReport.jasper" to be resolved, it should either be a file in the JVM's working directory, or a resource on your application's classpath (so the folder where you have the *.jasper files would have to be part of the classpath).

 

Regards,

Lucian

Link to comment
Share on other sites

lucian, then how is it explained that one of the reports works without a full abstract path? the same directories are used in both cases . all jrxml files are in one directory and all jasper files in another.
Link to comment
Share on other sites

i found out why the particular one was created. eclipse forgot to delete the jasper file from the bin directory, so it was in the run dir.

 

 

so ..

in the end i used greylimbo's solution after all.

 

thank you, it is quite a trick.

 

i cannot imagine another way, to use a relative path to the subreport

Post edited by: dusca, at: 2008/05/14 20:06

Link to comment
Share on other sites

  • 1 year later...

Hi

I'm coming back to this with a problem.

So my Subreport is defined using this expression:

                    <connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
                    <subreportExpression  class="net.sf.jasperreports.engine.JasperReport"><![CDATA[net.sf.jasperreports.engine.JasperCompileManager.compileReport(getClass().getResource("Subreport.jrxml").openStream())]]></subreportExpression>
 

If I run and execute the report from Ireport, the subreport is loaded, it all works like a charm

But from my application,  when I generate it using

JasperPrint jPrint = JasperFillManager.fillReport(rep, params, conn);

        JRExporter exporter = getExporter(pdf);
        exporter.setParameter(JRExporterParameter.JASPER_PRINT, jPrint);
        exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, byteArrayOutputStream);
        exporter.exportReport();

    
 

it doesn't work. No exception is thrown, it just doesn't embed the subreport.

So how can this be? Do I need to do something more in my reporting app?

Link to comment
Share on other sites

Isn't it a bit kind of inperformance to (re)compile the jrxml everytime the SubReport is loaded?

Imagine you have a placed the SubReport-Element in detail of MasterReport and have 1000 records... with your SubReportExpression you will now have 1000 compiles, isn't it????

So I would pass the compiled JasperReport Object as parameter or use a scriptlet does check wheter the jrxml must be (re)compiled or not!??!?! So as the SubReport-design isn't changed normally while fill process it should be compiled just once and not at each call!??!?!?!??

 

just my two cents.

C-Box

Link to comment
Share on other sites

you are correct.

 for each subreport in a detail field there is a lot of overhead (the sql query would be more expensive i think - i may be wrong here, so plese correct me) - that is why i embed my subreports in the summary band, or in a new report group's header/foooter

But now that you pointed out the performance issue, I used the SubreportVisitor lucian suggested to compile the sources, and passed the subreport dir parameter to the report.

 

Thanks!

 

 

Link to comment
Share on other sites

  • 4 weeks later...

I all

i have tryed the solution using the following line:

<subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[net.sf.jasperreports.engine.JasperCompileManager.compileReport(getClass().getResource("/prova/sub_dummy.jrxml").openStream())]]></subreportExpression>

on my main.jrxml report file

works great from my webapp (jsp), but if i open the file with IREPORT (v 3.5.2) and use "preview" button,  that gives me the following error:

Error filling print... Error evaluating expression :      Source text : net.sf.jasperreports.engine.JasperCompileManager.compileReport(getClass().getResource("/prova/sub_dummy.jrxml").openStream())
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression :      Source text : net.sf.jasperreports.engine.JasperCompileManager.compileReport(getClass().getResource("/prova/sub_dummy.jrxml").openStream())      at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:197)      at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:574)      at net.sf.jasperreports.engine.fill.JRCalculator.evaluate(JRCalculator.java:542)      at net.sf.jasperreports.engine.fill.JRFillElement.evaluateExpression(JRFillElement.java:872)      at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:283)      at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluate(JRFillSubreport.java:270)      at net.sf.jasperreports.engine.fill.JRFillElementContainer.evaluate(JRFillElementContainer.java:260)      at net.sf.jasperreports.engine.fill.JRFillBand.evaluate(JRFillBand.java:486)      at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillTitle(JRVerticalFiller.java:312)      at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReportStart(JRVerticalFiller.java:248)      at net.sf.jasperreports.engine.fill.JRVerticalFiller.fillReport(JRVerticalFiller.java:114)      at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:911)      at net.sf.jasperreports.engine.fill.JRBaseFiller.fill(JRBaseFiller.java:814)      at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:63)      at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:421)      at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:251)      at com.jaspersoft.ireport.designer.compiler.IReportCompiler.run(IReportCompiler.java:898)      at org.openide.util.RequestProcessor$Task.run(RequestProcessor.java:561)      at org.openide.util.RequestProcessor$Processor.run(RequestProcessor.java:986)  Caused by: net.sf.jasperreports.engine.JRException: Could not instantiate report compiler : it.businesslogic.ireport.compiler.ExtendedJRJdtCompiler      at net.sf.jasperreports.engine.JasperCompileManager.getCompiler(JasperCompileManager.java:520)      at net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:219)      at net.sf.jasperreports.engine.JasperCompileManager.compileReport(JasperCompileManager.java:205)      at main_1245143465937_710977.evaluate(main_1245143465937_710977:183)      at net.sf.jasperreports.engine.fill.JREvaluator.evaluate(JREvaluator.java:186)      ... 18 more  Caused by: java.lang.ClassNotFoundException: it.businesslogic.ireport.compiler.ExtendedJRJdtCompiler      at java.net.URLClassLoader$1.run(URLClassLoader.java:200)      at java.security.AccessController.doPrivileged(Native Method)      at java.net.URLClassLoader.findClass(URLClassLoader.java:188)      at java.lang.ClassLoader.loadClass(ClassLoader.java:307)      at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)      at java.lang.ClassLoader.loadClass(ClassLoader.java:252)      at org.netbeans.ProxyClassLoader.loadClass(ProxyClassLoader.java:231)      at java.lang.ClassLoader.loadClass(ClassLoader.java:252)      at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:320)      at java.lang.Class.forName0(Native Method)      at java.lang.Class.forName(Class.java:247)      at net.sf.jasperreports.engine.util.JRClassLoader.loadClassForRealName(JRClassLoader.java:179)      at net.sf.jasperreports.engine.util.JRClassLoader.loadClassForName(JRClassLoader.java:119)      at net.sf.jasperreports.engine.JasperCompileManager.getCompiler(JasperCompileManager.java:515)      ... 22 more 
Print not filled. Try to use an EmptyDataSource...

anyone knows the problem and a solution to it?

maybe i have missing something like a particular jar in the classpath?

thanks,

Mat

Link to comment
Share on other sites

  • 1 month later...
  • 3 weeks later...
  • 4 years later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...