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
18 Answers:
Code: |
<br /> <subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[JasperCompileManager.compileReport(getClass().getResource("/templates/subreport.jrxml"«»).openStream())]]></subreportExpression><br /> </td></tr></tbody></table><br /> <br /> within the mainReport thereby compiling the subreport jrxml everytime the main report is run.<br /> <br /> 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. |
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 [url=http://jasperreports.sourceforge.net/api/net/sf/jasperreports/engine/uti...
Code: |
<br /> JRElementsVisitor.visitReport(jr, new JRVisitorSupport() {<br /> @Override<br /> public void visitSubreport(JRSubreport subreport) {<br /> ..do whatever you have to do with the subreport..<br /> }<br /> });<br /> </td></tr></tbody></table><br /> <br /> 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.<br /> <br /> HTH,<br /> Lucian |
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);<br /> ret = (JasperReport) JRLoader.loadObject(jasperPath);<br /> JRElementsVisitor.visitReport(ret, new SubreportVisitor(sourcePath, destinationPath));</td></tr></tbody></table><br /> <br /> and in my visitor I get the subreport path and also<br /> <br /> JasperCompileManager.compileReportToFile(subReportJrxmlPath, jasperPath);<br /> <br /> <br /> but at runtime I get a <br /> <table align="center" border="0" cellpadding="3" cellspacing="1" width="90%"><tbody><tr><td><b>Code:</b></td></tr><tr><td><pre>net.sf.jasperreports.engine.JRException: Could not load object from location : MySubReport.jasper<br /> at net.sf.jasperreports.engine.util.JRLoader.loadObjectFromLocation(JRLoader.java:267)<br /> at net.sf.jasperreports.engine.fill.JRFillSubreport.evaluateSubreport(JRFillSubreport.java:308)</td></tr></tbody></table><br /> <br /> <br /> am I supposed to do a JRLoader.loadObject for the supreport too,or what am I missing?<br /> the jasper files exist and are all in the same dir. <br /> <br /> thanks |
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
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
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
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?
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
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!
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
Hi,
It is like saying: My friend, I have the same car and it also does not start.
Well, there are 1 million reasons for the car not to start.
So you better open up a new thread and provide as much details as you can, with report templates and PDFs and so on.
Thank you,
Teodor
general solution/background regarding the path handling and compilation: http://stackoverflow.com/questions/4364205/jasperserver-unable-to-locate...