Я работаю над веб-приложением, написанным на Java, с использованием фреймворка Tapestry 5.1.0.5.Эта структура не имеет встроенной поддержки JasperReports, поэтому я написал сервис, который модифицирует службу JasperReport компании ChenilleKit.Я не зависим от версии ChenilleKit, вместо этого я использую зависимость JasperReport 3.5.0.Это может не быть необходимой информацией, но это никогда не повредит, чтобы быть конкретным.
В любом случае, мой сервис работает довольно хорошо.Он встроен в веб-приложение, и я могу собирать и выводить основные отчеты в форматах PDF, XLS, HTML и CSV.Однако у меня возникла большая проблема с получением SQL в XML-файле (ах) jasperReport для правильной загрузки карты параметров.
Я получаю следующую ошибку при попытке запустить отчеты с параметрами startdate и enddate.
SQLException: Missing IN or OUT parameter at index:: 1
Знание SQL скажет, что это означает, что у меня есть какая-то форма параметра, которая не передается вSQL.Операторы отладки указывают мне, что я передаю параметры в порядке, и что по крайней мере некоторые из них попадают в отчет XML.
Например, я передаю три параметра в отчет: Title, StartDate иДата окончания.Название отображается при рендеринге отчетов, но StartDate и EndDate, кажется, теряются в переводе?
Я не уверен, что мне не хватает, потому что почти идентичный код работает в моей компании на основе JSP-Tomcat-Servletприложение с JasperReports.
В любом случае я начну показывать код и объяснять, что происходит:
public StreamResponse getReport(String reportTitle, ExportFormat formMode, Date startDate, Date endDate) {
Map<String,String> parameterMap = loadParameters(reportTitle);
Connection conn = null;
OutputStream os = new ByteArrayOutputStream();
try{
conn = Report.getConnection();
Resource resc = new ContextResource(cimpl, "src/main/webapp/reports/"+reportTitle+".xml");
log.debug("Calling fillAndExport to fetch the report " + reportTitle);
log.debug("resource="+resc+"\n"+"formMode="+formMode+"\n"+"parameterMap="+parameterMap+"\n"+"conn="+conn+"\n"+
"outputStream="+os);
SimpleDateFormat repDate = new SimpleDateFormat("MM/dd/yyyy HH:mm");
parameterMap.put("StartDate", repDate.format(startDate));
parameterMap.put("EndDate", repDate.format(endDate));
log.debug("StartDate into report: " + parameterMap.get("StartDate"));
log.debug("EndDate into report: " + parameterMap.get("EndDate"));
js.fillAndExport(resc, formMode, parameterMap, conn, os);
SimpleDateFormat sdf = new SimpleDateFormat("MMMddyyyy");
return new JasperStreamResponse((ByteArrayOutputStream) os, formMode, reportTitle+"-"+sdf.format(startDate)+"-"
+sdf.format(endDate));
}catch (Exception e){
log.error("Caught exception while trying to execute the report fillAndExport service method.");
throw new TapestryException("Issue executing report", e);
} finally {
if(conn != null){
try {
conn.close();
} catch (SQLException e) {
System.out.println("Could not close the JDBC connection!!");
}
}
}
}
В двух словах, я загружаю ресурс отчета и добавляю параметры StartDate и EndDate (Заголовок уже есть в параметре Map).Затем я вызываю JasperService, который использует fillAndExport для генерации отчета.Если исключений нет, оно возвращается в браузер в потоке.
Вот сопровождающие операторы отладки для определенного времени, я получаю исключение:
[DEBUG] AppModule.ReportService Loaded report class: com.moremagic.reports.TriggerReport
[DEBUG] AppModule.ReportService Calling fillAndExport to fetch the report Trigger
[DEBUG] AppModule.ReportService resource=context:src/main/webapp/reports/Trigger.xml
formMode=HTML
parameterMap={Title=Triggering Merchant Commission}
conn=oracle.jdbc.driver.T4CConnection@7c974e4b
outputStream=
[DEBUG] AppModule.ReportService StartDate into report: 08/22/2010 14:19
[DEBUG] AppModule.ReportService EndDate into report: 08/23/2010 14:19
[DEBUG] AppModule.JasperService Constructed configuration: {}
[DEBUG] AppModule.JasperService Invoking method com.moremagic.services.AppModule.buildJasperService(Logger, Map) (at AppModule.java:188).
[DEBUG] AppModule.JasperService Using template -> src/main/webapp/reports/Trigger.xml
[DEBUG] AppModule.JasperService In fillReport, parameterMap is : {EndDate=08/23/2010 14:31, StartDate=08/22/2010 14:31, Title=Triggering Merchant Commission}
[ERROR] AppModule.JasperService Caught exception in fillReport of ReportsServiceImpl {}
net.sf.jasperreports.engine.JRException: Error executing SQL statement for : WebappReport1
Caused by: java.sql.SQLException: Missing IN or OUT parameter at index:: 1
Так что, как вы можете видеть,значения находятся в карте параметров вплоть до тех пор, пока JasperService не вызовет API JapserReports.Теперь я покажу код JasperService и некоторые отчеты, чтобы вы могли видеть, что SQL ломает.
JasperService:
/**
* Fills the report design loaded from the supplied input resource and returns the generated report object.
* <p/>
* if parameter <em>jasperPrint<em> not null, the data filled into <em>jasperPrint</em>
* instead of returns a new jasper print object.
*
* @param jasperPrint
* @param inputResource the input resource (report template file ".jrxml")
* @param parameterMap the parameter map
* @param dataSource the datasource, either a JRDataSource or an SQL JDBC Connection.
*
* @return
*/
public JasperPrint fillReport(JasperPrint jasperPrint, Resource inputResource, Map parameterMap, Object dataSource) throws JRException
{
JasperReport jasperReport = doCompileReportSource(inputResource);
JasperPrint actualJasperPrint;
logger.debug("In fillReport, parameterMap is : " + parameterMap + "\n startDate: " + parameterMap.get("StartDate") + "\n endDate: " + parameterMap.get("EndDate"));
try
{
if (dataSource != null && dataSource instanceof JRDataSource)
actualJasperPrint = JasperFillManager.fillReport(jasperReport, parameterMap, (JRDataSource) dataSource);
else if(dataSource != null && dataSource instanceof Connection)
actualJasperPrint = JasperFillManager.fillReport(jasperReport, parameterMap, (Connection) dataSource);
else
actualJasperPrint = JasperFillManager.fillReport(jasperReport, parameterMap);
if (jasperPrint != null)
{
for (Object page : actualJasperPrint.getPages())
jasperPrint.addPage((JRPrintPage) page);
}
else
jasperPrint = actualJasperPrint;
return jasperPrint;
}
catch (JRException e)
{
logger.error("Caught exception in fillReport of ReportsServiceImpl {}", e);
throw new JRException(e);
}
}
Отчет:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN"
"http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport
name="WebappReport1"
pageWidth="595"
pageHeight="842"
columnWidth="555"
columnSpacing="0"
leftMargin="20"
rightMargin="20"
topMargin="30"
whenNoDataType="AllSectionsNoDetail"
bottomMargin="30">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="9" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="9" isBold="true" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="9" isItalic="true" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="Title" class="java.lang.String"/>
<parameter name="StartDate" class="java.lang.String" />
<parameter name="EndDate" class="java.lang.String" />
<!--This is report query string used to fill data-->
<queryString><![CDATA[
SELECT
something
from table b
where
b.ba_timestamp between to_date( $P!{StartDate}, 'MM/DD/YYYY HH24:MI' ) and to_date( $P!{EndDate}, 'MM/DD/YYYY HH24:MI' )+1
]]></queryString>