Drop JasperReports support

Issue: SPR-13294
This commit is contained in:
Juergen Hoeller 2016-07-05 23:06:15 +02:00
parent 355c6f0715
commit 7dda9fbd8c
50 changed files with 2 additions and 5041 deletions

View File

@ -51,7 +51,6 @@ configure(allprojects) { project ->
ext.httpasyncVersion = "4.1.2"
ext.httpclientVersion = "4.5.2"
ext.jackson2Version = "2.8.0"
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
ext.javamailVersion = "1.5.5"
ext.jcaVersion = "1.7"
ext.jettyVersion = "9.3.10.v20160621"
@ -622,14 +621,6 @@ project("spring-context-support") {
optional("org.codehaus.fabric3.api:commonj:1.1.0")
optional("org.freemarker:freemarker:${freemarkerVersion}")
optional("com.lowagie:itext:2.1.7")
optional("net.sf.jasperreports:jasperreports:$jasperreportsVersion") {
exclude group: "com.fasterxml.jackson.core", module: "jackson-annotations"
exclude group: "com.fasterxml.jackson.core", module: "jackson-core"
exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
exclude group: "org.olap4j", module: "olap4j"
exclude group: "xml-apis", module: "xml-apis"
exclude group: "org.springframework", module: "spring-context"
}
testCompile(project(":spring-context"))
testCompile("org.apache.poi:poi:${poiVersion}")
testCompile("org.hsqldb:hsqldb:${hsqldbVersion}")
@ -748,14 +739,6 @@ project("spring-webmvc") {
optional("org.freemarker:freemarker:${freemarkerVersion}")
optional("org.codehaus.groovy:groovy-all:${groovyVersion}")
optional("com.lowagie:itext:2.1.7")
optional("net.sf.jasperreports:jasperreports:$jasperreportsVersion") {
exclude group: "com.fasterxml.jackson.core", module: "jackson-annotations"
exclude group: "com.fasterxml.jackson.core", module: "jackson-core"
exclude group: "com.fasterxml.jackson.core", module: "jackson-databind"
exclude group: "org.olap4j", module: "olap4j"
exclude group: "xml-apis", module: "xml-apis"
exclude group: "org.springframework", module: "spring-context"
}
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}")
optional("com.rometools:rome:${romeVersion}")

View File

@ -1,276 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.ui.jasperreports;
import java.io.OutputStream;
import java.io.Writer;
import java.util.Collection;
import java.util.Map;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanArrayDataSource;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRCsvExporter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRXlsExporter;
/**
* Utility methods for working with JasperReports. Provides a set of convenience
* methods for generating reports in a CSV, HTML, PDF and XLS formats.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which has been deprecated in early 2014.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.3
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public abstract class JasperReportsUtils {
/**
* Convert the given report data value to a {@code JRDataSource}.
* <p>In the default implementation, a {@code JRDataSource},
* {@code java.util.Collection} or object array is detected.
* The latter are converted to {@code JRBeanCollectionDataSource}
* or {@code JRBeanArrayDataSource}, respectively.
* @param value the report data value to convert
* @return the JRDataSource (never {@code null})
* @throws IllegalArgumentException if the value could not be converted
* @see net.sf.jasperreports.engine.JRDataSource
* @see net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
* @see net.sf.jasperreports.engine.data.JRBeanArrayDataSource
*/
public static JRDataSource convertReportData(Object value) throws IllegalArgumentException {
if (value instanceof JRDataSource) {
return (JRDataSource) value;
}
else if (value instanceof Collection) {
return new JRBeanCollectionDataSource((Collection<?>) value);
}
else if (value instanceof Object[]) {
return new JRBeanArrayDataSource((Object[]) value);
}
else {
throw new IllegalArgumentException("Value [" + value + "] cannot be converted to a JRDataSource");
}
}
/**
* Render the supplied {@code JasperPrint} instance using the
* supplied {@code JRAbstractExporter} instance and write the results
* to the supplied {@code Writer}.
* <p>Make sure that the {@code JRAbstractExporter} implementation
* you supply is capable of writing to a {@code Writer}.
* @param exporter the {@code JRAbstractExporter} to use to render the report
* @param print the {@code JasperPrint} instance to render
* @param writer the {@code Writer} to write the result to
* @throws JRException if rendering failed
*/
public static void render(net.sf.jasperreports.engine.JRExporter exporter, JasperPrint print, Writer writer)
throws JRException {
exporter.setParameter(net.sf.jasperreports.engine.JRExporterParameter.JASPER_PRINT, print);
exporter.setParameter(net.sf.jasperreports.engine.JRExporterParameter.OUTPUT_WRITER, writer);
exporter.exportReport();
}
/**
* Render the supplied {@code JasperPrint} instance using the
* supplied {@code JRAbstractExporter} instance and write the results
* to the supplied {@code OutputStream}.
* <p>Make sure that the {@code JRAbstractExporter} implementation you
* supply is capable of writing to a {@code OutputStream}.
* @param exporter the {@code JRAbstractExporter} to use to render the report
* @param print the {@code JasperPrint} instance to render
* @param outputStream the {@code OutputStream} to write the result to
* @throws JRException if rendering failed
*/
public static void render(net.sf.jasperreports.engine.JRExporter exporter, JasperPrint print,
OutputStream outputStream) throws JRException {
exporter.setParameter(net.sf.jasperreports.engine.JRExporterParameter.JASPER_PRINT, print);
exporter.setParameter(net.sf.jasperreports.engine.JRExporterParameter.OUTPUT_STREAM, outputStream);
exporter.exportReport();
}
/**
* Render a report in CSV format using the supplied report data.
* Writes the results to the supplied {@code Writer}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param writer the {@code Writer} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsCsv(JasperReport report, Map<String, Object> parameters, Object reportData,
Writer writer) throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
render(new JRCsvExporter(), print, writer);
}
/**
* Render a report in CSV format using the supplied report data.
* Writes the results to the supplied {@code Writer}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param writer the {@code Writer} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @param exporterParameters a {@link Map} of {@code JRExporterParameter exporter parameters}
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsCsv(JasperReport report, Map<String, Object> parameters, Object reportData,
Writer writer, Map<net.sf.jasperreports.engine.JRExporterParameter, Object> exporterParameters)
throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
JRCsvExporter exporter = new JRCsvExporter();
exporter.setParameters(exporterParameters);
render(exporter, print, writer);
}
/**
* Render a report in HTML format using the supplied report data.
* Writes the results to the supplied {@code Writer}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param writer the {@code Writer} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsHtml(JasperReport report, Map<String, Object> parameters, Object reportData,
Writer writer) throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
render(new net.sf.jasperreports.engine.export.JRHtmlExporter(), print, writer);
}
/**
* Render a report in HTML format using the supplied report data.
* Writes the results to the supplied {@code Writer}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param writer the {@code Writer} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @param exporterParameters a {@link Map} of {@code JRExporterParameter exporter parameters}
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsHtml(JasperReport report, Map<String, Object> parameters, Object reportData,
Writer writer, Map<net.sf.jasperreports.engine.JRExporterParameter, Object> exporterParameters)
throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
net.sf.jasperreports.engine.export.JRHtmlExporter exporter = new net.sf.jasperreports.engine.export.JRHtmlExporter();
exporter.setParameters(exporterParameters);
render(exporter, print, writer);
}
/**
* Render a report in PDF format using the supplied report data.
* Writes the results to the supplied {@code OutputStream}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param stream the {@code OutputStream} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsPdf(JasperReport report, Map<String, Object> parameters, Object reportData,
OutputStream stream) throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
render(new JRPdfExporter(), print, stream);
}
/**
* Render a report in PDF format using the supplied report data.
* Writes the results to the supplied {@code OutputStream}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param stream the {@code OutputStream} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @param exporterParameters a {@link Map} of {@code JRExporterParameter exporter parameters}
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsPdf(JasperReport report, Map<String, Object> parameters, Object reportData,
OutputStream stream, Map<net.sf.jasperreports.engine.JRExporterParameter, Object> exporterParameters)
throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
JRPdfExporter exporter = new JRPdfExporter();
exporter.setParameters(exporterParameters);
render(exporter, print, stream);
}
/**
* Render a report in XLS format using the supplied report data.
* Writes the results to the supplied {@code OutputStream}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param stream the {@code OutputStream} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsXls(JasperReport report, Map<String, Object> parameters, Object reportData,
OutputStream stream) throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
render(new JRXlsExporter(), print, stream);
}
/**
* Render a report in XLS format using the supplied report data.
* Writes the results to the supplied {@code OutputStream}.
* @param report the {@code JasperReport} instance to render
* @param parameters the parameters to use for rendering
* @param stream the {@code OutputStream} to write the rendered report to
* @param reportData a {@code JRDataSource}, {@code java.util.Collection} or object array
* (converted accordingly), representing the report data to read fields from
* @param exporterParameters a {@link Map} of {@code JRExporterParameter exporter parameters}
* @throws JRException if rendering failed
* @see #convertReportData
*/
public static void renderAsXls(JasperReport report, Map<String, Object> parameters, Object reportData,
OutputStream stream, Map<net.sf.jasperreports.engine.JRExporterParameter, Object> exporterParameters)
throws JRException {
JasperPrint print = JasperFillManager.fillReport(report, parameters, convertReportData(reportData));
JRXlsExporter exporter = new JRXlsExporter();
exporter.setParameters(exporterParameters);
render(exporter, print, stream);
}
}

View File

@ -1,5 +0,0 @@
/**
* Support classes for
* <a href="http://jasperreports.sourceforge.net">JasperReports</a>.
*/
package org.springframework.ui.jasperreports;

View File

@ -1,274 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.ui.jasperreports;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRExporterParameter;
import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.export.JRCsvExporterParameter;
import net.sf.jasperreports.engine.export.JRExportProgressMonitor;
import net.sf.jasperreports.engine.export.JRHtmlExporter;
import net.sf.jasperreports.engine.export.JRHtmlExporterParameter;
import net.sf.jasperreports.engine.export.JRPdfExporter;
import net.sf.jasperreports.engine.export.JRPdfExporterParameter;
import net.sf.jasperreports.engine.export.JRXlsExporterParameter;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.tests.Assume;
import static org.junit.Assert.*;
/**
* @author Rob Harrop
* @author Juergen Hoeller
* @since 18.11.2004
*/
@SuppressWarnings("deprecation")
public class JasperReportsUtilsTests {
@BeforeClass
public static void assumptions() {
Assume.canLoadNativeDirFonts();
}
@Test
public void renderAsCsvWithDataSource() throws Exception {
StringWriter writer = new StringWriter();
JasperReportsUtils.renderAsCsv(getReport(), getParameters(), getDataSource(), writer);
String output = writer.getBuffer().toString();
assertCsvOutputCorrect(output);
}
@Test
public void renderAsCsvWithCollection() throws Exception {
StringWriter writer = new StringWriter();
JasperReportsUtils.renderAsCsv(getReport(), getParameters(), getData(), writer);
String output = writer.getBuffer().toString();
assertCsvOutputCorrect(output);
}
@Test
public void renderAsCsvWithExporterParameters() throws Exception {
StringWriter writer = new StringWriter();
Map<JRExporterParameter, Object> exporterParameters = new HashMap<>();
exporterParameters.put(JRCsvExporterParameter.FIELD_DELIMITER, "~");
JasperReportsUtils.renderAsCsv(getReport(), getParameters(), getData(), writer, exporterParameters);
String output = writer.getBuffer().toString();
assertCsvOutputCorrect(output);
assertTrue("Delimiter is incorrect", output.contains("~"));
}
@Test
public void renderAsHtmlWithDataSource() throws Exception {
StringWriter writer = new StringWriter();
JasperReportsUtils.renderAsHtml(getReport(), getParameters(), getDataSource(), writer);
String output = writer.getBuffer().toString();
assertHtmlOutputCorrect(output);
}
@Test
public void renderAsHtmlWithCollection() throws Exception {
StringWriter writer = new StringWriter();
JasperReportsUtils.renderAsHtml(getReport(), getParameters(), getData(), writer);
String output = writer.getBuffer().toString();
assertHtmlOutputCorrect(output);
}
@Test
public void renderAsHtmlWithExporterParameters() throws Exception {
StringWriter writer = new StringWriter();
Map<JRExporterParameter, Object> exporterParameters = new HashMap<>();
String uri = "/my/uri";
exporterParameters.put(JRHtmlExporterParameter.IMAGES_URI, uri);
JasperReportsUtils.renderAsHtml(getReport(), getParameters(), getData(), writer, exporterParameters);
String output = writer.getBuffer().toString();
assertHtmlOutputCorrect(output);
assertTrue("URI not included", output.contains(uri));
}
@Test
public void renderAsPdfWithDataSource() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getDataSource(), os);
byte[] output = os.toByteArray();
assertPdfOutputCorrect(output);
}
@Test
public void renderAsPdfWithCollection() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getData(), os);
byte[] output = os.toByteArray();
assertPdfOutputCorrect(output);
}
@Test
public void renderAsPdfWithExporterParameters() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Map<JRExporterParameter, Object> exporterParameters = new HashMap<>();
exporterParameters.put(JRPdfExporterParameter.PDF_VERSION, JRPdfExporterParameter.PDF_VERSION_1_6.toString());
JasperReportsUtils.renderAsPdf(getReport(), getParameters(), getData(), os, exporterParameters);
byte[] output = os.toByteArray();
assertPdfOutputCorrect(output);
assertTrue(new String(output).contains("PDF-1.6"));
}
@Test
public void renderAsXlsWithDataSource() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JasperReportsUtils.renderAsXls(getReport(), getParameters(), getDataSource(), os);
byte[] output = os.toByteArray();
assertXlsOutputCorrect(output);
}
@Test
public void renderAsXlsWithCollection() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JasperReportsUtils.renderAsXls(getReport(), getParameters(), getData(), os);
byte[] output = os.toByteArray();
assertXlsOutputCorrect(output);
}
@Test
public void renderAsXlsWithExporterParameters() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
Map<JRExporterParameter, Object> exporterParameters = new HashMap<>();
SimpleProgressMonitor monitor = new SimpleProgressMonitor();
exporterParameters.put(JRXlsExporterParameter.PROGRESS_MONITOR, monitor);
JasperReportsUtils.renderAsXls(getReport(), getParameters(), getData(), os, exporterParameters);
byte[] output = os.toByteArray();
assertXlsOutputCorrect(output);
assertTrue(monitor.isInvoked());
}
@Test
public void renderWithWriter() throws Exception {
StringWriter writer = new StringWriter();
JasperPrint print = JasperFillManager.fillReport(getReport(), getParameters(), getDataSource());
JasperReportsUtils.render(new JRHtmlExporter(), print, writer);
String output = writer.getBuffer().toString();
assertHtmlOutputCorrect(output);
}
@Test
public void renderWithOutputStream() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JasperPrint print = JasperFillManager.fillReport(getReport(), getParameters(), getDataSource());
JasperReportsUtils.render(new JRPdfExporter(), print, os);
byte[] output = os.toByteArray();
assertPdfOutputCorrect(output);
}
private void assertCsvOutputCorrect(String output) {
assertTrue("Output length should be greater than 0", (output.length() > 0));
assertTrue("Output should start with Dear Lord!", output.startsWith("Dear Lord!"));
assertTrue("Output should contain 'MeineSeite'", output.contains("MeineSeite"));
}
private void assertHtmlOutputCorrect(String output) {
assertTrue("Output length should be greater than 0", (output.length() > 0));
assertTrue("Output should contain <html>", output.contains("<html>"));
assertTrue("Output should contain 'MeineSeite'", output.contains("MeineSeite"));
}
private void assertPdfOutputCorrect(byte[] output) throws Exception {
assertTrue("Output length should be greater than 0", (output.length > 0));
String translated = new String(output, "US-ASCII");
assertTrue("Output should start with %PDF", translated.startsWith("%PDF"));
}
@SuppressWarnings("resource")
private void assertXlsOutputCorrect(byte[] output) throws Exception {
HSSFWorkbook workbook = new HSSFWorkbook(new ByteArrayInputStream(output));
HSSFSheet sheet = workbook.getSheetAt(0);
assertNotNull("Sheet should not be null", sheet);
HSSFRow row = sheet.getRow(3);
HSSFCell cell = row.getCell((short) 1);
assertNotNull("Cell should not be null", cell);
assertEquals("Cell content should be Dear Lord!", "Dear Lord!", cell.getRichStringCellValue().getString());
}
private JasperReport getReport() throws Exception {
ClassPathResource resource = new ClassPathResource("DataSourceReport.jasper", getClass());
return (JasperReport) JRLoader.loadObject(resource.getInputStream());
}
private Map<String, Object> getParameters() {
Map<String, Object> model = new HashMap<>();
model.put("ReportTitle", "Dear Lord!");
model.put(JRParameter.REPORT_LOCALE, Locale.GERMAN);
model.put(JRParameter.REPORT_RESOURCE_BUNDLE,
ResourceBundle.getBundle("org/springframework/ui/jasperreports/messages", Locale.GERMAN));
return model;
}
private JRDataSource getDataSource() {
return new JRBeanCollectionDataSource(getData());
}
private List<PersonBean> getData() {
List<PersonBean> list = new ArrayList<>();
for (int x = 0; x < 10; x++) {
PersonBean bean = new PersonBean();
bean.setId(x);
bean.setName("Rob Harrop");
bean.setStreet("foo");
list.add(bean);
}
return list;
}
private static class SimpleProgressMonitor implements JRExportProgressMonitor {
private boolean invoked = false;
@Override
public void afterPageExport() {
this.invoked = true;
}
public boolean isInvoked() {
return invoked;
}
}
}

