Hi.
There's a slight performace problem with JRResource, that it creates
JasperReport in it's constructor. I've 10 resource links on one page so
it means that 10 JasperReports will be initialized everytime page is
created, even if none of them gets clicked. The performance penalty is
not small - 400ms.
So I think the JasperReport should be initialized lazyly, only when
the resource is really used.
I've atached "fixed" JRResource, it may not be the best solution, but
it works for me. (Look in the constructor(s) to see how it works)
-Matej
------------------------------------------------------------------------
Index: src/java/wicket/contrib/jasperreports/JRResource.java
===================================================================
RCS file:
/cvsroot/wicket-stuff/wicket-contrib-jasperreports/src/java/wicket/contrib/jasperreports/JRResource.java,v
retrieving revision 1.1
diff -u -r1.1 JRResource.java
--- src/java/wicket/contrib/jasperreports/JRResource.java 20 Sep 2005
20:00:46 -0000 1.1
+++ src/java/wicket/contrib/jasperreports/JRResource.java 21 Nov 2005
18:36:46 -0000
@@ -21,6 +21,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
+import java.io.Serializable;
import java.net.URL;
import java.sql.Connection;
import java.util.Map;
@@ -54,7 +55,7 @@
/**
* Provides JDBC connection.
*/
- public static interface IDatabaseConnectionProvider
+ public static interface IDatabaseConnectionProvider extends Serializable
{
/**
* Gets a JDBC connection to use when filling the report.
@@ -70,8 +71,32 @@
void release();
}
- /** the compiled report this resource references. */
- private JasperReport jasperReport;
+ /**
+ * Factory class for lazy initialization of the jasper report.
+ */
+ private static interface JasperReportFactory extends Serializable
+ {
+ /**
+ * Create a jasper report instance.
+ *
+ * @return the new jasper report instance.
+ * @throws JRException
+ */
+ JasperReport newJasperReport() throws JRException;
+ };
+
+ /** the connection provider if any for filling this report. */
+ private IDatabaseConnectionProvider connectionProvider;
+
+ /** factory for delayed report creation. */
+ private JasperReportFactory jasperReportFactory;
+
+ /**
+ * The compiled report this resource references. Made transient as we
don't
+ * want our report to be serialized while we can recreate it at other
+ * servers at will using the factory.
+ */
+ private transient JasperReport jasperReport;
/** the report parameters. */
private Map reportParameters;
@@ -79,9 +104,6 @@
/** the datasource if any for filling this report. */
private JRDataSource reportDataSource;
- /** the connection provider if any for filling this report. */
- private IDatabaseConnectionProvider connectionProvider;
-
/**
* When set, a header 'Content-Disposition: attachment;
* filename="${fileName}"' will be added to the response, resulting in a
@@ -106,18 +128,15 @@
* @param report
* the report input stream
*/
- public JRResource(InputStream report)
+ public JRResource(final InputStream report)
{
- super();
- setCacheable(false);
- try
+ this(new JasperReportFactory()
{
- jasperReport = (JasperReport)
JRLoader.loadObject(report);
- }
- catch (JRException e)
- {
- throw new WicketRuntimeException(e);
- }
+ public JasperReport newJasperReport() throws JRException
+ {
+ return (JasperReport)
JRLoader.loadObject(report);
+ };
+ });
}
/**
@@ -126,18 +145,15 @@
* @param report
* the report input stream
*/
- public JRResource(URL report)
+ public JRResource(final URL report)
{
- super();
- setCacheable(false);
- try
- {
- jasperReport = (JasperReport)
JRLoader.loadObject(report);
- }
- catch (JRException e)
+ this(new JasperReportFactory()
{
- throw new WicketRuntimeException(e);
- }
+ public JasperReport newJasperReport() throws JRException
+ {
+ return (JasperReport)
JRLoader.loadObject(report);
+ };
+ });
}
/**
@@ -146,27 +162,53 @@
* @param report
* the report input stream
*/
- public JRResource(File report)
+ public JRResource(final File report)
+ {
+ this(new JasperReportFactory()
+ {
+ public JasperReport newJasperReport() throws JRException
+ {
+ return (JasperReport)
JRLoader.loadObject(report);
+ };
+ });
+ }
+
+ /**
+ * Construct.
+ *
+ * @param jasperReportFactory
+ * report factory for lazy initialization
+ */
+ private JRResource(JasperReportFactory jasperReportFactory)
{
super();
setCacheable(false);
- try
- {
- jasperReport = (JasperReport)
JRLoader.loadObject(report);
- }
- catch (JRException e)
- {
- throw new WicketRuntimeException(e);
- }
+
+ this.jasperReportFactory = jasperReportFactory;
}
/**
- * Gets jasperReport.
+ * Gets jasperReport. This implementation uses an internal factory to
lazily
+ * create the report. After creation the report is cached (set as the
+ * jasperReport property). Override this method in case you want to
provide
+ * some alternative creation/ caching scheme.
*
* @return jasperReport
*/
public JasperReport getJasperReport()
{
+ // if the report has not yet been initialized and can be,
initialize it
+ if (jasperReport == null && jasperReportFactory != null)
+ {
+ try
+ {
+
setJasperReport(jasperReportFactory.newJasperReport());
+ }
+ catch (JRException e)
+ {
+ throw new WicketRuntimeException(e);
+ }
+ }
return jasperReport;
}
@@ -282,6 +324,7 @@
/**
* Called by getData to obtain an exporter instance.
+ *
* @return an exporter instance
*/
protected abstract JRAbstractExporter newExporter();
@@ -337,6 +380,7 @@
protected JasperPrint newJasperPrint() throws JRException
{
final JasperPrint jasperPrint;
+
JasperReport jasperReport = getJasperReport();
Map reportParameters = getReportParameters();
JRDataSource reportDataSource = getReportDataSource();
@@ -385,4 +429,4 @@
}
}
-}
+}
\ No newline at end of file