Okay, once more, without antivirus message attached to java file and one unnecessary try/catch block :)

Matej Knopp wrote:
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



__________ NOD32 1.1295 (20051120) Information __________

This message was checked by NOD32 antivirus system.
http://www.eset.com


------------------------------------------------------------------------

/*
 * $Id: JRResource.java,v 1.1 2005/09/20 20:00:46 eelco12 Exp $
 * $Revision: 1.1 $
 * $Date: 2005/09/20 20:00:46 $
 *
 * 
==============================================================================
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package framework.wicket.jr;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
import java.util.Map;

import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.util.JRLoader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import wicket.WicketRuntimeException;
import wicket.protocol.http.WebResponse;
import wicket.resource.DynamicByteArrayResource;

/**
 * Base class for jasper reports resources.
* * @author Eelco Hillenius
 */
public abstract class JRResource extends DynamicByteArrayResource
{
        /** logger. */
        private static Log log = LogFactory.getLog(JRResource.class);

        /**
         * Provides JDBC connection.
         */
        public static interface IDatabaseConnectionProvider
        {
                /**
                 * Gets a JDBC connection to use when filling the report.
* * @return a JDBC connection
                 */
                Connection get();

                /**
                 * Called when the report is generated and the connection can be
                 * released again.
                 */
                void release();
        }

        /** the compiled report this resource references. */
        private JasperReport jasperReport;

        /** the report parameters. */
        private Map reportParameters;

        /** the datasource if any for filling this report. */
        private JRDataSource reportDataSource;

        /** the connection provider if any for filling this report. */
        private IDatabaseConnectionProvider connectionProvider;

        private static abstract class JasperReportInitializer {
                abstract JasperReport createJasperReport() throws JRException;
        };
        
        /** initializer for delayed report initialization. */
private JasperReportInitializer initializer;
        /**
         * When set, a header 'Content-Disposition: attachment;
         * filename="${fileName}"' will be added to the response, resulting in a
         * download dialog. No magical extensions are added, so you should make 
sure
         * the file has the extension you want yourself.
         */
        private String fileName;

        /**
         * Construct without a report. You must provide a report before you can 
use
         * this resource.
         */
        public JRResource()
        {
                super();
                setCacheable(false);
        }

        /**
         * Construct.
* * @param report
         *            the report input stream
         */
        public JRResource(final InputStream report)
        {
                super();
                setCacheable(false);
                
                initializer = new JasperReportInitializer() {
                        JasperReport createJasperReport() throws JRException {
                                return (JasperReport) 
JRLoader.loadObject(report);
                        };
                };              
        }

        /**
         * Construct.
* * @param report
         *            the report input stream
         */
        public JRResource(final URL report)
        {
                super();
                setCacheable(false);
                
                initializer = new JasperReportInitializer() {
                        JasperReport createJasperReport() throws JRException {
                                return (JasperReport) 
JRLoader.loadObject(report);
                        };
                };
        }

        /**
         * Construct.
* * @param report
         *            the report input stream
         */
        public JRResource(final File report)
        {
                super();
                setCacheable(false);
                
                initializer = new JasperReportInitializer() {
                        JasperReport createJasperReport() throws JRException {
                                return (JasperReport) 
JRLoader.loadObject(report);
                        };
                };
        }

        /**
         * Gets jasperReport.
* * @return jasperReport
         */
        public JasperReport getJasperReport()
        {
                return jasperReport;
        }

        /**
         * Sets {bjasperReport.
* * @param jasperReport
         *            jasperReport
         */
        public final void setJasperReport(JasperReport jasperReport)
        {
                this.jasperReport = jasperReport;
        }

        /**
         * Gets the report parameters.
* * @return report parameters
         */
        public Map getReportParameters()
        {
                return reportParameters;
        }

        /**
         * Sets the report parameters.
* * @param reportParameters
         *            report parameters
         * @return This
         */
        public final JRResource setReportParameters(Map reportParameters)
        {
                this.reportParameters = reportParameters;
                return this;
        }

        /**
         * Gets the datasource if any for filling this report.
* * @return the datasource if any for filling this report
         */
        public JRDataSource getReportDataSource()
        {
                return reportDataSource;
        }

        /**
         * Sets the datasource if any for filling this report.
* * @param reportDataSource
         *            the datasource if any for filling this report
         * @return This
         */
        public JRResource setReportDataSource(JRDataSource reportDataSource)
        {
                this.reportDataSource = reportDataSource;
                return this;
        }