View File

@ -1,64 +0,0 @@
/*
* Copyright 2002-2005 the original author or authors.
*
* 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 org.springframework.ui.jasperreports;
/**
* @author Rob Harrop
*/
public class PersonBean {
private int id;
private String name;
private String street;
private String city;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
}

View File

@ -1,64 +0,0 @@
/*
* Copyright 2002-2005 the original author or authors.
*
* 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 org.springframework.ui.jasperreports;
/**
* @author Rob Harrop
*/
public class ProductBean {
private int id;
private String name;
private float quantity;
private float price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getQuantity() {
return quantity;
}
public void setQuantity(float quantity) {
this.quantity = quantity;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}

View File

@ -1,185 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created using JasperAssistant (http://www.jasperassistant.com) -->
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="DataSourceReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="ReportTitle" class="java.lang.String">
</parameter>
<parameter name="DataFile" class="java.lang.String">
</parameter>
<field name="id" class="java.lang.Integer">
</field>
<field name="name" class="java.lang.String">
</field>
<field name="street" class="java.lang.String">
</field>
<field name="city" class="java.lang.String">
</field>
<variable name="CityNumber" class="java.lang.Integer" resetType="Group" resetGroup="CityGroup" calculation="System">
<initialValueExpression><![CDATA[($V{CityNumber} != null)?(new Integer($V{CityNumber}.intValue() + 1)):(new Integer(1))]]></initialValueExpression>
</variable>
<group name="CityGroup" minHeightToStartNewPage="60">
<groupExpression><![CDATA[$F{city}]]></groupExpression>
<groupHeader>
<band height="20">
<rectangle>
<reportElement x="0" y="4" width="515" height="15" forecolor="#c0c0c0" backcolor="#c0c0c0"/>
<graphicElement/>
</rectangle>
<textField>
<reportElement mode="Opaque" x="0" y="4" width="515" height="15" backcolor="#c0c0c0"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{CityNumber}) + ". " + String.valueOf($F{city})]]></textFieldExpression>
</textField>
<line>
<reportElement x="0" y="19" width="515" height="1"/>
<graphicElement/>
</line>
</band>
</groupHeader>
<groupFooter>
<band height="20">
<line>
<reportElement x="0" y="-1" width="515" height="1"/>
<graphicElement/>
</line>
<staticText>
<reportElement x="400" y="1" width="60" height="15"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Count :]]></text>
</staticText>
<textField>
<reportElement x="460" y="1" width="30" height="15"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{CityGroup_COUNT}]]></textFieldExpression>
</textField>
</band>
</groupFooter>
</group>
<title>
<band height="70">
<line>
<reportElement x="0" y="0" width="515" height="1"/>
<graphicElement/>
</line>
<textField isBlankWhenNull="true">
<reportElement x="0" y="10" width="515" height="30"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Normal" size="22"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{ReportTitle}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="0" y="40" width="515" height="20"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Normal" size="14"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{DataFile}]]></textFieldExpression>
</textField>
</band>
</title>
<pageHeader>
<band height="20">
<rectangle>
<reportElement x="0" y="5" width="515" height="15" forecolor="#333333" backcolor="#333333"/>
<graphicElement/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="5" width="55" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[ID]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="55" y="5" width="205" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="260" y="5" width="255" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Street]]></text>
</staticText>
</band>
</pageHeader>
<detail>
<band height="20">
<textField>
<reportElement x="0" y="4" width="50" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="55" y="4" width="200" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="260" y="4" width="255" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{street}]]></textFieldExpression>
</textField>
<line>
<reportElement positionType="Float" x="0" y="19" width="515" height="1" forecolor="#808080"/>
<graphicElement/>
</line>
</band>
</detail>
<pageFooter>
<band height="40">
<line>
<reportElement x="0" y="10" width="515" height="1"/>
<graphicElement/>
</line>
<textField>
<reportElement x="200" y="20" width="80" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA[$R{page} + " " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="280" y="20" width="75" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
</textField>
</band>
</pageFooter>
<lastPageFooter>
<band height="60">
<textField>
<reportElement x="0" y="10" width="515" height="15"/>
<textElement textAlignment="Center"/>
<textFieldExpression class="java.lang.String"><![CDATA["There were " +
String.valueOf($V{REPORT_COUNT}) +
" address records on this report."]]></textFieldExpression>
</textField>
<line>
<reportElement x="0" y="30" width="515" height="1"/>
<graphicElement/>
</line>
<textField>
<reportElement x="200" y="40" width="80" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA[$R{page} + " " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="280" y="40" width="75" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
</textField>
</band>
</lastPageFooter>
</jasperReport>

View File

@ -1,227 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created using JasperAssistant (http://www.jasperassistant.com) -->
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="ProductReport" columnCount="2" pageWidth="325" pageHeight="842" columnWidth="160" columnSpacing="5" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="8" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="8" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="8" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="City" class="java.lang.String"/>
<field name="id" class="java.lang.Integer">
</field>
<field name="name" class="java.lang.String">
</field>
<field name="quantity" class="java.lang.Float">
</field>
<field name="price" class="java.lang.Float">
</field>
<variable name="QuantityProductSum" class="java.lang.Float" resetType="Group" resetGroup="ProductGroup" calculation="Sum">
<variableExpression><![CDATA[$F{quantity}]]></variableExpression>
</variable>
<variable name="PriceProductSum" class="java.lang.Float" resetType="Group" resetGroup="ProductGroup" calculation="Sum">
<variableExpression><![CDATA[$F{price}]]></variableExpression>
</variable>
<variable name="QuantitySum" class="java.lang.Float" calculation="Sum">
<variableExpression><![CDATA[$F{quantity}]]></variableExpression>
</variable>
<variable name="PriceSum" class="java.lang.Float" calculation="Sum">
<variableExpression><![CDATA[$F{price}]]></variableExpression>
</variable>
<variable name="ProductCount" class="java.lang.Integer" resetType="Group" resetGroup="ProductGroup" calculation="System">
<initialValueExpression><![CDATA[($V{ProductCount} != null)?(new Integer($V{ProductCount}.intValue() + 1)):(new Integer(1))]]></initialValueExpression>
</variable>
<group name="ProductGroup">
<groupExpression><![CDATA[$F{id}]]></groupExpression>
<groupHeader>
<band height="14">
<textField>
<reportElement x="0" y="2" width="15" height="10"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="20" y="2" width="80" height="10"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true" evaluationTime="Group" evaluationGroup="ProductGroup" pattern="#0">
<reportElement positionType="Float" x="105" y="2" width="20" height="10"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{QuantityProductSum}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true" evaluationTime="Group" evaluationGroup="ProductGroup" pattern="#0.00">
<reportElement positionType="Float" x="130" y="2" width="30" height="10"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{PriceProductSum}]]></textFieldExpression>
</textField>
</band>
</groupHeader>
<groupFooter>
<band>
</band>
</groupFooter>
</group>
<title>
<band height="14">
<staticText>
<reportElement x="0" y="2" width="60" height="10"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Title]]></text>
</staticText>
<textField>
<reportElement x="0" y="2" width="325" height="10"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["Products ordered by people in " + $P{City}]]></textFieldExpression>
</textField>
</band>
</title>
<pageHeader>
<band height="14">
<rectangle>
<reportElement mode="Transparent" x="0" y="2" width="325" height="10" forecolor="#808000"/>
<graphicElement pen="Thin"/>
</rectangle>
<staticText>
<reportElement x="0" y="2" width="60" height="10" forecolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Page Header]]></text>
</staticText>
</band>
</pageHeader>
<columnHeader>
<band height="14">
<rectangle>
<reportElement x="0" y="2" width="160" height="10" forecolor="#ffff99" backcolor="#ffff99"/>
<graphicElement/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="2" width="20" height="10" backcolor="#ffff99"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[ID]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="20" y="2" width="85" height="10" backcolor="#ffff99"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="105" y="2" width="20" height="10" backcolor="#ffff99"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Qty]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="125" y="2" width="35" height="10" backcolor="#ffff99"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Price]]></text>
</staticText>
</band>
</columnHeader>
<columnFooter>
<band height="14">
<line>
<reportElement x="0" y="1" width="160" height="1"/>
<graphicElement pen="Thin"/>
</line>
<staticText>
<reportElement x="0" y="2" width="60" height="10"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Column Footer]]></text>
</staticText>
<staticText>
<reportElement x="70" y="2" width="30" height="10"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Total :]]></text>
</staticText>
<textField pattern="#0">
<reportElement x="105" y="2" width="20" height="10"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{QuantitySum}]]></textFieldExpression>
</textField>
<textField pattern="#0.00">
<reportElement x="130" y="2" width="30" height="10"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{PriceSum}]]></textFieldExpression>
</textField>
</band>
</columnFooter>
<pageFooter>
<band height="14">
<rectangle>
<reportElement mode="Transparent" x="0" y="2" width="325" height="10" forecolor="#808000"/>
<graphicElement pen="Thin"/>
</rectangle>
<staticText>
<reportElement x="0" y="2" width="60" height="10" forecolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Page Footer]]></text>
</staticText>
<textField>
<reportElement x="150" y="2" width="100" height="10" forecolor="#808000"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Italic"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of "]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="250" y="2" width="50" height="10" forecolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
</band>
</pageFooter>
<summary>
<band height="14">
<rectangle>
<reportElement x="0" y="2" width="325" height="10" forecolor="#808000" backcolor="#808000"/>
<graphicElement pen="Thin"/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="2" width="230" height="10" backcolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Summary]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="230" y="2" width="55" height="10" backcolor="#808000"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Count :]]></text>
</staticText>
<textField pattern="#0">
<reportElement mode="Opaque" x="285" y="2" width="40" height="10" backcolor="#808000"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{ProductCount}]]></textFieldExpression>
</textField>
</band>
</summary>
</jasperReport>

View File

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created using JasperAssistant (http://www.jasperassistant.com) -->
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="MasterReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="ProductsSubReport" class="net.sf.jasperreports.engine.JasperReport"/>
<parameter name="SubReportData" class="net.sf.jasperreports.engine.JRDataSource"/>
<field name="city" class="java.lang.String">
</field>
<title>
<band height="50">
<line>
<reportElement x="0" y="0" width="515" height="1"/>
<graphicElement/>
</line>
<staticText>
<reportElement x="0" y="10" width="515" height="30"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Normal" size="22"/>
</textElement>
<text><![CDATA[Master Report]]></text>
</staticText>
</band>
</title>
<pageHeader>
<band height="21">
<rectangle>
<reportElement x="0" y="5" width="515" height="15" backcolor="#333333"/>
<graphicElement pen="None"/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="5" width="515" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[City List]]></text>
</staticText>
<line>
<reportElement x="0" y="20" width="515" height="1"/>
<graphicElement/>
</line>
</band>
</pageHeader>
<detail>
<band height="50">
<textField>
<reportElement x="5" y="5" width="100" height="15" isPrintWhenDetailOverflows="true"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{city}]]></textFieldExpression>
</textField>
<staticText>
<reportElement isPrintRepeatedValues="false" x="110" y="5" width="100" height="15" isPrintWhenDetailOverflows="true"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[(continued)]]></text>
</staticText>
<line>
<reportElement x="0" y="20" width="515" height="1" isPrintWhenDetailOverflows="true"/>
<graphicElement/>
</line>
<subreport>
<reportElement isPrintRepeatedValues="false" x="5" y="25" width="325" height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/>
<subreportParameter name="City">
<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression>
<subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{ProductsSubReport}]]></subreportExpression>
</subreport>
<!--<subreport>
<reportElement positionType="Float" x="335" y="25" width="175" height="20" isRemoveLineWhenBlank="true" backcolor="#99ccff"/>
<subreportParameter name="City">
<subreportParameterExpression><![CDATA[$F{City}]]></subreportParameterExpression>
</subreportParameter>
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression class="java.lang.String"><![CDATA["AddressReport.jasper"]]></subreportExpression>
</subreport> -->
</band>
</detail>
<pageFooter>
<band height="40">
<line>
<reportElement x="0" y="10" width="515" height="1"/>
<graphicElement/>
</line>
<textField>
<reportElement x="200" y="20" width="80" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="280" y="20" width="75" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>

View File

