Sure. I've attached an action that will allow you to use jasperreports to write to the output stream. You'll have to tweak the classpath. Mine probably won't work. It will load, compile and cache jrxml files located in /WEB-INF/reports. It uses a javax.sql.DataSource from JNDI. It also will take request parameters and translate them into java objects in order to pass into the JasperReports engine.


aretobios wrote:
I have created some reports with iReport and I tried to integrated them with
my struts2 web application. While the documentation for the jasperReport
plugin explains how to use a datasource and a compiled template to generate
a report, I wasn't able to find out how to use a database connection as a
datasource and how to pass parameters to the report.

Is there any way to pass parameters from an action?

Can I use a connection from a connection pooling as a datasource?

To overcome these problems I changed the source code of the plug-in.jkoutr@

--
Chad S. Lauritsen
Ecommerce Enterprise Developer
The Sherwin-Williams Company
216-566-2166

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.TimeZone;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;

import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRExporter;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.sherwin.ecom.common.util.ServiceLocator;
import com.sherwin.ecom.common.util.ServiceLocatorException;
import com.sherwin.ordering.ctools.Constants;

/**
 * <p>
 * Writes (potentially binary) report data to response output stream.
 * Since it is designed to be dynamic, this action does not use an ActionForm. 
 * Rather it parses request parameters on-the-fly, converting them to a Map of
 * parameters to pass into a JasperReport as appropriate. See the 
decodeJasperParameters
 * for more details.
 * </p>
 *
 * <p>
 * An unlimited number of named reports can be served from this action. They
 * are defined as .jrxml files and placed in WEB-INF/reports. These .jrxml files
 * are loaded and compiled on-the-fly. The compiled reports are cached in a
 * synchronized static java.util.Map. If a .jrxml file is updated after 
 * it has been compiled and cached, this action will detect such and recompile 
 * and recache the report.
 * </p>
 *
 * <p>
 * Reports are converted one of the following formats based on the value of the
 * "output" request parameter:
 * <ul>
 *  <li>"pdf" - Acrobat/PDF</li>
 *  <li>"xls" - Microsoft Excel Workbook</li>
 *  <li>"html" - HTML with images to control spacing</li>
 * </ul>
 * </p>
 *
 * @author <a href="mailto:[EMAIL PROTECTED]">Chad S. Lauritsen</a>
 */
public class ReportAction extends BaseAction {
    
    private static Log log  = LogFactory.getLog(ReportAction.class);

    private static class ReportMapEntry {
        public Date         compileDate;
        public JasperReport report;
    }

    public ActionForward process(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        writeReport(request, response);
        return null; // reponse completed
    }
    


    protected Map             reportsMap       = Collections
                                                       .synchronizedMap(new 
HashMap());
    /**
     * Build a java.util.Map from specially coded request parameters. Only
     * request parameters starting with "jpXxx_" will be loaded into the map.
     * Xxx represents the target type in which to parse the string. Valid
     * choices are
     * <ul>
     * <li>Date - java.sql.Date formatted as M/d/yyyy</li>
     * <li>Ts - java.sql.Timestamp formatted as M/d/yyyy H:mm:ss</li>
     * <li>Int - java.lang.Integer</li>
     * <li>Long - java.lang.Long</li>
     * <li>Bool - java.lang.Boolean</li>
     * </ul>
     * Everything else will be placed in the map as a string.
     * 
     * @param request
     * @return
     */
    public Map decodeJasperParameters(HttpServletRequest request) {
        Map ret = new HashMap();
        DateFormat dtFmt = new SimpleDateFormat("M/d/yyyy");
        DateFormat tsFmt = new SimpleDateFormat("M/d/yyyy H:mm:ss"); 
        Enumeration names = request.getParameterNames();
        while (names.hasMoreElements()) {
            String name = (String) names.nextElement();
            String value = request.getParameter(name);
            if (name.matches("^jp.+?_.+")) {
                try {
                    if (name.startsWith("jpDate_")) {
                        ret.put(name, new 
java.sql.Date(dtFmt.parse(value).getTime()));
                    } else if (name.startsWith("jpTs_")) {
                        ret.put(name, new 
java.sql.Timestamp(tsFmt.parse(value).getTime()));
                    } else if (name.startsWith("jpInt_")) {
                        ret.put(name, new Integer(value));
                    } else if (name.startsWith("jpLong_")) {
                        ret.put(name, new Long(value));
                    } else if (name.startsWith("jpBool_")) {
                        ret.put(name, new Boolean(value));
                    } else {
                        ret.put(name, request.getParameter(name));
                    }
                } catch (ParseException e) {
                    log.error(e);
                }
                if (log.isDebugEnabled()) {
                    log.debug("Mapped parameter: " + name + "=" + 
ret.get(name));
                }
            } else {
                if (log.isDebugEnabled()) {
                    log.debug("Skipping parameter: " + name);
                }
            }
        }
        return ret;
    }