        /**
         * Gets the connection provider if any for filling this report.
* * @return the connection provider if any for filling this report
         */
        public IDatabaseConnectionProvider getConnectionProvider()
        {
                return connectionProvider;
        }

        /**
         * Sets the connection provider if any for filling this report.
* * @param connectionProvider
         *            the connection provider if any for filling this report
         * @return This
         */
        public final JRResource setConnectionProvider(
                        IDatabaseConnectionProvider connectionProvider)
        {
                this.connectionProvider = connectionProvider;
                return this;
        }

        /**
         * Gets the file name. When set, a header 'Content-Disposition: 
attachment;
         * filename="${fileName}"' will be added to the response, resulting in a
         * download dialog. No magical extensions are added, so you should make 
sure
         * the file has the extension you want yourself.
* * @return the file name
         */
        public String getFileName()
        {
                return fileName;
        }

        /**
         * Sets the file name. When set, a header 'Content-Disposition: 
attachment;
         * filename="${fileName}"' will be added to the response, resulting in a
         * download dialog. No magical extensions are added, so you should make 
sure
         * the file has the extension you want yourself.
* * @param fileName
         *            the file name
         * @return This
         */
        public final JRResource setFileName(String fileName)
        {
                this.fileName = fileName;
                return this;
        }

        /**
         * Called by getData to obtain an exporter instance.
         * @return an exporter instance
         */
        protected abstract JRAbstractExporter newExporter();

        /**
         * Gets the binary data by getting a new instance of JasperPrint and an
         * exporter for generating the output.
* * @return the binary data * * @see wicket.resource.DynamicByteArrayResource#getData()
         */
        protected byte[] getData()
        {
                try
                {
                        long t1 = System.currentTimeMillis();
                        // get a print instance for exporting
                        JasperPrint print = newJasperPrint();

                        // get a fresh instance of an exporter for this report
                        JRAbstractExporter exporter = newExporter();

                        // prepare a stream to trap the exporter's output
                        ByteArrayOutputStream baos = new 
ByteArrayOutputStream();
                        exporter.setParameter(JRExporterParameter.JASPER_PRINT, 
print);
                        
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);

                        // execute the export and return the trapped result
                        exporter.exportReport();
                        byte[] data = baos.toByteArray();
                        if (log.isDebugEnabled())
                        {
                                long t2 = System.currentTimeMillis();
                                log.debug("loaded report data; bytes: "
                                                + data.length + " in " + (t2 - t1) + 
" miliseconds");
                        }
                        return data;
                }
                catch (JRException e)
                {
                        throw new WicketRuntimeException(e);
                }
        }

        /**
         * Creates a new [EMAIL PROTECTED] JasperPrint} instance. This instance 
is specific for
         * this render, but it not yet designated for one output format only.
* * @return a new [EMAIL PROTECTED] JasperPrint} instance.
         * @throws JRException
         */
        protected JasperPrint newJasperPrint() throws JRException
        {
                final JasperPrint jasperPrint;
                
                // if the report has not yet been initialized and can be, 
initialize it
                if (getJasperReport() == null && initializer != null) {
                        try {
                                
setJasperReport(initializer.createJasperReport());
                        } catch (JRException e) {
                                throw new WicketRuntimeException(e);
                        }
                }
                
                JasperReport jasperReport = getJasperReport();
                Map reportParameters = getReportParameters();
                JRDataSource reportDataSource = getReportDataSource();
                if (reportDataSource != null)
                {
                        jasperPrint = 
JasperFillManager.fillReport(jasperReport, reportParameters,
                                        reportDataSource);
                }
                else
                {
                        IDatabaseConnectionProvider connectionProvider = null;
                        try
                        {
                                connectionProvider = getConnectionProvider();
                                if (connectionProvider == null)
                                {
                                        throw new IllegalStateException(
                                                        "JasperReportsResources must 
either have a JRDataSource, "
                                                                        + "or a JDBC 
Connection provided");
                                }
                                jasperPrint = 
JasperFillManager.fillReport(jasperReport,
                                                reportParameters, 
connectionProvider.get());
                        }
                        finally
                        {
                                if (connectionProvider != null)
                                {
                                        connectionProvider.release();
                                }
                        }
                }
                return jasperPrint;
        }

        /**
         * @see 
wicket.markup.html.WebResource#setHeaders(wicket.protocol.http.WebResponse)
         */
        protected void setHeaders(WebResponse response)
        {
                super.setHeaders(response);
                String fileName = getFileName();
                if (fileName != null)
                {
                        response.setHeader("Content-Disposition", "attachment; 
filename=\""
                                        + fileName + "\"");

                }
        }
}

__________ NOD32 1.1295 (20051120) Information __________