@ -16,15 +16,11 @@
package org.springframework.tests;
import java.awt.GraphicsEnvironment;
import java.lang.reflect.Method;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.junit.AssumptionViolatedException;
import org.springframework.util.ClassUtils;
import static org.junit.Assume.*;
/**
@ -89,26 +85,6 @@ public abstract class Assume {
assumeFalse(log.isDebugEnabled());
}
/**
* Assume that we can load fonts.
* <p>See <a href="https://java.net/jira/browse/MACOSX_PORT-355">MACOSX_PORT-355</a>
* issue.
* @throws AssumptionViolatedException if the assumption fails
*/
public static void canLoadNativeDirFonts() {
try {
GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
Class<?> parserClass = ClassUtils.forName(
"net.sf.jasperreports.engine.util.JRStyledTextParser", Assume.class.getClassLoader());
Method method = parserClass.getMethod("getInstance");
method.setAccessible(true);
method.invoke(null);
}
catch (Throwable ex) {
throw new AssumptionViolatedException("Requires GraphicsEnvironment that can load fonts", ex);
}
}
/**
* @since 4.2

View File

@ -1,139 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.io.ByteArrayOutputStream;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JasperPrint;
import org.springframework.ui.jasperreports.JasperReportsUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.util.WebUtils;
/**
* Extends {@code AbstractJasperReportsView} to provide basic rendering logic
* for views that use a fixed format, e.g. always PDF or always HTML.
*
* <p>Subclasses need to implement two template methods: {@code createExporter}
* to create a JasperReports exporter for a specific output format, and
* {@code useWriter} to determine whether to write text or binary content.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.5
* @see #createExporter()
* @see #useWriter()
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public abstract class AbstractJasperReportsSingleFormatView extends AbstractJasperReportsView {
@Override
protected boolean generatesDownloadContent() {
return !useWriter();
}
/**
* Perform rendering for a single Jasper Reports exporter, that is,
* for a pre-defined output format.
*/
@Override
@SuppressWarnings("unchecked")
protected void renderReport(JasperPrint populatedReport, Map<String, Object> model, HttpServletResponse response)
throws Exception {
net.sf.jasperreports.engine.JRExporter exporter = createExporter();
Map<net.sf.jasperreports.engine.JRExporterParameter, Object> mergedExporterParameters = getConvertedExporterParameters();
if (!CollectionUtils.isEmpty(mergedExporterParameters)) {
exporter.setParameters(mergedExporterParameters);
}
if (useWriter()) {
renderReportUsingWriter(exporter, populatedReport, response);
}
else {
renderReportUsingOutputStream(exporter, populatedReport, response);
}
}
/**
* We need to write text to the response Writer.
* @param exporter the JasperReports exporter to use
* @param populatedReport the populated {@code JasperPrint} to render
* @param response the HTTP response the report should be rendered to
* @throws Exception if rendering failed
*/
protected void renderReportUsingWriter(net.sf.jasperreports.engine.JRExporter exporter,
JasperPrint populatedReport, HttpServletResponse response) throws Exception {
// Copy the encoding configured for the report into the response.
String contentType = getContentType();
String encoding = (String) exporter.getParameter(net.sf.jasperreports.engine.JRExporterParameter.CHARACTER_ENCODING);
if (encoding != null) {
// Only apply encoding if content type is specified but does not contain charset clause already.
if (contentType != null && !contentType.toLowerCase().contains(WebUtils.CONTENT_TYPE_CHARSET_PREFIX)) {
contentType = contentType + WebUtils.CONTENT_TYPE_CHARSET_PREFIX + encoding;
}
}
response.setContentType(contentType);
// Render report into HttpServletResponse's Writer.
JasperReportsUtils.render(exporter, populatedReport, response.getWriter());
}
/**
* We need to write binary output to the response OutputStream.
* @param exporter the JasperReports exporter to use
* @param populatedReport the populated {@code JasperPrint} to render
* @param response the HTTP response the report should be rendered to
* @throws Exception if rendering failed
*/
protected void renderReportUsingOutputStream(net.sf.jasperreports.engine.JRExporter exporter,
JasperPrint populatedReport, HttpServletResponse response) throws Exception {
// IE workaround: write into byte array first.
ByteArrayOutputStream baos = createTemporaryOutputStream();
JasperReportsUtils.render(exporter, populatedReport, baos);
writeToResponse(response, baos);
}
/**
* Create a JasperReports exporter for a specific output format,
* which will be used to render the report to the HTTP response.
* <p>The {@code useWriter} method determines whether the
* output will be written as text or as binary content.
* @see #useWriter()
*/
protected abstract net.sf.jasperreports.engine.JRExporter createExporter();
/**
* Return whether to use a {@code java.io.Writer} to write text content
* to the HTTP response. Else, a {@code java.io.OutputStream} will be used,
* to write binary content to the response.
* @see javax.servlet.ServletResponse#getWriter()
* @see javax.servlet.ServletResponse#getOutputStream()
*/
protected abstract boolean useWriter();
}

View File