    public void writeReport(HttpServletRequest request, HttpServletResponse 
response)
            throws ServletException, IOException, ServiceLocatorException {

        String cp = System.getProperty("jasper.reports.compile.class.path");
        if (isEmpty(cp)) {
            ServletContext srvCtx = getServlet().getServletContext();
            // from
            // 
http://www-128.ibm.com/developerworks/websphere/library/techarticles/0411_olivieri/0411_olivieri.html
            // Set class path for compiling XML templates
            System.setProperty("jasper.reports.compile.class.path",
                    srvCtx.getRealPath("/WEB-INF/lib/jasperreports-1.3.0.jar")
                          + System.getProperty("path.separator")
                          + 
srvCtx.getRealPath("/WEB-INF/lib/poi-2.0-final-20040126.jar")
                          + System.getProperty("path.separator")
                          + srvCtx.getRealPath("/WEB-INF/classes/"));
        }
        boolean paginate = Boolean.getBoolean(request.getParameter("paginate"));
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
        df.setTimeZone(TimeZone.getTimeZone("America/New_York"));
        JRExporter exp = null;
        Connection conn = null;
        // Get the datasource from JNDI
        DataSource ds = (DataSource) 
ServiceLocator.getInstance().lookup(Constants.JNDI_DATASOURCE);
        
        String output= request.getParameter("output");
        if (output == null) throw new IllegalArgumentException("parameter 
'output' required");
        
        String reportName = request.getParameter("reportName");
        if (reportName == null) throw new IllegalArgumentException("parameter 
'reportName' required");  

        String fileName = reportName + "_" + df.format(new Date()) + "." + 
output;
        String contentType = "application/octet-stream";
        if ("pdf".equalsIgnoreCase(output)) {
            contentType = "application/pdf";
            paginate = true;
            exp = new JRPdfExporter();
        } else if ("xls".equalsIgnoreCase(output)) {
            contentType = "application/ms-excel";
            exp = new JRXlsExporter();
            
exp.setParameter(JRXlsExporterParameter.IS_REMOVE_EMPTY_SPACE_BETWEEN_ROWS, 
Boolean.TRUE);
            exp.setParameter(JRXlsExporterParameter.IS_WHITE_PAGE_BACKGROUND, 
Boolean.FALSE);
        } else if ("html".equalsIgnoreCase(output)) {
            contentType = "text/html";
            exp = new JRHtmlExporter();
        } else if ("csv".equalsIgnoreCase(output)) {
            contentType = "text/csv";
            exp = new JRCsvExporter();
        } else {
            throw new IllegalArgumentException("Unknown export type");
        }
        

        
        OutputStream os = response.getOutputStream();
        try {
            JasperReport report = getReport(reportName);
            conn = ds.getConnection();
            Map reportParameters = decodeJasperParameters(request);
            reportParameters.put("jpString_requestUser", 
request.getUserPrincipal());
            if (request.isUserInRole(Constants.ROLE_ADMIN)) {
                String tmp = request.getParameter("jpString_requestUser");
                if (!isEmpty(tmp)) {
                    reportParameters.put("jpString_requestUser", tmp);          
          
                }
            }
            reportParameters.put(JRParameter.IS_IGNORE_PAGINATION, new 
Boolean(!paginate));
            JasperPrint jasperPrint = JasperFillManager.fillReport(report, 
reportParameters, conn);
            exp.setParameter(JRExporterParameter.JASPER_PRINT, jasperPrint);
            exp.setParameter(JRExporterParameter.OUTPUT_STREAM, os);
            exp.setParameter(JRExporterParameter.OUTPUT_FILE_NAME, fileName);
        } catch (JRException e) {
            throw new ServletException("Exception thrown by report API: " + 
e.getMessage(), e);
        } catch (SQLException e) {
            throw new ServletException("SQLException thrown by report API: ", 
e);
        } catch (IOException e) {
            throw new ServletException("IOException thrown: ", e);
        } finally {
            if (conn != null) {
                try { conn.close(); } catch (Exception ignore) {}
            }
            conn = null;
        }

        // Don't mess with the response until we're fairly sure we have
        // something to output--let the server show a visible error message in
        // case of problems

        // don't use no-cache, MSIE complains, esp while using SSL
        // evidently it only takes the no-cache seriously over SSL transport.
        // <shrug>
        // more info at:
        // http://support.microsoft.com/default.aspx?scid=kb;en-us;316431
        // response.setHeader("Cache-Control", "no-cache");
         response.setHeader("Pragma", "no-cache");
        // this should have the same end result
//        response.setHeader("Cache-Control", "must-revalidate");

        // only allow content to live for 5 minutes
        response.setDateHeader("Expires", System.currentTimeMillis() + 10000);
        response.setContentType(contentType);
        response.setHeader("Content-Disposition", "attachment; filename=\"" + 
fileName + "\"");
        try {
            exp.exportReport();
        } catch (JRException e) {
            log.error("Error running report: ", e);
        } finally {
            os.flush();
            os.close();
        }
    }

    protected JasperReport getReport(String reportName) throws IOException, 
JRException {
        JasperReport ret = null;
        ReportMapEntry rme = (ReportMapEntry) reportsMap.get(reportName);
        ServletContext srvCtx = getServlet().getServletContext();
        String xmlRealPath = srvCtx.getRealPath("/WEB-INF/reports/" + 
reportName + ".jrxml");
        if (rme == null) {
            ret = pathToJasperReport(xmlRealPath);
            rme = new ReportMapEntry();
            rme.report = ret;
            rme.compileDate = new Date();
            reportsMap.put(reportName, rme);     
        } else {
            File jrxmlFile = new File(xmlRealPath);
            if (log.isDebugEnabled()) {
                log.debug("Found report last compiled at: " + rme.compileDate);
                Date d = new Date();
                d.setTime(jrxmlFile.lastModified());
                log.debug("jrxml last modified: " + d);
            }
            if (rme.compileDate.getTime() <= jrxmlFile.lastModified()) {
                if (log.isInfoEnabled()) {
                    log.info("Recompiling report " + reportName + ", last 
compile date=" + rme.compileDate);
                }
                ret = pathToJasperReport(xmlRealPath);
                rme = new ReportMapEntry();
                rme.report = ret;
                rme.compileDate = new Date();
                reportsMap.put(reportName, rme);                
            } else {
                ret = rme.report;
            }
        }
        return ret;   
    }
    
    protected JasperReport pathToJasperReport(String path) throws IOException, 
JRException {
        JasperReport ret = null;
        ret = JasperCompileManager.compileReport(path);
        if (log.isInfoEnabled()) {
            log.info("compiled report loaded from " + path);
        }
        return ret;
    }

}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to