This message was checked by NOD32 antivirus system.
http://www.eset.com


/*
 * $Id: JRResource.java,v 1.1 2005/09/20 20:00:46 eelco12 Exp $
 * $Revision: 1.1 $
 * $Date: 2005/09/20 20:00:46 $
 *
 * 
==============================================================================
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package framework.wicket.jr;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.net.URL;
import java.sql.Connection;
import java.util.Map;

import net.sf.jasperreports.engine.JRAbstractExporter;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.util.JRLoader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import wicket.WicketRuntimeException;
import wicket.protocol.http.WebResponse;
import wicket.resource.DynamicByteArrayResource;

/**
 * Base class for jasper reports resources.
 * 
 * @author Eelco Hillenius
 */
public abstract class JRResource extends DynamicByteArrayResource
{
        /** logger. */
        private static Log log = LogFactory.getLog(JRResource.class);

        /**
         * Provides JDBC connection.
         */
        public static interface IDatabaseConnectionProvider
        {
                /**
                 * Gets a JDBC connection to use when filling the report.
                 * 
                 * @return a JDBC connection
                 */
                Connection get();

                /**
                 * Called when the report is generated and the connection can be
                 * released again.
                 */
                void release();
        }

        /** the compiled report this resource references. */
        private JasperReport jasperReport;

        /** the report parameters. */
        private Map reportParameters;

        /** the datasource if any for filling this report. */
        private JRDataSource reportDataSource;

        /** the connection provider if any for filling this report. */
        private IDatabaseConnectionProvider connectionProvider;

        private static abstract class JasperReportInitializer {
                abstract JasperReport createJasperReport() throws JRException;
        };
        
        /** initializer for delayed report initialization. */
        private JasperReportInitializer initializer; 
        
        /**
         * When set, a header 'Content-Disposition: attachment;
         * filename="${fileName}"' will be added to the response, resulting in a
         * download dialog. No magical extensions are added, so you should make 
sure
         * the file has the extension you want yourself.
         */
        private String fileName;

        /**
         * Construct without a report. You must provide a report before you can 
use
         * this resource.
         */
        public JRResource()
        {
                super();
                setCacheable(false);
        }

        /**
         * Construct.
         * 
         * @param report
         *            the report input stream
         */
        public JRResource(final InputStream report)
        {
                super();
                setCacheable(false);
                
                initializer = new JasperReportInitializer() {
                        JasperReport createJasperReport() throws JRException {
                                return (JasperReport) 
JRLoader.loadObject(report);
                        };
                };              
        }

        /**
         * Construct.
         * 
         * @param report
         *            the report input stream
         */
        public JRResource(final URL report)
        {
                super();
                setCacheable(false);
                
                initializer = new JasperReportInitializer() {
                        JasperReport createJasperReport() throws JRException {
                                return (JasperReport) 
JRLoader.loadObject(report);
                        };
                };
        }

        /**
         * Construct.
         * 
         * @param report
         *            the report input stream
         */
        public JRResource(final File report)
        {
                super();
                setCacheable(false);
                
                initializer = new JasperReportInitializer() {
                        JasperReport createJasperReport() throws JRException {
                                return (JasperReport) 
JRLoader.loadObject(report);
                        };
                };
        }

        /**
         * Gets jasperReport.
         * 
         * @return jasperReport
         */
        public JasperReport getJasperReport()
        {
                return jasperReport;
        }

        /**
         * Sets {bjasperReport.
         * 
         * @param jasperReport
         *            jasperReport
         */
        public final void setJasperReport(JasperReport jasperReport)
        {
                this.jasperReport = jasperReport;
        }

        /**
         * Gets the report parameters.
         * 
         * @return report parameters
         */
        public Map getReportParameters()
        {
                return reportParameters;
        }

        /**
         * Sets the report parameters.
         * 
         * @param reportParameters
         *            report parameters
         * @return This
         */
        public final JRResource setReportParameters(Map reportParameters)
        {
                this.reportParameters = reportParameters;
                return this;
        }

        /**
         * Gets the datasource if any for filling this report.
         * 
         * @return the datasource if any for filling this report
         */
        public JRDataSource getReportDataSource()
        {
                return reportDataSource;
        }

        /**
         * Sets the datasource if any for filling this report.
         * 
         * @param reportDataSource
         *            the datasource if any for filling this report
         * @return This
         */
        public JRResource setReportDataSource(JRDataSource reportDataSource)
        {
                this.reportDataSource = reportDataSource;
                return this;
        }