@ -1,848 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.TimeZone;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRDataSourceProvider;
import net.sf.jasperreports.engine.JRException;
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.design.JasperDesign;
import net.sf.jasperreports.engine.util.JRLoader;
import net.sf.jasperreports.engine.xml.JRXmlLoader;
import org.springframework.context.ApplicationContextException;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.core.io.Resource;
import org.springframework.ui.jasperreports.JasperReportsUtils;
import org.springframework.util.ClassUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.support.RequestContext;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
/**
* Base class for all JasperReports views. Applies on-the-fly compilation
* of report designs as required and coordinates the rendering process.
* The resource path of the main report needs to be specified as {@code url}.
*
* <p>This class is responsible for getting report data from the model that has
* been provided to the view. The default implementation checks for a model object
* under the specified {@code reportDataKey} first, then falls back to looking
* for a value of type {@code JRDataSource}, {@code java.util.Collection},
* object array (in that order).
*
* <p>If no {@code JRDataSource} can be found in the model, then reports will
* be filled using the configured {@code javax.sql.DataSource} if any. If neither
* a {@code JRDataSource} or {@code javax.sql.DataSource} is available then
* an {@code IllegalArgumentException} is raised.
*
* <p>Provides support for sub-reports through the {@code subReportUrls} and
* {@code subReportDataKeys} properties.
*
* <p>When using sub-reports, the master report should be configured using the
* {@code url} property and the sub-reports files should be configured using
* the {@code subReportUrls} property. Each entry in the {@code subReportUrls}
* Map corresponds to an individual sub-report. The key of an entry must match up
* to a sub-report parameter in your report file of type
* {@code net.sf.jasperreports.engine.JasperReport},
* and the value of an entry must be the URL for the sub-report file.
*
* <p>For sub-reports that require an instance of {@code JRDataSource}, that is,
* they don't have a hard-coded query for data retrieval, you can include the
* appropriate data in your model as would with the data source for the parent report.
* However, you must provide a List of parameter names that need to be converted to
* {@code JRDataSource} instances for the sub-report via the
* {@code subReportDataKeys} property. When using {@code JRDataSource}
* instances for sub-reports, you <i>must</i> specify a value for the
* {@code reportDataKey} property, indicating the data to use for the main report.
*
* <p>Allows for exporter parameters to be configured declatively using the
* {@code exporterParameters} property. This is a {@code Map} typed
* property where the key of an entry corresponds to the fully-qualified name
* of the static field for the {@code JRExporterParameter} and the value
* of an entry is the value you want to assign to the exporter parameter.
*
* <p>Response headers can be controlled via the {@code headers} property. Spring
* will attempt to set the correct value for the {@code Content-Diposition} header
* so that reports render correctly in Internet Explorer. However, you can override this
* setting through the {@code headers} property.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.3
* @see #setUrl
* @see #setReportDataKey
* @see #setSubReportUrls
* @see #setSubReportDataKeys
* @see #setHeaders
* @see #setExporterParameters
* @see #setJdbcDataSource
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public abstract class AbstractJasperReportsView extends AbstractUrlBasedView {
/**
* Constant that defines "Content-Disposition" header.
*/
protected static final String HEADER_CONTENT_DISPOSITION = "Content-Disposition";
/**
* The default Content-Disposition header. Used to make IE play nice.
*/
protected static final String CONTENT_DISPOSITION_INLINE = "inline";
/**
* A String key used to lookup the {@code JRDataSource} in the model.
*/
private String reportDataKey;
/**
* Stores the paths to any sub-report files used by this top-level report,
* along with the keys they are mapped to in the top-level report file.
*/
private Properties subReportUrls;
/**
* Stores the names of any data source objects that need to be converted to
* {@code JRDataSource} instances and included in the report parameters
* to be passed on to a sub-report.
*/
private String[] subReportDataKeys;
/**
* Stores the headers to written with each response
*/
private Properties headers;
/**
* Stores the exporter parameters passed in by the user as passed in by the user. May be keyed as
* {@code String}s with the fully qualified name of the exporter parameter field.
*/
private Map<?, ?> exporterParameters = new HashMap<>();
/**
* Stores the converted exporter parameters - keyed by {@code JRExporterParameter}.
*/
private Map<net.sf.jasperreports.engine.JRExporterParameter, Object> convertedExporterParameters;
/**
* Stores the {@code DataSource}, if any, used as the report data source.
*/
private DataSource jdbcDataSource;
/**
* The {@code JasperReport} that is used to render the view.
*/
private JasperReport report;
/**
* Holds mappings between sub-report keys and {@code JasperReport} objects.
*/
private Map<String, JasperReport> subReports;
/**
* Set the name of the model attribute that represents the report data.
* If not specified, the model map will be searched for a matching value type.
* <p>A {@code JRDataSource} will be taken as-is. For other types, conversion
* will apply: By default, a {@code java.util.Collection} will be converted
* to {@code JRBeanCollectionDataSource}, and an object array to
* {@code JRBeanArrayDataSource}.
* <p><b>Note:</b> If you pass in a Collection or object array in the model map
* for use as plain report parameter, rather than as report data to extract fields
* from, you need to specify the key for the actual report data to use, to avoid
* mis-detection of report data by type.
* @see #convertReportData
* @see net.sf.jasperreports.engine.JRDataSource
* @see net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
* @see net.sf.jasperreports.engine.data.JRBeanArrayDataSource
*/
public void setReportDataKey(String reportDataKey) {
this.reportDataKey = reportDataKey;
}
/**
* Specify resource paths which must be loaded as instances of
* {@code JasperReport} and passed to the JasperReports engine for
* rendering as sub-reports, under the same keys as in this mapping.
* @param subReports mapping between model keys and resource paths
* (Spring resource locations)
* @see #setUrl
* @see org.springframework.context.ApplicationContext#getResource
*/
public void setSubReportUrls(Properties subReports) {
this.subReportUrls = subReports;
}
/**
* Set the list of names corresponding to the model parameters that will contain
* data source objects for use in sub-reports. Spring will convert these objects
* to instances of {@code JRDataSource} where applicable and will then
* include the resulting {@code JRDataSource} in the parameters passed into
* the JasperReports engine.
* <p>The name specified in the list should correspond to an attribute in the
* model Map, and to a sub-report data source parameter in your report file.
* If you pass in {@code JRDataSource} objects as model attributes,
* specifying this list of keys is not required.
* <p>If you specify a list of sub-report data keys, it is required to also
* specify a {@code reportDataKey} for the main report, to avoid confusion
* between the data source objects for the various reports involved.
* @param subReportDataKeys list of names for sub-report data source objects
* @see #setReportDataKey
* @see #convertReportData
* @see net.sf.jasperreports.engine.JRDataSource
* @see net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
* @see net.sf.jasperreports.engine.data.JRBeanArrayDataSource
*/
public void setSubReportDataKeys(String... subReportDataKeys) {
this.subReportDataKeys = subReportDataKeys;
}
/**
* Specify the set of headers that are included in each of response.
* @param headers the headers to write to each response.
*/
public void setHeaders(Properties headers) {
this.headers = headers;
}
/**
* Set the exporter parameters that should be used when rendering a view.
* @param parameters {@code Map} with the fully qualified field name
* of the {@code JRExporterParameter} instance as key
* (e.g. "net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI")
* and the value you wish to assign to the parameter as value
*/
public void setExporterParameters(Map<?, ?> parameters) {
this.exporterParameters = parameters;
}
/**
* Return the exporter parameters that this view uses, if any.
*/
public Map<?, ?> getExporterParameters() {
return this.exporterParameters;
}
/**
* Allows subclasses to populate the converted exporter parameters.
*/
protected void setConvertedExporterParameters(Map<net.sf.jasperreports.engine.JRExporterParameter, Object> parameters) {
this.convertedExporterParameters = parameters;
}
/**
* Allows subclasses to retrieve the converted exporter parameters.
*/
protected Map<net.sf.jasperreports.engine.JRExporterParameter, Object> getConvertedExporterParameters() {
return this.convertedExporterParameters;
}
/**
* Specify the {@code javax.sql.DataSource} to use for reports with
* embedded SQL statements.
*/
public void setJdbcDataSource(DataSource jdbcDataSource) {
this.jdbcDataSource = jdbcDataSource;
}
/**
* Return the {@code javax.sql.DataSource} that this view uses, if any.
*/
protected DataSource getJdbcDataSource() {
return this.jdbcDataSource;
}
/**
* JasperReports views do not strictly required a 'url' value.
* Alternatively, the {@link #getReport()} template method may be overridden.
*/
@Override
protected boolean isUrlRequired() {
return false;
}
/**
* Checks to see that a valid report file URL is supplied in the
* configuration. Compiles the report file is necessary.
* <p>Subclasses can add custom initialization logic by overriding
* the {@link #onInit} method.
*/
@Override
protected final void initApplicationContext() throws ApplicationContextException {
this.report = loadReport();
// Load sub reports if required, and check data source parameters.
if (this.subReportUrls != null) {
if (this.subReportDataKeys != null && this.subReportDataKeys.length > 0 && this.reportDataKey == null) {
throw new ApplicationContextException(
"'reportDataKey' for main report is required when specifying a value for 'subReportDataKeys'");
}
this.subReports = new HashMap<>(this.subReportUrls.size());
for (Enumeration<?> urls = this.subReportUrls.propertyNames(); urls.hasMoreElements();) {
String key = (String) urls.nextElement();
String path = this.subReportUrls.getProperty(key);
Resource resource = getApplicationContext().getResource(path);
this.subReports.put(key, loadReport(resource));
}
}
// Convert user-supplied exporterParameters.
convertExporterParameters();
if (this.headers == null) {
this.headers = new Properties();
}
if (!this.headers.containsKey(HEADER_CONTENT_DISPOSITION)) {
this.headers.setProperty(HEADER_CONTENT_DISPOSITION, CONTENT_DISPOSITION_INLINE);
}
onInit();
}
/**
* Subclasses can override this to add some custom initialization logic. Called
* by {@link #initApplicationContext()} as soon as all standard initialization logic
* has finished executing.
* @see #initApplicationContext()
*/
protected void onInit() {
}
/**
* Converts the exporter parameters passed in by the user which may be keyed
* by {@code String}s corresponding to the fully qualified name of the
* {@code JRExporterParameter} into parameters which are keyed by
* {@code JRExporterParameter}.
* @see #getExporterParameter(Object)
*/
protected final void convertExporterParameters() {
if (!CollectionUtils.isEmpty(this.exporterParameters)) {
this.convertedExporterParameters =
new HashMap<>(this.exporterParameters.size());
for (Map.Entry<?, ?> entry : this.exporterParameters.entrySet()) {
net.sf.jasperreports.engine.JRExporterParameter exporterParameter = getExporterParameter(entry.getKey());
this.convertedExporterParameters.put(
exporterParameter, convertParameterValue(exporterParameter, entry.getValue()));
}
}
}
/**
* Convert the supplied parameter value into the actual type required by the
* corresponding {@code JRExporterParameter}.
* <p>The default implementation simply converts the String values "true" and
* "false" into corresponding {@code Boolean} objects, and tries to convert
* String values that start with a digit into {@code Integer} objects
* (simply keeping them as String if number conversion fails).
* @param parameter the parameter key
* @param value the parameter value
* @return the converted parameter value
*/
protected Object convertParameterValue(net.sf.jasperreports.engine.JRExporterParameter parameter, Object value) {
if (value instanceof String) {
String str = (String) value;
if ("true".equals(str)) {
return Boolean.TRUE;
}
else if ("false".equals(str)) {
return Boolean.FALSE;
}
else if (str.length() > 0 && Character.isDigit(str.charAt(0))) {
// Looks like a number... let's try.
try {
return new Integer(str);
}
catch (NumberFormatException ex) {
// OK, then let's keep it as a String value.
return str;
}
}
}
return value;
}
/**
* Return a {@code JRExporterParameter} for the given parameter object,
* converting it from a String if necessary.
* @param parameter the parameter object, either a String or a JRExporterParameter
* @return a JRExporterParameter for the given parameter object
* @see #convertToExporterParameter(String)
*/
protected net.sf.jasperreports.engine.JRExporterParameter getExporterParameter(Object parameter) {
if (parameter instanceof net.sf.jasperreports.engine.JRExporterParameter) {
return (net.sf.jasperreports.engine.JRExporterParameter) parameter;
}
if (parameter instanceof String) {
return convertToExporterParameter((String) parameter);
}
throw new IllegalArgumentException(
"Parameter [" + parameter + "] is invalid type. Should be either String or JRExporterParameter.");
}
/**
* Convert the given fully qualified field name to a corresponding
* JRExporterParameter instance.
* @param fqFieldName the fully qualified field name, consisting
* of the class name followed by a dot followed by the field name
* (e.g. "net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI")
* @return the corresponding JRExporterParameter instance
*/
protected net.sf.jasperreports.engine.JRExporterParameter convertToExporterParameter(String fqFieldName) {
int index = fqFieldName.lastIndexOf('.');
if (index == -1 || index == fqFieldName.length()) {
throw new IllegalArgumentException(
"Parameter name [" + fqFieldName + "] is not a valid static field. " +
"The parameter name must map to a static field such as " +
"[net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI]");
}
String className = fqFieldName.substring(0, index);
String fieldName = fqFieldName.substring(index + 1);
try {
Class<?> cls = ClassUtils.forName(className, getApplicationContext().getClassLoader());
Field field = cls.getField(fieldName);
if (net.sf.jasperreports.engine.JRExporterParameter.class.isAssignableFrom(field.getType())) {
try {
return (net.sf.jasperreports.engine.JRExporterParameter) field.get(null);
}
catch (IllegalAccessException ex) {
throw new IllegalArgumentException(
"Unable to access field [" + fieldName + "] of class [" + className + "]. " +
"Check that it is static and accessible.");
}
}
else {
throw new IllegalArgumentException("Field [" + fieldName + "] on class [" + className +
"] is not assignable from JRExporterParameter - check the type of this field.");
}
}
catch (ClassNotFoundException ex) {
throw new IllegalArgumentException(
"Class [" + className + "] in key [" + fqFieldName + "] could not be found.");
}
catch (NoSuchFieldException ex) {
throw new IllegalArgumentException("Field [" + fieldName + "] in key [" + fqFieldName +
"] could not be found on class [" + className + "].");
}
}
/**
* Load the main {@code JasperReport} from the specified {@code Resource}.
* If the {@code Resource} points to an uncompiled report design file then the
* report file is compiled dynamically and loaded into memory.
* @return a {@code JasperReport} instance, or {@code null} if no main
* report has been statically defined
*/
protected JasperReport loadReport() {
String url = getUrl();
if (url == null) {
return null;
}
Resource mainReport = getApplicationContext().getResource(url);
return loadReport(mainReport);
}
/**
* Loads a {@code JasperReport} from the specified {@code Resource}.
* If the {@code Resource} points to an uncompiled report design file then
* the report file is compiled dynamically and loaded into memory.
* @param resource the {@code Resource} containing the report definition or design
* @return a {@code JasperReport} instance
*/
protected final JasperReport loadReport(Resource resource) {
try {
String filename = resource.getFilename();
if (filename != null) {
if (filename.endsWith(".jasper")) {
// Load pre-compiled report.
if (logger.isInfoEnabled()) {
logger.info("Loading pre-compiled Jasper Report from " + resource);
}
InputStream is = resource.getInputStream();
try {
return (JasperReport) JRLoader.loadObject(is);
}
finally {
is.close();
}
}
else if (filename.endsWith(".jrxml")) {
// Compile report on-the-fly.
if (logger.isInfoEnabled()) {
logger.info("Compiling Jasper Report loaded from " + resource);
}
InputStream is = resource.getInputStream();
try {
JasperDesign design = JRXmlLoader.load(is);
return JasperCompileManager.compileReport(design);
}
finally {
is.close();
}
}
}
throw new IllegalArgumentException(
"Report filename [" + filename + "] must end in either .jasper or .jrxml");
}
catch (IOException ex) {
throw new ApplicationContextException(
"Could not load JasperReports report from " + resource, ex);
}
catch (JRException ex) {
throw new ApplicationContextException(
"Could not parse JasperReports report from " + resource, ex);
}
}
/**
* Finds the report data to use for rendering the report and then invokes the
* {@link #renderReport} method that should be implemented by the subclass.
* @param model the model map, as passed in for view rendering. Must contain
* a report data value that can be converted to a {@code JRDataSource},
* according to the rules of the {@link #fillReport} method.
*/
@Override
protected void renderMergedOutputModel(
Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (this.subReports != null) {
// Expose sub-reports as model attributes.
model.putAll(this.subReports);
// Transform any collections etc into JRDataSources for sub reports.
if (this.subReportDataKeys != null) {
for (String key : this.subReportDataKeys) {
model.put(key, convertReportData(model.get(key)));
}
}
}
// Expose Spring-managed Locale and MessageSource.
exposeLocalizationContext(model, request);
// Fill the report.
JasperPrint filledReport = fillReport(model);
postProcessReport(filledReport, model);
// Prepare response and render report.
populateHeaders(response);
renderReport(filledReport, model, response);
}
/**
* Expose current Spring-managed Locale and MessageSource to JasperReports i18n
* ($R expressions etc). The MessageSource should only be exposed as JasperReports
* resource bundle if no such bundle is defined in the report itself.
* <p>The default implementation exposes the Spring RequestContext Locale and a
* MessageSourceResourceBundle adapter for the Spring ApplicationContext,
* analogous to the {@code JstlUtils.exposeLocalizationContext} method.
* @see org.springframework.web.servlet.support.RequestContextUtils#getLocale
* @see org.springframework.context.support.MessageSourceResourceBundle
* @see #getApplicationContext()
* @see net.sf.jasperreports.engine.JRParameter#REPORT_LOCALE
* @see net.sf.jasperreports.engine.JRParameter#REPORT_RESOURCE_BUNDLE
* @see org.springframework.web.servlet.support.JstlUtils#exposeLocalizationContext
*/
protected void exposeLocalizationContext(Map<String, Object> model, HttpServletRequest request) {
RequestContext rc = new RequestContext(request, getServletContext());
Locale locale = rc.getLocale();
if (!model.containsKey(JRParameter.REPORT_LOCALE)) {
model.put(JRParameter.REPORT_LOCALE, locale);
}
TimeZone timeZone = rc.getTimeZone();
if (timeZone != null && !model.containsKey(JRParameter.REPORT_TIME_ZONE)) {
model.put(JRParameter.REPORT_TIME_ZONE, timeZone);
}
JasperReport report = getReport();
if ((report == null || report.getResourceBundle() == null) &&
!model.containsKey(JRParameter.REPORT_RESOURCE_BUNDLE)) {
model.put(JRParameter.REPORT_RESOURCE_BUNDLE,
new MessageSourceResourceBundle(rc.getMessageSource(), locale));
}
}
/**
* Create a populated {@code JasperPrint} instance from the configured
* {@code JasperReport} instance.
* <p>By default, this method will use any {@code JRDataSource} instance
* (or wrappable {@code Object}) that can be located using {@link #setReportDataKey},
* a lookup for type {@code JRDataSource} in the model Map, or a special value
* retrieved via {@link #getReportData}.
* <p>If no {@code JRDataSource} can be found, this method will use a JDBC
* {@code Connection} obtained from the configured {@code javax.sql.DataSource}
* (or a DataSource attribute in the model). If no JDBC DataSource can be found
* either, the JasperReports engine will be invoked with plain model Map,
* assuming that the model contains parameters that identify the source
* for report data (e.g. Hibernate or JPA queries).
* @param model the model for this request
* @throws IllegalArgumentException if no {@code JRDataSource} can be found
* and no {@code javax.sql.DataSource} is supplied
* @throws SQLException if there is an error when populating the report using
* the {@code javax.sql.DataSource}
* @throws JRException if there is an error when populating the report using
* a {@code JRDataSource}
* @return the populated {@code JasperPrint} instance
* @see #getReportData
* @see #setJdbcDataSource
*/
protected JasperPrint fillReport(Map<String, Object> model) throws Exception {
// Determine main report.
JasperReport report = getReport();
if (report == null) {
throw new IllegalStateException("No main report defined for 'fillReport' - " +
"specify a 'url' on this view or override 'getReport()' or 'fillReport(Map)'");
}
JRDataSource jrDataSource = null;
DataSource jdbcDataSourceToUse = null;
// Try model attribute with specified name.
if (this.reportDataKey != null) {
Object reportDataValue = model.get(this.reportDataKey);
if (reportDataValue instanceof DataSource) {
jdbcDataSourceToUse = (DataSource) reportDataValue;
}
else {
jrDataSource = convertReportData(reportDataValue);
}
}
else {
Collection<?> values = model.values();
jrDataSource = CollectionUtils.findValueOfType(values, JRDataSource.class);
if (jrDataSource == null) {
JRDataSourceProvider provider = CollectionUtils.findValueOfType(values, JRDataSourceProvider.class);
if (provider != null) {
jrDataSource = createReport(provider);
}
else {
jdbcDataSourceToUse = CollectionUtils.findValueOfType(values, DataSource.class);
if (jdbcDataSourceToUse == null) {
jdbcDataSourceToUse = this.jdbcDataSource;
}
}
}
}
if (jdbcDataSourceToUse != null) {
return doFillReport(report, model, jdbcDataSourceToUse);
}
else {
// Determine JRDataSource for main report.
if (jrDataSource == null) {
jrDataSource = getReportData(model);
}
if (jrDataSource != null) {
// Use the JasperReports JRDataSource.
if (logger.isDebugEnabled()) {
logger.debug("Filling report with JRDataSource [" + jrDataSource + "]");
}
return JasperFillManager.fillReport(report, model, jrDataSource);
}
else {
// Assume that the model contains parameters that identify
// the source for report data (e.g. Hibernate or JPA queries).
logger.debug("Filling report with plain model");
return JasperFillManager.fillReport(report, model);
}
}
}
/**
* Fill the given report using the given JDBC DataSource and model.
*/
private JasperPrint doFillReport(JasperReport report, Map<String, Object> model, DataSource ds) throws Exception {
// Use the JDBC DataSource.
if (logger.isDebugEnabled()) {
logger.debug("Filling report using JDBC DataSource [" + ds + "]");
}
Connection con = ds.getConnection();
try {
return JasperFillManager.fillReport(report, model, con);
}
finally {
try {
con.close();
}
catch (Throwable ex) {
logger.debug("Could not close JDBC Connection", ex);
}
}
}
/**
* Populates the headers in the {@code HttpServletResponse} with the
* headers supplied by the user.
*/
private void populateHeaders(HttpServletResponse response) {
// Apply the headers to the response.
for (Enumeration<?> en = this.headers.propertyNames(); en.hasMoreElements();) {
String key = (String) en.nextElement();
response.addHeader(key, this.headers.getProperty(key));
}
}
/**
* Determine the {@code JasperReport} to fill.
* Called by {@link #fillReport}.
* <p>The default implementation returns the report as statically configured
* through the 'url' property (and loaded by {@link #loadReport()}).
* Can be overridden in subclasses in order to dynamically obtain a
* {@code JasperReport} instance. As an alternative, consider
* overriding the {@link #fillReport} template method itself.
* @return an instance of {@code JasperReport}
*/
protected JasperReport getReport() {
return this.report;
}
/**
* Create an appropriate {@code JRDataSource} for passed-in report data.
* Called by {@link #fillReport} when its own lookup steps were not successful.
* <p>The default implementation looks for a value of type {@code java.util.Collection}
* or object array (in that order). Can be overridden in subclasses.
* @param model the model map, as passed in for view rendering
* @return the {@code JRDataSource} or {@code null} if the data source is not found
* @see #getReportDataTypes
* @see #convertReportData
*/
protected JRDataSource getReportData(Map<String, Object> model) {
// Try to find matching attribute, of given prioritized types.
Object value = CollectionUtils.findValueOfType(model.values(), getReportDataTypes());
return (value != null ? convertReportData(value) : null);
}
/**
* Convert the given report data value to a {@code JRDataSource}.
* <p>The default implementation delegates to {@code JasperReportUtils} unless
* the report data value is an instance of {@code JRDataSourceProvider}.
* A {@code JRDataSource}, {@code JRDataSourceProvider},
* {@code java.util.Collection} or object array is detected.
* {@code JRDataSource}s are returned as is, whilst {@code JRDataSourceProvider}s
* are used to create an instance of {@code JRDataSource} which is then returned.
* The latter two are converted to {@code JRBeanCollectionDataSource} or
* {@code JRBeanArrayDataSource}, respectively.
* @param value the report data value to convert
* @return the JRDataSource
* @throws IllegalArgumentException if the value could not be converted
* @see org.springframework.ui.jasperreports.JasperReportsUtils#convertReportData
* @see net.sf.jasperreports.engine.JRDataSource
* @see net.sf.jasperreports.engine.JRDataSourceProvider
* @see net.sf.jasperreports.engine.data.JRBeanCollectionDataSource
* @see net.sf.jasperreports.engine.data.JRBeanArrayDataSource
*/
protected JRDataSource convertReportData(Object value) throws IllegalArgumentException {
if (value instanceof JRDataSourceProvider) {
return createReport((JRDataSourceProvider) value);
}
else {
return JasperReportsUtils.convertReportData(value);
}
}
/**
* Create a report using the given provider.
* @param provider the JRDataSourceProvider to use
* @return the created report
*/
protected JRDataSource createReport(JRDataSourceProvider provider) {
try {
JasperReport report = getReport();
if (report == null) {
throw new IllegalStateException("No main report defined for JRDataSourceProvider - " +
"specify a 'url' on this view or override 'getReport()'");
}
return provider.create(report);
}
catch (JRException ex) {
throw new IllegalArgumentException("Supplied JRDataSourceProvider is invalid", ex);
}
}
/**
* Return the value types that can be converted to a {@code JRDataSource},
* in prioritized order. Should only return types that the
* {@link #convertReportData} method is actually able to convert.
* <p>Default value types are: {@code java.util.Collection} and {@code Object} array.
* @return the value types in prioritized order
*/
protected Class<?>[] getReportDataTypes() {
return new Class<?>[] {Collection.class, Object[].class};
}
/**
* Template method to be overridden for custom post-processing of the
* populated report. Invoked after filling but before rendering.
* <p>The default implementation is empty.
* @param populatedReport the populated {@code JasperPrint}
* @param model the map containing report parameters
* @throws Exception if post-processing failed
*/
protected void postProcessReport(JasperPrint populatedReport, Map<String, Object> model) throws Exception {
}
/**
* Subclasses should implement this method to perform the actual rendering process.
* <p>Note that the content type has not been set yet: Implementers should build
* a content type String and set it via {@code response.setContentType}.
* If necessary, this can include a charset clause for a specific encoding.
* The latter will only be necessary for textual output onto a Writer, and only
* in case of the encoding being specified in the JasperReports exporter parameters.
* <p><b>WARNING:</b> Implementers should not use {@code response.setCharacterEncoding}
* unless they are willing to depend on Servlet API 2.4 or higher. Prefer a
* concatenated content type String with a charset clause instead.
* @param populatedReport the populated {@code JasperPrint} to render
* @param model the map containing report parameters
* @param response the HTTP response the report should be rendered to
* @throws Exception if rendering failed
* @see #getContentType()
* @see javax.servlet.ServletResponse#setContentType
* @see javax.servlet.ServletResponse#setCharacterEncoding
*/
protected abstract void renderReport(
JasperPrint populatedReport, Map<String, Object> model, HttpServletResponse response)
throws Exception;
}

View File

@ -1,94 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import org.springframework.beans.BeanUtils;
import org.springframework.util.Assert;
/**
* Configurable JasperReports View, allowing to specify the JasperReports exporter
* to be specified through bean properties rather than through the view class name.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @since 2.0
* @see JasperReportsCsvView
* @see JasperReportsHtmlView
* @see JasperReportsPdfView
* @see JasperReportsXlsView
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public class ConfigurableJasperReportsView extends AbstractJasperReportsSingleFormatView {
private Class<? extends net.sf.jasperreports.engine.JRExporter> exporterClass;
private boolean useWriter = true;
/**
* Set the {@code JRExporter} implementation {@code Class} to use. Throws
* {@link IllegalArgumentException} if the {@code Class} doesn't implement
* {@code JRExporter}. Required setting, as it does not have a default.
*/
public void setExporterClass(Class<? extends net.sf.jasperreports.engine.JRExporter> exporterClass) {
Assert.isAssignable(net.sf.jasperreports.engine.JRExporter.class, exporterClass);
this.exporterClass = exporterClass;
}
/**
* Specifies whether or not the {@code JRExporter} writes to the {@link java.io.PrintWriter}
* of the associated with the request ({@code true}) or whether it writes directly to the
* {@link java.io.InputStream} of the request ({@code false}). Default is {@code true}.
*/
public void setUseWriter(boolean useWriter) {
this.useWriter = useWriter;
}
/**
* Checks that the {@link #setExporterClass(Class) exporterClass} property is specified.
*/
@Override
protected void onInit() {
if (this.exporterClass == null) {
throw new IllegalArgumentException("exporterClass is required");
}
}
/**
* Returns a new instance of the specified {@link net.sf.jasperreports.engine.JRExporter} class.
* @see #setExporterClass(Class)
* @see BeanUtils#instantiateClass(Class)
*/
@Override
protected net.sf.jasperreports.engine.JRExporter createExporter() {
return BeanUtils.instantiateClass(this.exporterClass);
}
/**
* Indicates how the {@code JRExporter} should render its data.
* @see #setUseWriter(boolean)
*/
@Override
protected boolean useWriter() {
return this.useWriter;
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import net.sf.jasperreports.engine.export.JRCsvExporter;
/**
* Implementation of {@code AbstractJasperReportsSingleFormatView}
* that renders report results in CSV format.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.3
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public class JasperReportsCsvView extends AbstractJasperReportsSingleFormatView {
public JasperReportsCsvView() {
setContentType("text/csv");
}
@Override
protected net.sf.jasperreports.engine.JRExporter createExporter() {
return new JRCsvExporter();
}
@Override
protected boolean useWriter() {
return true;
}
}

View File

@ -1,48 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
/**
* Implementation of {@code AbstractJasperReportsSingleFormatView}
* that renders report results in HTML format.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.3
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public class JasperReportsHtmlView extends AbstractJasperReportsSingleFormatView {
public JasperReportsHtmlView() {
setContentType("text/html");
}
@Override
protected net.sf.jasperreports.engine.JRExporter createExporter() {
return new net.sf.jasperreports.engine.export.JRHtmlExporter();
}
@Override
protected boolean useWriter() {
return true;
}
}

View File

@ -1,219 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JasperPrint;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
/**
* JasperReports view class that allows for the actual rendering format
* to be specified at runtime using a parameter contained in the model.
*
* <p>This view works on the concept of a format key and a mapping key.
* The format key is used to pass the mapping key from your {@code Controller}
* to Spring through as part of the model and the mapping key is used to map
* a logical format to an actual JasperReports view class.
*
* <p>For example, you might add the following code to your {@code Controller}:
*
* <pre class="code">
* Map<String, Object> model = new HashMap<String, Object>();
* model.put("format", "pdf");</pre>
*
* Here {@code format} is the format key and {@code pdf} is the mapping key.
* When rendering a report, this class looks for a model parameter under the
* format key, which by default is {@code format}. It then uses the value of
* this parameter to lookup the actual {@code View} class to use.
*
* <p>The default mappings for the format lookup are:
*
* <p><ul>
* <li>{@code csv} - {@code JasperReportsCsvView}</li>
* <li>{@code html} - {@code JasperReportsHtmlView}</li>
* <li>{@code pdf} - {@code JasperReportsPdfView}</li>
* <li>{@code xls} - {@code JasperReportsXlsView}</li>
* <li>{@code xlsx} - {@code JasperReportsXlsxView}</li> (as of Spring 4.2)
* </ul>
*
* <p>The format key can be changed using the {@code formatKey} property.
* The applicable key-to-view-class mappings can be configured using the
* {@code formatMappings} property.
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.5
* @see #setFormatKey
* @see #setFormatMappings
*/
public class JasperReportsMultiFormatView extends AbstractJasperReportsView {
/**
* Default value used for format key: "format"
*/
public static final String DEFAULT_FORMAT_KEY = "format";
/**
* The key of the model parameter that holds the format key.
*/
private String formatKey = DEFAULT_FORMAT_KEY;
/**
* Stores the format mappings, with the format discriminator
* as key and the corresponding view class as value.
*/
private Map<String, Class<? extends AbstractJasperReportsView>> formatMappings;
/**
* Stores the mappings of mapping keys to Content-Disposition header values.
*/
private Properties contentDispositionMappings;
/**
* Creates a new {@code JasperReportsMultiFormatView} instance
* with a default set of mappings.
*/
public JasperReportsMultiFormatView() {
this.formatMappings = new HashMap<>(4);
this.formatMappings.put("csv", JasperReportsCsvView.class);
this.formatMappings.put("html", JasperReportsHtmlView.class);
this.formatMappings.put("pdf", JasperReportsPdfView.class);
this.formatMappings.put("xls", JasperReportsXlsView.class);
this.formatMappings.put("xlsx", JasperReportsXlsxView.class);
}
/**
* Set the key of the model parameter that holds the format discriminator.
* Default is "format".
*/
public void setFormatKey(String formatKey) {
this.formatKey = formatKey;
}
/**
* Set the mappings of format discriminators to view class names.
* The default mappings are:
* <p><ul>
* <li>{@code csv} - {@code JasperReportsCsvView}</li>
* <li>{@code html} - {@code JasperReportsHtmlView}</li>
* <li>{@code pdf} - {@code JasperReportsPdfView}</li>
* <li>{@code xls} - {@code JasperReportsXlsView}</li>
* <li>{@code xlsx} - {@code JasperReportsXlsxView}</li> (as of Spring 4.2)
* </ul>
*/
public void setFormatMappings(Map<String, Class<? extends AbstractJasperReportsView>> formatMappings) {
if (CollectionUtils.isEmpty(formatMappings)) {
throw new IllegalArgumentException("'formatMappings' must not be empty");
}
this.formatMappings = formatMappings;
}
/**
* Set the mappings of {@code Content-Disposition} header values to
* mapping keys. If specified, Spring will look at these mappings to determine
* the value of the {@code Content-Disposition} header for a given
* format mapping.
*/
public void setContentDispositionMappings(Properties mappings) {
this.contentDispositionMappings = mappings;
}
/**
* Return the mappings of {@code Content-Disposition} header values to
* mapping keys. Mainly available for configuration through property paths
* that specify individual keys.
*/
public Properties getContentDispositionMappings() {
if (this.contentDispositionMappings == null) {
this.contentDispositionMappings = new Properties();
}
return this.contentDispositionMappings;
}
@Override
protected boolean generatesDownloadContent() {
return true;
}
/**
* Locates the format key in the model using the configured discriminator key and uses this
* key to lookup the appropriate view class from the mappings. The rendering of the
* report is then delegated to an instance of that view class.
*/
@Override
protected void renderReport(JasperPrint populatedReport, Map<String, Object> model, HttpServletResponse response)
throws Exception {
String format = (String) model.get(this.formatKey);
if (format == null) {
throw new IllegalArgumentException("No format found in model");
}
if (logger.isDebugEnabled()) {
logger.debug("Rendering report using format mapping key [" + format + "]");
}
Class<? extends AbstractJasperReportsView> viewClass = this.formatMappings.get(format);
if (viewClass == null) {
throw new IllegalArgumentException("Format discriminator [" + format + "] is not a configured mapping");
}
if (logger.isDebugEnabled()) {
logger.debug("Rendering report using view class [" + viewClass.getName() + "]");
}
AbstractJasperReportsView view = BeanUtils.instantiateClass(viewClass);
// Can skip most initialization since all relevant URL processing
// has been done - just need to convert parameters on the sub view.
view.setExporterParameters(getExporterParameters());
view.setConvertedExporterParameters(getConvertedExporterParameters());
// Prepare response and render report.
populateContentDispositionIfNecessary(response, format);
view.renderReport(populatedReport, model, response);
}
/**
* Adds/overwrites the {@code Content-Disposition} header value with the format-specific
* value if the mappings have been specified and a valid one exists for the given format.
* @param response the {@code HttpServletResponse} to set the header in
* @param format the format key of the mapping
* @see #setContentDispositionMappings
*/
private void populateContentDispositionIfNecessary(HttpServletResponse response, String format) {
if (this.contentDispositionMappings != null) {
String header = this.contentDispositionMappings.getProperty(format);
if (header != null) {
if (logger.isDebugEnabled()) {
logger.debug("Setting Content-Disposition header to: [" + header + "]");
}
response.setHeader(HEADER_CONTENT_DISPOSITION, header);
}
}
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import net.sf.jasperreports.engine.export.JRPdfExporter;
/**
* Implementation of {@code AbstractJasperReportsSingleFormatView}
* that renders report results in PDF format.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.3
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public class JasperReportsPdfView extends AbstractJasperReportsSingleFormatView {
public JasperReportsPdfView() {
setContentType("application/pdf");
}
@Override
protected net.sf.jasperreports.engine.JRExporter createExporter() {
return new JRPdfExporter();
}
@Override
protected boolean useWriter() {
return false;
}
}

View File

@ -1,119 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.sql.DataSource;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
/**
* {@link org.springframework.web.servlet.ViewResolver} implementation that
* resolves instances of {@link AbstractJasperReportsView} by translating
* the supplied view name into the URL of the report file.
*
* @author Rob Harrop
* @since 1.2.6
*/
public class JasperReportsViewResolver extends UrlBasedViewResolver {
private String reportDataKey;
private Properties subReportUrls;
private String[] subReportDataKeys;
private Properties headers;
private Map<String, Object> exporterParameters = new HashMap<>();
private DataSource jdbcDataSource;
/**
* Requires the view class to be a subclass of {@link AbstractJasperReportsView}.
*/
@Override
protected Class<?> requiredViewClass() {
return AbstractJasperReportsView.class;
}
/**
* Set the {@code reportDataKey} the view class should use.
* @see AbstractJasperReportsView#setReportDataKey
*/
public void setReportDataKey(String reportDataKey) {
this.reportDataKey = reportDataKey;
}
/**
* Set the {@code subReportUrls} the view class should use.
* @see AbstractJasperReportsView#setSubReportUrls
*/
public void setSubReportUrls(Properties subReportUrls) {
this.subReportUrls = subReportUrls;
}
/**
* Set the {@code subReportDataKeys} the view class should use.
* @see AbstractJasperReportsView#setSubReportDataKeys
*/
public void setSubReportDataKeys(String... subReportDataKeys) {
this.subReportDataKeys = subReportDataKeys;
}
/**
* Set the {@code headers} the view class should use.
* @see AbstractJasperReportsView#setHeaders
*/
public void setHeaders(Properties headers) {
this.headers = headers;
}
/**
* Set the {@code exporterParameters} the view class should use.
* @see AbstractJasperReportsView#setExporterParameters
*/
public void setExporterParameters(Map<String, Object> exporterParameters) {
this.exporterParameters = exporterParameters;
}
/**
* Set the {@link DataSource} the view class should use.
* @see AbstractJasperReportsView#setJdbcDataSource
*/
public void setJdbcDataSource(DataSource jdbcDataSource) {
this.jdbcDataSource = jdbcDataSource;
}
@Override
protected AbstractUrlBasedView buildView(String viewName) throws Exception {
AbstractJasperReportsView view = (AbstractJasperReportsView) super.buildView(viewName);
view.setReportDataKey(this.reportDataKey);
view.setSubReportUrls(this.subReportUrls);
view.setSubReportDataKeys(this.subReportDataKeys);
view.setHeaders(this.headers);
view.setExporterParameters(this.exporterParameters);
view.setJdbcDataSource(this.jdbcDataSource);
return view;
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2002-2014 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import net.sf.jasperreports.engine.export.JRXlsExporter;
/**
* Implementation of {@code AbstractJasperReportsSingleFormatView}
* that renders report results in XLS format.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 1.1.3
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public class JasperReportsXlsView extends AbstractJasperReportsSingleFormatView {
public JasperReportsXlsView() {
setContentType("application/vnd.ms-excel");
}
@Override
protected net.sf.jasperreports.engine.JRExporter createExporter() {
return new JRXlsExporter();
}
@Override
protected boolean useWriter() {
return false;
}
}

View File

@ -1,50 +0,0 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter;
/**
* Implementation of {@code AbstractJasperReportsSingleFormatView}
* that renders report results in XLSX format.
*
* <p><b>This class is compatible with classic JasperReports releases back until 2.x.</b>
* As a consequence, it keeps using the {@link net.sf.jasperreports.engine.JRExporter}
* API which got deprecated as of JasperReports 5.5.2 (early 2014).
*
* @author Rob Harrop
* @author Juergen Hoeller
* @since 4.2
*/
@SuppressWarnings({"deprecation", "rawtypes"})
public class JasperReportsXlsxView extends AbstractJasperReportsSingleFormatView {
public JasperReportsXlsxView() {
setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
@Override
protected net.sf.jasperreports.engine.JRExporter createExporter() {
return new JRXlsxExporter();
}
@Override
protected boolean useWriter() {
return false;
}
}

View File

@ -1,7 +0,0 @@
/**
* Support classes for the integration of
* <a href="http://jasperreports.sourceforge.net">JasperReports</a>
* as Spring web view technology.
* Contains various View implementations for JasperReports.
*/
package org.springframework.web.servlet.view.jasperreports;

View File

@ -1,36 +0,0 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import org.junit.Test;
import org.springframework.context.support.StaticApplicationContext;
/**
* @author Rob Harrop
*/
public abstract class AbstractConfigurableJasperReportsViewTests extends AbstractJasperReportsViewTests {
@Test(expected = IllegalArgumentException.class)
public void noConfiguredExporter() throws Exception {
ConfigurableJasperReportsView view = new ConfigurableJasperReportsView();
view.setUrl(COMPILED_REPORT);
// Should not be able to set up view class without an exporter class.
view.setApplicationContext(new StaticApplicationContext());
}
}

View File

@ -1,109 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.junit.BeforeClass;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.mock.web.test.MockHttpServletResponse;
import org.springframework.tests.Assume;
import org.springframework.ui.jasperreports.PersonBean;
import org.springframework.ui.jasperreports.ProductBean;
import org.springframework.util.ClassUtils;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.i18n.AcceptHeaderLocaleResolver;
/**
* @author Rob Harrop
* @author Juergen Hoeller
* @author Sam Brannen
*/
public abstract class AbstractJasperReportsTests {
protected static final String COMPILED_REPORT = "/org/springframework/ui/jasperreports/DataSourceReport.jasper";
protected static final String UNCOMPILED_REPORT = "/org/springframework/ui/jasperreports/DataSourceReport.jrxml";
protected static final String SUB_REPORT_PARENT = "/org/springframework/ui/jasperreports/subReportParent.jrxml";
protected static final boolean canCompileReport = ClassUtils.isPresent(
"org.eclipse.jdt.internal.compiler.Compiler", AbstractJasperReportsTests.class.getClassLoader());
protected final MockHttpServletResponse response = new MockHttpServletResponse();
protected final MockHttpServletRequest request = new MockHttpServletRequest();
{
request.setAttribute(DispatcherServlet.LOCALE_RESOLVER_ATTRIBUTE, new AcceptHeaderLocaleResolver());
request.addPreferredLocale(Locale.GERMAN);
}
@BeforeClass
public static void assumptions() {
Assume.canLoadNativeDirFonts();
}
protected Map<String, Object> getModel() {
Map<String, Object> model = new HashMap<>();
model.put("ReportTitle", "Dear Lord!");
model.put("dataSource", new JRBeanCollectionDataSource(getData()));
extendModel(model);
return model;
}
/**
* Subclasses can extend the model if they need to.
*/
protected void extendModel(Map<String, Object> model) {
}
protected List<Object> getData() {
List<Object> list = new ArrayList<>();
for (int x = 0; x < 10; x++) {
PersonBean bean = new PersonBean();
bean.setId(x);
bean.setName("Rob Harrop");
bean.setStreet("foo");
list.add(bean);
}
return list;
}
protected List<Object> getProductData() {
List<Object> list = new ArrayList<>();
for (int x = 0; x < 10; x++) {
ProductBean bean = new ProductBean();
bean.setId(x);
bean.setName("Foo Bar");
bean.setPrice(1.9f);
bean.setQuantity(1.0f);
list.add(bean);
}
return list;
}
}

View File

@ -1,414 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRAbstractBeanDataSourceProvider;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.context.ApplicationContextException;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.ui.jasperreports.PersonBean;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import static org.mockito.BDDMockito.*;
/**
* @author Rob Harrop
* @author Juergen Hoeller
* @author Sam Brannen
*/
@SuppressWarnings("deprecation")
public abstract class AbstractJasperReportsViewTests extends AbstractJasperReportsTests {
@Rule
public final ExpectedException exception = ExpectedException.none();
/**
* Simple test to see if compiled report succeeds.
*/
@Test
public void compiledReport() throws Exception {
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(getModel(), request, response);
assertTrue(response.getContentAsByteArray().length > 0);
assumeTrue(view instanceof AbstractJasperReportsSingleFormatView
&& ((AbstractJasperReportsSingleFormatView) view).useWriter());
String output = response.getContentAsString();
assertTrue("Output should contain 'MeineSeite'", output.contains("MeineSeite"));
}
@Test
public void uncompiledReport() throws Exception {
assumeTrue(canCompileReport);
AbstractJasperReportsView view = getView(UNCOMPILED_REPORT);
view.render(getModel(), request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
public void withInvalidPath() throws Exception {
exception.expect(ApplicationContextException.class);
getView("foo.jasper");
}
@Test
public void invalidExtension() throws Exception {
exception.expect(IllegalArgumentException.class);
getView("foo.bar");
}
@Test
public void contentType() throws Exception {
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(getModel(), request, response);
assertEquals("Response content type is incorrect", getDesiredContentType(), response.getContentType());
}
@Test
public void withoutDatasource() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(model, request, response);
assertTrue(response.getStatus() == HttpServletResponse.SC_OK);
}
@Test
public void withCollection() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("reportData", getData());
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(model, request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
@SuppressWarnings("rawtypes")
public void withMultipleCollections() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("reportData", getData());
model.put("otherData", new LinkedList());
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(model, request, response);
// no clear data source found
}
@Test
public void withJRDataSourceProvider() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("dataSource", new MockDataSourceProvider(PersonBean.class));
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(model, request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
@SuppressWarnings("rawtypes")
public void withSpecificCollection() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("reportData", getData());
model.put("otherData", new LinkedList());
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.setReportDataKey("reportData");
view.render(model, request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
public void withArray() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("reportData", getData().toArray());
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(model, request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
public void withMultipleArrays() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("reportData", getData().toArray());
model.put("otherData", new String[0]);
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(model, request, response);
// no clear data source found
}
@Test
public void withSpecificArray() throws Exception {
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("reportData", getData().toArray());
model.put("otherData", new String[0]);
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.setReportDataKey("reportData");
view.render(model, request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
public void withSubReport() throws Exception {
assumeTrue(canCompileReport);
Map<String, Object> model = getModel();
model.put("SubReportData", getProductData());
Properties subReports = new Properties();
subReports.put("ProductsSubReport", "/org/springframework/ui/jasperreports/subReportChild.jrxml");
AbstractJasperReportsView view = getView(SUB_REPORT_PARENT);
view.setReportDataKey("dataSource");
view.setSubReportUrls(subReports);
view.setSubReportDataKeys(new String[]{"SubReportData"});
view.initApplicationContext();
view.render(model, request, response);
assertTrue(response.getContentAsByteArray().length > 0);
}
@Test
public void withNonExistentSubReport() throws Exception {
assumeTrue(canCompileReport);
Map<String, Object> model = getModel();
model.put("SubReportData", getProductData());
Properties subReports = new Properties();
subReports.put("ProductsSubReport", "org/springframework/ui/jasperreports/subReportChildFalse.jrxml");
AbstractJasperReportsView view = getView(SUB_REPORT_PARENT);
view.setReportDataKey("dataSource");
view.setSubReportUrls(subReports);
view.setSubReportDataKeys(new String[]{"SubReportData"});
// Invalid report URL should throw ApplicationContextException
exception.expect(ApplicationContextException.class);
view.initApplicationContext();
}
// TODO Determine why encoding does not get overridden.
@Ignore("Disabled since encoding does not get overridden")
@Test
public void overrideExporterParameters() throws Exception {
AbstractJasperReportsView view = getView(COMPILED_REPORT);
assumeTrue(view instanceof AbstractJasperReportsSingleFormatView
&& ((AbstractJasperReportsSingleFormatView) view).useWriter());
String characterEncoding = "UTF-8";
String overiddenCharacterEncoding = "ASCII";
Map<Object, Object> parameters = new HashMap<>();
parameters.put(net.sf.jasperreports.engine.JRExporterParameter.CHARACTER_ENCODING, characterEncoding);
view.setExporterParameters(parameters);
view.convertExporterParameters();
Map<String, Object> model = getModel();
model.put(net.sf.jasperreports.engine.JRExporterParameter.CHARACTER_ENCODING.toString(),
overiddenCharacterEncoding);
view.render(model, this.request, this.response);
assertEquals(overiddenCharacterEncoding, this.response.getCharacterEncoding());
}
@Test
public void subReportWithUnspecifiedParentDataSource() throws Exception {
assumeTrue(canCompileReport);
Map<String, Object> model = getModel();
model.put("SubReportData", getProductData());
Properties subReports = new Properties();
subReports.put("ProductsSubReport", "org/springframework/ui/jasperreports/subReportChildFalse.jrxml");
AbstractJasperReportsView view = getView(SUB_REPORT_PARENT);
view.setSubReportUrls(subReports);
view.setSubReportDataKeys(new String[]{"SubReportData"});
// Unspecified reportDataKey should throw exception when subReportDataSources is specified
exception.expect(ApplicationContextException.class);
view.initApplicationContext();
}
@Test
public void contentDisposition() throws Exception {
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.render(getModel(), request, response);
assertEquals("Invalid content type", "inline", response.getHeader("Content-Disposition"));
}
@Test
public void overrideContentDisposition() throws Exception {
Properties headers = new Properties();
String cd = "attachment";
headers.setProperty("Content-Disposition", cd);
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.setHeaders(headers);
view.render(getModel(), request, response);
assertEquals("Invalid content type", cd, response.getHeader("Content-Disposition"));
}
@Test
public void setCustomHeaders() throws Exception {
Properties headers = new Properties();
String key = "foo";
String value = "bar";
headers.setProperty(key, value);
AbstractJasperReportsView view = getView(COMPILED_REPORT);
view.setHeaders(headers);
view.render(getModel(), request, response);
assertNotNull("Header not present", response.getHeader(key));
assertEquals("Invalid header value", value, response.getHeader(key));
}
@Test
public void withJdbcDataSource() throws Exception {
assumeTrue(canCompileReport);
AbstractJasperReportsView view = getView(UNCOMPILED_REPORT);
view.setJdbcDataSource(getMockJdbcDataSource());
Map<String, Object> model = getModel();
model.remove("dataSource");
// DataSource was not used as report DataSource
exception.expect(SQLException.class);
view.render(model, request, response);
}
@Test
public void withJdbcDataSourceInModel() throws Exception {
assumeTrue(canCompileReport);
AbstractJasperReportsView view = getView(UNCOMPILED_REPORT);
Map<String, Object> model = getModel();
model.remove("dataSource");
model.put("someKey", getMockJdbcDataSource());
// DataSource was not used as report DataSource
exception.expect(SQLException.class);
view.render(model, request, response);
}
@Test
public void jrDataSourceOverridesJdbcDataSource() throws Exception {
assumeTrue(canCompileReport);
AbstractJasperReportsView view = getView(UNCOMPILED_REPORT);
view.setJdbcDataSource(getMockJdbcDataSource());
view.render(getModel(), request, response);
}
@Test
public void withCharacterEncoding() throws Exception {
AbstractJasperReportsView view = getView(COMPILED_REPORT);
assumeTrue(view instanceof AbstractJasperReportsSingleFormatView
&& ((AbstractJasperReportsSingleFormatView) view).useWriter());
String characterEncoding = "UTF-8";
Map<Object, Object> parameters = new HashMap<>();
parameters.put(net.sf.jasperreports.engine.JRExporterParameter.CHARACTER_ENCODING, characterEncoding);
view.setExporterParameters(parameters);
view.convertExporterParameters();
view.render(getModel(), this.request, this.response);
assertEquals(characterEncoding, this.response.getCharacterEncoding());
}
protected AbstractJasperReportsView getView(String url) throws Exception {
AbstractJasperReportsView view = getViewImplementation();
view.setUrl(url);
StaticWebApplicationContext ac = new StaticWebApplicationContext();
ac.setServletContext(new MockServletContext());
ac.addMessage("page", Locale.GERMAN, "MeineSeite");
ac.refresh();
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, ac);
view.setApplicationContext(ac);
return view;
}
protected abstract AbstractJasperReportsView getViewImplementation();
protected abstract String getDesiredContentType();
private DataSource getMockJdbcDataSource() throws SQLException {
DataSource ds = mock(DataSource.class);
given(ds.getConnection()).willThrow(new SQLException());
return ds;
}
private class MockDataSourceProvider extends JRAbstractBeanDataSourceProvider {
public MockDataSourceProvider(Class<?> clazz) {
super(clazz);
}
@Override
public JRDataSource create(JasperReport jasperReport) throws JRException {
return new JRBeanCollectionDataSource(getData());
}
@Override
public void dispose(JRDataSource jrDataSource) throws JRException {
}
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
/**
* @author Rob Harrop
*/
public class ConfigurableJasperReportsViewWithStreamTests extends AbstractConfigurableJasperReportsViewTests {
@Override
@SuppressWarnings("deprecation")
protected AbstractJasperReportsView getViewImplementation() {
ConfigurableJasperReportsView view = new ConfigurableJasperReportsView();
view.setExporterClass(net.sf.jasperreports.engine.export.JRHtmlExporter.class);
view.setUseWriter(true);
view.setContentType("application/pdf");
return view;
}
@Override
protected String getDesiredContentType() {
return "application/pdf";
}
}

View File

@ -1,39 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import net.sf.jasperreports.engine.export.JRPdfExporter;
/**
* @author Rob Harrop
*/
public class ConfigurableJasperReportsViewWithWriterTests extends AbstractConfigurableJasperReportsViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
ConfigurableJasperReportsView view = new ConfigurableJasperReportsView();
view.setExporterClass(JRPdfExporter.class);
view.setUseWriter(false);
view.setContentType("text/html");
return view;
}
@Override
protected String getDesiredContentType() {
return "text/html";
}
}

View File

@ -1,129 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JasperPrint;
import org.junit.Test;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import static org.junit.Assert.*;
/**
* @author Rob Harrop
* @author Sam Brannen
*/
@SuppressWarnings("deprecation")
public class ExporterParameterTests extends AbstractJasperReportsTests {
@Test
public void parameterParsing() throws Exception {
Map<String, String> params = new HashMap<>();
params.put("net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI", "/foo/bar");
AbstractJasperReportsView view = new AbstractJasperReportsView() {
@Override
protected void renderReport(JasperPrint filledReport, Map<String, Object> model, HttpServletResponse response)
throws Exception {
assertEquals("Invalid number of exporter parameters", 1, getConvertedExporterParameters().size());
net.sf.jasperreports.engine.JRExporterParameter key = net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI;
Object value = getConvertedExporterParameters().get(key);
assertNotNull("Value not mapped to correct key", value);
assertEquals("Incorrect value for parameter", "/foo/bar", value);
}
};
view.setExporterParameters(params);
setViewProperties(view);
view.render(getModel(), request, response);
}
@Test(expected = IllegalArgumentException.class)
public void invalidClass() throws Exception {
Map<String, String> params = new HashMap<>();
params.put("foo.net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI", "/foo");
AbstractJasperReportsView view = new JasperReportsHtmlView();
setViewProperties(view);
view.setExporterParameters(params);
view.convertExporterParameters();
}
@Test(expected = IllegalArgumentException.class)
public void invalidField() {
Map<String, String> params = new HashMap<>();
params.put("net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI_FOO", "/foo");
AbstractJasperReportsView view = new JasperReportsHtmlView();
setViewProperties(view);
view.setExporterParameters(params);
view.convertExporterParameters();
}
@Test(expected = IllegalArgumentException.class)
public void invalidType() {
Map<String, String> params = new HashMap<>();
params.put("java.lang.Boolean.TRUE", "/foo");
AbstractJasperReportsView view = new JasperReportsHtmlView();
setViewProperties(view);
view.setExporterParameters(params);
view.convertExporterParameters();
}
@Test
public void typeConversion() {
Map<String, String> params = new HashMap<>();
params.put("net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN", "true");
AbstractJasperReportsView view = new JasperReportsHtmlView();
setViewProperties(view);
view.setExporterParameters(params);
view.convertExporterParameters();
Object value = view.getConvertedExporterParameters().get(
net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IS_USING_IMAGES_TO_ALIGN);
assertEquals(Boolean.TRUE, value);
}
private void setViewProperties(AbstractJasperReportsView view) {
view.setUrl("/org/springframework/ui/jasperreports/DataSourceReport.jasper");
StaticWebApplicationContext ac = new StaticWebApplicationContext();
ac.setServletContext(new MockServletContext());
ac.addMessage("page", Locale.GERMAN, "MeineSeite");
ac.refresh();
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, ac);
view.setApplicationContext(ac);
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.Locale;
import org.junit.Test;
import org.springframework.context.support.StaticApplicationContext;
import static org.junit.Assert.*;
/**
* @author Rob Harrop
*/
public class JasperReportViewResolverTests {
@Test
public void resolveView() throws Exception {
StaticApplicationContext ctx = new StaticApplicationContext();
String prefix = "org/springframework/ui/jasperreports/";
String suffix = ".jasper";
String viewName = "DataSourceReport";
JasperReportsViewResolver viewResolver = new JasperReportsViewResolver();
viewResolver.setViewClass(JasperReportsHtmlView.class);
viewResolver.setPrefix(prefix);
viewResolver.setSuffix(suffix);
viewResolver.setApplicationContext(ctx);
AbstractJasperReportsView view = (AbstractJasperReportsView) viewResolver.resolveViewName(viewName,
Locale.ENGLISH);
assertNotNull("View should not be null", view);
assertEquals("Incorrect URL", prefix + viewName + suffix, view.getUrl());
}
@Test
public void withViewNamesAndEndsWithPattern() throws Exception {
doViewNamesTest("DataSource*");
}
@Test
public void withViewNamesAndStartsWithPattern() throws Exception {
doViewNamesTest("*Report");
}
@Test
public void withViewNamesAndStatic() throws Exception {
doViewNamesTest("DataSourceReport");
}
private void doViewNamesTest(String... viewNames) throws Exception {
StaticApplicationContext ctx = new StaticApplicationContext();
String prefix = "org/springframework/ui/jasperreports/";
String suffix = ".jasper";
String viewName = "DataSourceReport";
JasperReportsViewResolver viewResolver = new JasperReportsViewResolver();
viewResolver.setViewClass(JasperReportsHtmlView.class);
viewResolver.setPrefix(prefix);
viewResolver.setSuffix(suffix);
viewResolver.setViewNames(viewNames);
viewResolver.setApplicationContext(ctx);
AbstractJasperReportsView view = (AbstractJasperReportsView) viewResolver.resolveViewName(viewName,
Locale.ENGLISH);
assertNotNull("View should not be null", view);
assertEquals("Incorrect URL", prefix + viewName + suffix, view.getUrl());
assertNull(viewResolver.resolveViewName("foo", Locale.ENGLISH));
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
/**
* @author Rob Harrop
*/
public class JasperReportsCsvViewTests extends AbstractJasperReportsViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
return new JasperReportsCsvView();
}
@Override
protected String getDesiredContentType() {
return "text/csv";
}
}

View File

@ -1,64 +0,0 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import org.junit.Test;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
import org.springframework.core.io.ClassPathResource;
import org.springframework.mock.web.test.MockServletContext;
import org.springframework.web.context.support.GenericWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import static org.junit.Assert.*;
/**
* @author Rob Harrop
*/
public class JasperReportsHtmlViewTests extends AbstractJasperReportsViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
return new JasperReportsHtmlView();
}
@Override
protected String getDesiredContentType() {
return "text/html";
}
@Test
@SuppressWarnings("deprecation")
public void configureExporterParametersWithEncodingFromPropertiesFile() throws Exception {
GenericWebApplicationContext ac = new GenericWebApplicationContext();
ac.setServletContext(new MockServletContext());
BeanDefinitionReader reader = new PropertiesBeanDefinitionReader(ac);
reader.loadBeanDefinitions(new ClassPathResource("view.properties", getClass()));
ac.refresh();
AbstractJasperReportsView view = (AbstractJasperReportsView) ac.getBean("report");
String encoding = (String) view.getConvertedExporterParameters().get(
net.sf.jasperreports.engine.export.JRHtmlExporterParameter.CHARACTER_ENCODING);
assertEquals("UTF-8", encoding);
request.setAttribute(DispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE, ac);
view.render(getModel(), request, response);
assertEquals("Response content type is incorrect", "text/html;charset=UTF-8", response.getContentType());
}
}

View File

@ -1,145 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JasperPrint;
import org.junit.Test;
import org.springframework.tests.Assume;
import org.springframework.tests.TestGroup;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
/**
* @author Rob Harrop
* @author Juergen Hoeller
* @author Sam Brannen
*/
public class JasperReportsMultiFormatViewTests extends AbstractJasperReportsViewTests {
@Override
protected void extendModel(Map<String, Object> model) {
model.put(getDiscriminatorKey(), "csv");
}
@Test
public void simpleHtmlRender() throws Exception {
Assume.group(TestGroup.CUSTOM_COMPILATION);
assumeTrue(canCompileReport);
AbstractJasperReportsView view = getView(UNCOMPILED_REPORT);
Map<String, Object> model = getBaseModel();
model.put(getDiscriminatorKey(), "html");
view.render(model, request, response);
assertEquals("Invalid content type", "text/html", response.getContentType());
}
@Test
@Override
public void overrideContentDisposition() throws Exception {
Assume.group(TestGroup.CUSTOM_COMPILATION);
assumeTrue(canCompileReport);
AbstractJasperReportsView view = getView(UNCOMPILED_REPORT);
Map<String, Object> model = getBaseModel();
model.put(getDiscriminatorKey(), "csv");
String headerValue = "inline; filename=foo.txt";
Properties mappings = new Properties();
mappings.put("csv", headerValue);
((JasperReportsMultiFormatView) view).setContentDispositionMappings(mappings);
view.render(model, request, response);
assertEquals("Invalid Content-Disposition header value", headerValue,
response.getHeader("Content-Disposition"));
}
@Test
public void exporterParametersAreCarriedAcross() throws Exception {
Assume.group(TestGroup.CUSTOM_COMPILATION);
assumeTrue(canCompileReport);
JasperReportsMultiFormatView view = (JasperReportsMultiFormatView) getView(UNCOMPILED_REPORT);
Map<String, Class<? extends AbstractJasperReportsView>> mappings =
new HashMap<>();
mappings.put("test", ExporterParameterTestView.class);
Map<String, String> exporterParameters = new HashMap<>();
// test view class performs the assertions - robh
exporterParameters.put(ExporterParameterTestView.TEST_PARAM, "foo");
view.setExporterParameters(exporterParameters);
view.setFormatMappings(mappings);
view.initApplicationContext();
Map<String, Object> model = getBaseModel();
model.put(getDiscriminatorKey(), "test");
view.render(model, request, response);
}
protected String getDiscriminatorKey() {
return "format";
}
@Override
protected AbstractJasperReportsView getViewImplementation() {
return new JasperReportsMultiFormatView();
}
@Override
protected String getDesiredContentType() {
return "text/csv";
}
private Map<String, Object> getBaseModel() {
Map<String, Object> model = new HashMap<>();
model.put("ReportTitle", "Foo");
model.put("dataSource", getData());
return model;
}
public static class ExporterParameterTestView extends AbstractJasperReportsView {
public static final String TEST_PARAM = "net.sf.jasperreports.engine.export.JRHtmlExporterParameter.IMAGES_URI";
@Override
protected void renderReport(JasperPrint filledReport, Map<String, Object> parameters, HttpServletResponse response) {
assertNotNull("Exporter parameters are null", getExporterParameters());
assertEquals("Incorrect number of exporter parameters", 1, getExporterParameters().size());
}
}
}

View File

@ -1,51 +0,0 @@
/*
* Copyright 2002-2016 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
import java.util.HashMap;
import java.util.Map;
/**
* @author Rob Harrop
* @author Juergen Hoeller
*/
public class JasperReportsMultiFormatViewWithCustomMappingsTests extends JasperReportsMultiFormatViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
JasperReportsMultiFormatView view = new JasperReportsMultiFormatView();
view.setFormatKey("fmt");
Map<String, Class<? extends AbstractJasperReportsView>> mappings =
new HashMap<>();
mappings.put("csv", JasperReportsCsvView.class);
mappings.put("comma-separated", JasperReportsCsvView.class);
mappings.put("html", JasperReportsHtmlView.class);
view.setFormatMappings(mappings);
return view;
}
@Override
protected String getDiscriminatorKey() {
return "fmt";
}
@Override
protected void extendModel(Map<String, Object> model) {
model.put(getDiscriminatorKey(), "comma-separated");
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
/**
* @author Rob Harrop
*/
public class JasperReportsPdfViewTests extends AbstractJasperReportsViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
return new JasperReportsPdfView();
}
@Override
protected String getDesiredContentType() {
return "application/pdf";
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
/**
* @author Rob Harrop
*/
public class JasperReportsXlsViewTests extends AbstractJasperReportsViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
return new JasperReportsXlsView();
}
@Override
protected String getDesiredContentType() {
return "application/vnd.ms-excel";
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright 2002-2015 the original author or authors.
*
* 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 org.springframework.web.servlet.view.jasperreports;
/**
* @author Juergen Hoeller
* @since 4.2
*/
public class JasperReportsXlsxViewTests extends AbstractJasperReportsViewTests {
@Override
protected AbstractJasperReportsView getViewImplementation() {
return new JasperReportsXlsxView();
}
@Override
protected String getDesiredContentType() {
return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
}

View File

@ -1 +0,0 @@
net.sf.jasperreports.awt.ignore.missing.font=true

View File

@ -1,185 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created using JasperAssistant (http://www.jasperassistant.com) -->
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="DataSourceReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="ReportTitle" class="java.lang.String">
</parameter>
<parameter name="DataFile" class="java.lang.String">
</parameter>
<field name="id" class="java.lang.Integer">
</field>
<field name="name" class="java.lang.String">
</field>
<field name="street" class="java.lang.String">
</field>
<field name="city" class="java.lang.String">
</field>
<variable name="CityNumber" class="java.lang.Integer" resetType="Group" resetGroup="CityGroup" calculation="System">
<initialValueExpression><![CDATA[($V{CityNumber} != null)?(new Integer($V{CityNumber}.intValue() + 1)):(new Integer(1))]]></initialValueExpression>
</variable>
<group name="CityGroup" minHeightToStartNewPage="60">
<groupExpression><![CDATA[$F{city}]]></groupExpression>
<groupHeader>
<band height="20">
<rectangle>
<reportElement x="0" y="4" width="515" height="15" forecolor="#c0c0c0" backcolor="#c0c0c0"/>
<graphicElement/>
</rectangle>
<textField>
<reportElement mode="Opaque" x="0" y="4" width="515" height="15" backcolor="#c0c0c0"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{CityNumber}) + ". " + String.valueOf($F{city})]]></textFieldExpression>
</textField>
<line>
<reportElement x="0" y="19" width="515" height="1"/>
<graphicElement/>
</line>
</band>
</groupHeader>
<groupFooter>
<band height="20">
<line>
<reportElement x="0" y="-1" width="515" height="1"/>
<graphicElement/>
</line>
<staticText>
<reportElement x="400" y="1" width="60" height="15"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Count :]]></text>
</staticText>
<textField>
<reportElement x="460" y="1" width="30" height="15"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{CityGroup_COUNT}]]></textFieldExpression>
</textField>
</band>
</groupFooter>
</group>
<title>
<band height="70">
<line>
<reportElement x="0" y="0" width="515" height="1"/>
<graphicElement/>
</line>
<textField isBlankWhenNull="true">
<reportElement x="0" y="10" width="515" height="30"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Normal" size="22"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{ReportTitle}]]></textFieldExpression>
</textField>
<textField isBlankWhenNull="true">
<reportElement x="0" y="40" width="515" height="20"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Normal" size="14"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$P{DataFile}]]></textFieldExpression>
</textField>
</band>
</title>
<pageHeader>
<band height="20">
<rectangle>
<reportElement x="0" y="5" width="515" height="15" forecolor="#333333" backcolor="#333333"/>
<graphicElement/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="5" width="55" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[ID]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="55" y="5" width="205" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="260" y="5" width="255" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Street]]></text>
</staticText>
</band>
</pageHeader>
<detail>
<band height="20">
<textField>
<reportElement x="0" y="4" width="50" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="55" y="4" width="200" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="260" y="4" width="255" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{street}]]></textFieldExpression>
</textField>
<line>
<reportElement positionType="Float" x="0" y="19" width="515" height="1" forecolor="#808080"/>
<graphicElement/>
</line>
</band>
</detail>
<pageFooter>
<band height="40">
<line>
<reportElement x="0" y="10" width="515" height="1"/>
<graphicElement/>
</line>
<textField>
<reportElement x="200" y="20" width="80" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA[$R{page} + " " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="280" y="20" width="75" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
</textField>
</band>
</pageFooter>
<lastPageFooter>
<band height="60">
<textField>
<reportElement x="0" y="10" width="515" height="15"/>
<textElement textAlignment="Center"/>
<textFieldExpression class="java.lang.String"><![CDATA["There were " +
String.valueOf($V{REPORT_COUNT}) +
" address records on this report."]]></textFieldExpression>
</textField>
<line>
<reportElement x="0" y="30" width="515" height="1"/>
<graphicElement/>
</line>
<textField>
<reportElement x="200" y="40" width="80" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA[$R{page} + " " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="280" y="40" width="75" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
</textField>
</band>
</lastPageFooter>
</jasperReport>

View File

@ -1,227 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created using JasperAssistant (http://www.jasperassistant.com) -->
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="ProductReport" columnCount="2" pageWidth="325" pageHeight="842" columnWidth="160" columnSpacing="5" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="8" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="8" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="8" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="City" class="java.lang.String"/>
<field name="id" class="java.lang.Integer">
</field>
<field name="name" class="java.lang.String">
</field>
<field name="quantity" class="java.lang.Float">
</field>
<field name="price" class="java.lang.Float">
</field>
<variable name="QuantityProductSum" class="java.lang.Float" resetType="Group" resetGroup="ProductGroup" calculation="Sum">
<variableExpression><![CDATA[$F{quantity}]]></variableExpression>
</variable>
<variable name="PriceProductSum" class="java.lang.Float" resetType="Group" resetGroup="ProductGroup" calculation="Sum">
<variableExpression><![CDATA[$F{price}]]></variableExpression>
</variable>
<variable name="QuantitySum" class="java.lang.Float" calculation="Sum">
<variableExpression><![CDATA[$F{quantity}]]></variableExpression>
</variable>
<variable name="PriceSum" class="java.lang.Float" calculation="Sum">
<variableExpression><![CDATA[$F{price}]]></variableExpression>
</variable>
<variable name="ProductCount" class="java.lang.Integer" resetType="Group" resetGroup="ProductGroup" calculation="System">
<initialValueExpression><![CDATA[($V{ProductCount} != null)?(new Integer($V{ProductCount}.intValue() + 1)):(new Integer(1))]]></initialValueExpression>
</variable>
<group name="ProductGroup">
<groupExpression><![CDATA[$F{id}]]></groupExpression>
<groupHeader>
<band height="14">
<textField>
<reportElement x="0" y="2" width="15" height="10"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Integer"><![CDATA[$F{id}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true">
<reportElement positionType="Float" x="20" y="2" width="80" height="10"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{name}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true" evaluationTime="Group" evaluationGroup="ProductGroup" pattern="#0">
<reportElement positionType="Float" x="105" y="2" width="20" height="10"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{QuantityProductSum}]]></textFieldExpression>
</textField>
<textField isStretchWithOverflow="true" evaluationTime="Group" evaluationGroup="ProductGroup" pattern="#0.00">
<reportElement positionType="Float" x="130" y="2" width="30" height="10"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{PriceProductSum}]]></textFieldExpression>
</textField>
</band>
</groupHeader>
<groupFooter>
<band>
</band>
</groupFooter>
</group>
<title>
<band height="14">
<staticText>
<reportElement x="0" y="2" width="60" height="10"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Title]]></text>
</staticText>
<textField>
<reportElement x="0" y="2" width="325" height="10"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["Products ordered by people in " + $P{City}]]></textFieldExpression>
</textField>
</band>
</title>
<pageHeader>
<band height="14">
<rectangle>
<reportElement mode="Transparent" x="0" y="2" width="325" height="10" forecolor="#808000"/>
<graphicElement pen="Thin"/>
</rectangle>
<staticText>
<reportElement x="0" y="2" width="60" height="10" forecolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Page Header]]></text>
</staticText>
</band>
</pageHeader>
<columnHeader>
<band height="14">
<rectangle>
<reportElement x="0" y="2" width="160" height="10" forecolor="#ffff99" backcolor="#ffff99"/>
<graphicElement/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="2" width="20" height="10" backcolor="#ffff99"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[ID]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="20" y="2" width="85" height="10" backcolor="#ffff99"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Name]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="105" y="2" width="20" height="10" backcolor="#ffff99"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Qty]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="125" y="2" width="35" height="10" backcolor="#ffff99"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Price]]></text>
</staticText>
</band>
</columnHeader>
<columnFooter>
<band height="14">
<line>
<reportElement x="0" y="1" width="160" height="1"/>
<graphicElement pen="Thin"/>
</line>
<staticText>
<reportElement x="0" y="2" width="60" height="10"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Column Footer]]></text>
</staticText>
<staticText>
<reportElement x="70" y="2" width="30" height="10"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Total :]]></text>
</staticText>
<textField pattern="#0">
<reportElement x="105" y="2" width="20" height="10"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{QuantitySum}]]></textFieldExpression>
</textField>
<textField pattern="#0.00">
<reportElement x="130" y="2" width="30" height="10"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Float"><![CDATA[$V{PriceSum}]]></textFieldExpression>
</textField>
</band>
</columnFooter>
<pageFooter>
<band height="14">
<rectangle>
<reportElement mode="Transparent" x="0" y="2" width="325" height="10" forecolor="#808000"/>
<graphicElement pen="Thin"/>
</rectangle>
<staticText>
<reportElement x="0" y="2" width="60" height="10" forecolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Page Footer]]></text>
</staticText>
<textField>
<reportElement x="150" y="2" width="100" height="10" forecolor="#808000"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Italic"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of "]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="250" y="2" width="50" height="10" forecolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{PAGE_NUMBER}]]></textFieldExpression>
</textField>
</band>
</pageFooter>
<summary>
<band height="14">
<rectangle>
<reportElement x="0" y="2" width="325" height="10" forecolor="#808000" backcolor="#808000"/>
<graphicElement pen="Thin"/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="2" width="230" height="10" backcolor="#808000"/>
<textElement>
<font reportFont="Arial_Italic"/>
</textElement>
<text><![CDATA[Summary]]></text>
</staticText>
<staticText>
<reportElement mode="Opaque" x="230" y="2" width="55" height="10" backcolor="#808000"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[Count :]]></text>
</staticText>
<textField pattern="#0">
<reportElement mode="Opaque" x="285" y="2" width="40" height="10" backcolor="#808000"/>
<textElement textAlignment="Right">
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.Integer"><![CDATA[$V{ProductCount}]]></textFieldExpression>
</textField>
</band>
</summary>
</jasperReport>