        /**
         * Gets the connection provider if any for filling this report.
         * 
         * @return the connection provider if any for filling this report
         */
        public IDatabaseConnectionProvider getConnectionProvider()
        {
                return connectionProvider;
        }

        /**
         * Sets the connection provider if any for filling this report.
         * 
         * @param connectionProvider
         *            the connection provider if any for filling this report
         * @return This
         */
        public final JRResource setConnectionProvider(
                        IDatabaseConnectionProvider connectionProvider)
        {
                this.connectionProvider = connectionProvider;
                return this;
        }

        /**
         * Gets the file name. When set, a header 'Content-Disposition: 
attachment;
         * filename="${fileName}"' will be added to the response, resulting in a
         * download dialog. No magical extensions are added, so you should make 
sure
         * the file has the extension you want yourself.
         * 
         * @return the file name
         */
        public String getFileName()
        {
                return fileName;
        }

        /**
         * Sets the file name. When set, a header 'Content-Disposition: 
attachment;
         * filename="${fileName}"' will be added to the response, resulting in a
         * download dialog. No magical extensions are added, so you should make 
sure
         * the file has the extension you want yourself.
         * 
         * @param fileName
         *            the file name
         * @return This
         */
        public final JRResource setFileName(String fileName)
        {
                this.fileName = fileName;
                return this;
        }

        /**
         * Called by getData to obtain an exporter instance.
         * @return an exporter instance
         */
        protected abstract JRAbstractExporter newExporter();

        /**
         * Gets the binary data by getting a new instance of JasperPrint and an
         * exporter for generating the output.
         * 
         * @return the binary data
         * 
         * @see wicket.resource.DynamicByteArrayResource#getData()
         */
        protected byte[] getData()
        {
                try
                {
                        long t1 = System.currentTimeMillis();
                        // get a print instance for exporting
                        JasperPrint print = newJasperPrint();

                        // get a fresh instance of an exporter for this report
                        JRAbstractExporter exporter = newExporter();

                        // prepare a stream to trap the exporter's output
                        ByteArrayOutputStream baos = new 
ByteArrayOutputStream();
                        exporter.setParameter(JRExporterParameter.JASPER_PRINT, 
print);
                        
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, baos);

                        // execute the export and return the trapped result
                        exporter.exportReport();
                        byte[] data = baos.toByteArray();
                        if (log.isDebugEnabled())
                        {
                                long t2 = System.currentTimeMillis();
                                log.debug("loaded report data; bytes: "
                                                + data.length + " in " + (t2 - 
t1) + " miliseconds");
                        }
                        return data;
                }
                catch (JRException e)
                {
                        throw new WicketRuntimeException(e);
                }
        }

        /**
         * Creates a new [EMAIL PROTECTED] JasperPrint} instance. This instance 
is specific for
         * this render, but it not yet designated for one output format only.
         * 
         * @return a new [EMAIL PROTECTED] JasperPrint} instance.
         * @throws JRException
         */
        protected JasperPrint newJasperPrint() throws JRException
        {
                final JasperPrint jasperPrint;
                
                // if the report has not yet been initialized and can be, 
initialize it
                if (getJasperReport() == null && initializer != null) {
                        setJasperReport(initializer.createJasperReport());
                }
                
                JasperReport jasperReport = getJasperReport();
                Map reportParameters = getReportParameters();
                JRDataSource reportDataSource = getReportDataSource();
                if (reportDataSource != null)
                {
                        jasperPrint = 
JasperFillManager.fillReport(jasperReport, reportParameters,
                                        reportDataSource);
                }
                else
                {
                        IDatabaseConnectionProvider connectionProvider = null;
                        try
                        {
                                connectionProvider = getConnectionProvider();
                                if (connectionProvider == null)
                                {
                                        throw new IllegalStateException(
                                                        "JasperReportsResources 
must either have a JRDataSource, "
                                                                        + "or a 
JDBC Connection provided");
                                }
                                jasperPrint = 
JasperFillManager.fillReport(jasperReport,
                                                reportParameters, 
connectionProvider.get());
                        }
                        finally
                        {
                                if (connectionProvider != null)
                                {
                                        connectionProvider.release();
                                }
                        }
                }
                return jasperPrint;
        }

        /**
         * @see 
wicket.markup.html.WebResource#setHeaders(wicket.protocol.http.WebResponse)
         */
        protected void setHeaders(WebResponse response)
        {
                super.setHeaders(response);
                String fileName = getFileName();
                if (fileName != null)
                {
                        response.setHeader("Content-Disposition", "attachment; 
filename=\""
                                        + fileName + "\"");

                }
        }
}

Reply via email to