View File

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created using JasperAssistant (http://www.jasperassistant.com) -->
<!DOCTYPE jasperReport PUBLIC "-//JasperReports//DTD Report Design//EN" "http://jasperreports.sourceforge.net/dtds/jasperreport.dtd">
<jasperReport name="MasterReport" pageWidth="595" pageHeight="842" columnWidth="515" leftMargin="40" rightMargin="40" topMargin="50" bottomMargin="50">
<reportFont name="Arial_Normal" isDefault="true" fontName="Arial" size="12" isBold="false" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Bold" isDefault="false" fontName="Arial" size="12" isBold="true" isItalic="false" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Bold" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<reportFont name="Arial_Italic" isDefault="false" fontName="Arial" size="12" isBold="false" isItalic="true" isUnderline="false" isStrikeThrough="false" pdfFontName="Helvetica-Oblique" pdfEncoding="Cp1252" isPdfEmbedded="false"/>
<parameter name="ProductsSubReport" class="net.sf.jasperreports.engine.JasperReport"/>
<parameter name="SubReportData" class="net.sf.jasperreports.engine.JRDataSource"/>
<field name="city" class="java.lang.String">
</field>
<title>
<band height="50">
<line>
<reportElement x="0" y="0" width="515" height="1"/>
<graphicElement/>
</line>
<staticText>
<reportElement x="0" y="10" width="515" height="30"/>
<textElement textAlignment="Center">
<font reportFont="Arial_Normal" size="22"/>
</textElement>
<text><![CDATA[Master Report]]></text>
</staticText>
</band>
</title>
<pageHeader>
<band height="21">
<rectangle>
<reportElement x="0" y="5" width="515" height="15" backcolor="#333333"/>
<graphicElement pen="None"/>
</rectangle>
<staticText>
<reportElement mode="Opaque" x="0" y="5" width="515" height="15" forecolor="#ffffff" backcolor="#333333"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[City List]]></text>
</staticText>
<line>
<reportElement x="0" y="20" width="515" height="1"/>
<graphicElement/>
</line>
</band>
</pageHeader>
<detail>
<band height="50">
<textField>
<reportElement x="5" y="5" width="100" height="15" isPrintWhenDetailOverflows="true"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<textFieldExpression class="java.lang.String"><![CDATA[$F{city}]]></textFieldExpression>
</textField>
<staticText>
<reportElement isPrintRepeatedValues="false" x="110" y="5" width="100" height="15" isPrintWhenDetailOverflows="true"/>
<textElement>
<font reportFont="Arial_Bold"/>
</textElement>
<text><![CDATA[(continued)]]></text>
</staticText>
<line>
<reportElement x="0" y="20" width="515" height="1" isPrintWhenDetailOverflows="true"/>
<graphicElement/>
</line>
<subreport>
<reportElement isPrintRepeatedValues="false" x="5" y="25" width="325" height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/>
<subreportParameter name="City">
<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression>
<subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{ProductsSubReport}]]></subreportExpression>
</subreport>
<!--<subreport>
<reportElement positionType="Float" x="335" y="25" width="175" height="20" isRemoveLineWhenBlank="true" backcolor="#99ccff"/>
<subreportParameter name="City">
<subreportParameterExpression><![CDATA[$F{City}]]></subreportParameterExpression>
</subreportParameter>
<connectionExpression><![CDATA[$P{REPORT_CONNECTION}]]></connectionExpression>
<subreportExpression class="java.lang.String"><![CDATA["AddressReport.jasper"]]></subreportExpression>
</subreport> -->
</band>
</detail>
<pageFooter>
<band height="40">
<line>
<reportElement x="0" y="10" width="515" height="1"/>
<graphicElement/>
</line>
<textField>
<reportElement x="200" y="20" width="80" height="15"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.lang.String"><![CDATA["Page " + String.valueOf($V{PAGE_NUMBER}) + " of"]]></textFieldExpression>
</textField>
<textField evaluationTime="Report">
<reportElement x="280" y="20" width="75" height="15"/>
<textElement/>
<textFieldExpression class="java.lang.String"><![CDATA[" " + String.valueOf($V{PAGE_NUMBER})]]></textFieldExpression>
</textField>
</band>
</pageFooter>
</jasperReport>

View File

@ -1,4 +0,0 @@
report.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView
report.url=/org/springframework/ui/jasperreports/DataSourceReport.jasper
report.exporterParameters[net.sf.jasperreports.engine.export.JRHtmlExporterParameter.CHARACTER_ENCODING]=UTF-8
report.exporterParameters[net.sf.jasperreports.engine.JRExporterParameter.PAGE_INDEX]=0

View File

@ -144,9 +144,8 @@ loading, and the transparent creation of contexts by, for example, a Servlet con
The Context module also supports Java EE features such as EJB, JMX, and basic remoting.
The `ApplicationContext` interface is the focal point of the Context module.
`spring-context-support` provides support for integrating common third-party libraries
into a Spring application context for caching (EhCache, Guava, JCache), mailing
(JavaMail), scheduling (CommonJ, Quartz) and template engines (FreeMarker, JasperReports).
into a Spring application context, in particular for caching (EhCache, JCache) and
scheduling (CommonJ, Quartz).
The `spring-expression` module provides a powerful <<expressions,__Expression
Language__>> for querying and manipulating an object graph at runtime. It is an extension

View File

@ -2037,358 +2037,6 @@ document should appear listing each of the words in the model map.
[[view-jasper-reports]]
== JasperReports
JasperReports ( http://jasperreports.sourceforge.net[]) is a powerful open-source
reporting engine that supports the creation of report designs using an easily understood
XML file format. JasperReports is capable of rendering reports in four different
formats: CSV, Excel, HTML and PDF.
[[view-jasper-reports-dependencies]]
=== Dependencies
Your application will need to include the latest release of JasperReports, which at the
time of writing was 0.6.1. JasperReports itself depends on the following projects:
* BeanShell
* Commons BeanUtils
* Commons Collections
* Commons Digester
* Commons Logging
* iText
* POI
JasperReports also requires a JAXP compliant XML parser.
[[view-jasper-reports-configuration]]
=== Configuration
To configure JasperReports views in your Spring container configuration you need to
define a `ViewResolver` to map view names to the appropriate view class depending on
which format you want your report rendered in.
[[view-jasper-reports-configuration-resolver]]
==== Configuring the ViewResolver
Typically, you will use the `ResourceBundleViewResolver` to map view names to view
classes and files in a properties file.
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<property name="basename" value="views"/>
</bean>
----
Here we've configured an instance of the `ResourceBundleViewResolver` class that will
look for view mappings in the resource bundle with base name `views`. (The content of
this file is described in the next section.)
[[view-jasper-reports-configuration-views]]
==== Configuring the Views
The Spring Framework contains five different `View` implementations for JasperReports,
four of which correspond to one of the four output formats supported by JasperReports,
and one that allows for the format to be determined at runtime:
[[view-jasper-reports-configuration-views-classes]]
.JasperReports View classes
|===
| Class Name| Render Format
| `JasperReportsCsvView`
| CSV
| `JasperReportsHtmlView`
| HTML
| `JasperReportsPdfView`
| PDF
| `JasperReportsXlsView`
| Microsoft Excel
| `JasperReportsMultiFormatView`
| The view is <<view-jasper-reports-configuration-multiformat-view,decided upon at
runtime>>
|===
Mapping one of these classes to a view name and a report file is a matter of adding the
appropriate entries in the resource bundle configured in the previous section as shown
here:
[literal]
[subs="verbatim,quotes"]
----
simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper
----
Here you can see that the view with name `simpleReport` is mapped to the
`JasperReportsPdfView` class, causing the output of this report to be rendered in PDF
format. The `url` property of the view is set to the location of the underlying report
file.
[[view-jasper-reports-configuration-report-files]]
==== About Report Files
JasperReports has two distinct types of report file: the design file, which has a
`.jrxml` extension, and the compiled report file, which has a `.jasper` extension.
Typically, you use the JasperReports Ant task to compile your `.jrxml` design file into
a `.jasper` file before deploying it into your application. With the Spring Framework
you can map either of these files to your report file and the framework will take care
of compiling the `.jrxml` file on the fly for you. You should note that after a `.jrxml`
file is compiled by the Spring Framework, the compiled report is cached for the lifetime
of the application. Thus, to make changes to the file you will need to restart your
application.
[[view-jasper-reports-configuration-multiformat-view]]
==== Using JasperReportsMultiFormatView
The `JasperReportsMultiFormatView` allows for the report format to be specified at
runtime. The actual rendering of the report is delegated to one of the other
JasperReports view classes - the `JasperReportsMultiFormatView` class simply adds a
wrapper layer that allows for the exact implementation to be specified at runtime.
The `JasperReportsMultiFormatView` class introduces two concepts: the format key and the
discriminator key. The `JasperReportsMultiFormatView` class uses the mapping key to look
up the actual view implementation class, and it uses the format key to lookup up the
mapping key. From a coding perspective you add an entry to your model with the format
key as the key and the mapping key as the value, for example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
public ModelAndView handleSimpleReportMulti(HttpServletRequest request,
HttpServletResponse response) throws Exception {
String uri = request.getRequestURI();
String format = uri.substring(uri.lastIndexOf(".") + 1);
Map model = getModel();
model.put("format", format);
return new ModelAndView("simpleReportMulti", model);
}
----
In this example, the mapping key is determined from the extension of the request URI and
is added to the model under the default format key: `format`. If you wish to use a
different format key then you can configure this using the `formatKey` property of the
`JasperReportsMultiFormatView` class.
By default the following mapping key mappings are configured in
`JasperReportsMultiFormatView`:
[[view-jasper-reports-configuration-multiformat-view-mappings]]
.JasperReportsMultiFormatView Default Mapping Key Mappings
|===
| Mapping Key| View Class
| csv
| `JasperReportsCsvView`
| html
| `JasperReportsHtmlView`
| pdf
| `JasperReportsPdfView`
| xls
| `JasperReportsXlsView`
|===
So in the example above a request to URI /foo/myReport.pdf would be mapped to the
`JasperReportsPdfView` class. You can override the mapping key to view class mappings
using the `formatMappings` property of `JasperReportsMultiFormatView`.
[[view-jasper-reports-model]]
=== Populating the ModelAndView
In order to render your report correctly in the format you have chosen, you must supply
Spring with all of the data needed to populate your report. For JasperReports this means
you must pass in all report parameters along with the report datasource. Report
parameters are simple name/value pairs and can be added to the `Map` for your model as
you would add any name/value pair.
When adding the datasource to the model you have two approaches to choose from. The
first approach is to add an instance of `JRDataSource` or a `Collection` type to the
model `Map` under any arbitrary key. Spring will then locate this object in the model
and treat it as the report datasource. For example, you may populate your model like so:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
private Map getModel() {
Map model = new HashMap();
Collection beanData = getBeanData();
model.put("myBeanData", beanData);
return model;
}
----
The second approach is to add the instance of `JRDataSource` or `Collection` under a
specific key and then configure this key using the `reportDataKey` property of the view
class. In both cases Spring will wrap instances of `Collection` in a
`JRBeanCollectionDataSource` instance. For example:
[source,java,indent=0]
[subs="verbatim,quotes"]
----
private Map getModel() {
Map model = new HashMap();
Collection beanData = getBeanData();
Collection someData = getSomeData();
model.put("myBeanData", beanData);
model.put("someData", someData);
return model;
}
----
Here you can see that two `Collection` instances are being added to the model. To ensure
that the correct one is used, we simply modify our view configuration as appropriate:
[literal]
[subs="verbatim,quotes"]
----
simpleReport.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper
simpleReport.reportDataKey=myBeanData
----
Be aware that when using the first approach, Spring will use the first instance of
`JRDataSource` or `Collection` that it encounters. If you need to place multiple
instances of `JRDataSource` or `Collection` into the model you need to use the second
approach.
[[view-jasper-reports-subreports]]
=== Working with Sub-Reports
JasperReports provides support for embedded sub-reports within your master report files.
There are a wide variety of mechanisms for including sub-reports in your report files.
The easiest way is to hard code the report path and the SQL query for the sub report
into your design files. The drawback of this approach is obvious: the values are
hard-coded into your report files reducing reusability and making it harder to modify
and update report designs. To overcome this you can configure sub-reports declaratively,
and you can include additional data for these sub-reports directly from your controllers.
[[view-jasper-reports-subreports-config-reports]]
==== Configuring Sub-Report Files
To control which sub-report files are included in a master report using Spring, your
report file must be configured to accept sub-reports from an external source. To do this
you declare a parameter in your report file like so:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<parameter name="ProductsSubReport" class="net.sf.jasperreports.engine.JasperReport"/>
----
Then, you define your sub-report to use this sub-report parameter:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<subreport>
<reportElement isPrintRepeatedValues="false" x="5" y="25" width="325"
height="20" isRemoveLineWhenBlank="true" backcolor="#ffcc99"/>
<subreportParameter name="City">
<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression>
<subreportExpression class="net.sf.jasperreports.engine.JasperReport">
<![CDATA[$P{ProductsSubReport}]]></subreportExpression>
</subreport>
----
This defines a master report file that expects the sub-report to be passed in as an
instance of `net.sf.jasperreports.engine.JasperReports` under the parameter
`ProductsSubReport`. When configuring your Jasper view class, you can instruct Spring to
load a report file and pass it into the JasperReports engine as a sub-report using the
`subReportUrls` property:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<property name="subReportUrls">
<map>
<entry key="ProductsSubReport" value="/WEB-INF/reports/subReportChild.jrxml"/>
</map>
</property>
----
Here, the key of the `Map` corresponds to the name of the sub-report parameter in the
report design file, and the entry is the URL of the report file. Spring will load this
report file, compiling it if necessary, and pass it into the JasperReports engine under
the given key.
[[view-jasper-reports-subreports-config-datasources]]
==== Configuring Sub-Report Data Sources
This step is entirely optional when using Spring to configure your sub-reports. If you
wish, you can still configure the data source for your sub-reports using static queries.
However, if you want Spring to convert data returned in your `ModelAndView` into
instances of `JRDataSource` then you need to specify which of the parameters in your
`ModelAndView` Spring should convert. To do this, configure the list of parameter names
using the `subReportDataKeys` property of your chosen view class:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<property name="subReportDataKeys" value="SubReportData"/>
----
Here, the key you supply __must__ correspond to both the key used in your `ModelAndView`
and the key used in your report design file.
[[view-jasper-reports-exporter-parameters]]
=== Configuring Exporter Parameters
If you have special requirements for exporter configuration -- perhaps you want a
specific page size for your PDF report -- you can configure these exporter parameters
declaratively in your Spring configuration file using the `exporterParameters` property
of the view class. The `exporterParameters` property is typed as a `Map`. In your
configuration the key of an entry should be the fully-qualified name of a static field
that contains the exporter parameter definition, and the value of an entry should be the
value you want to assign to the parameter. An example of this is shown below:
[source,xml,indent=0]
[subs="verbatim,quotes"]
----
<bean id="htmlReport" class="org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView">
<property name="url" value="/WEB-INF/reports/simpleReport.jrxml"/>
<property name="exporterParameters">
<map>
<entry key="net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER">
<value>Footer by Spring!
&lt;/td&gt;&lt;td width="50%"&gt;&amp;nbsp; &lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;
</value>
</entry>
</map>
</property>
</bean>
----
Here you can see that the `JasperReportsHtmlView` is configured with an exporter
parameter for `net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER`
which will output a footer in the resulting HTML.
[[view-feeds]]
== Feed Views
Both `AbstractAtomFeedView` and `AbstractRssFeedView` inherit from the base class