This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/struts.git
The following commit(s) were added to refs/heads/main by this push:
new f7a23c962 WW-5734 test(jasperreports7): run the plugin end-to-end on
an embedded Tomcat (#1924)
f7a23c962 is described below
commit f7a23c96233c776375aa3d71e515fd9d0dba177f
Author: Lukasz Lenart <[email protected]>
AuthorDate: Sat Sep 12 15:36:54 2026 +0200
WW-5734 test(jasperreports7): run the plugin end-to-end on an embedded
Tomcat (#1924)
The plugin had never been exercised outside Spring's mock response, which
is how WW-5731, WW-5732 and WW-5733 went unnoticed since 7.1.0. The
showcase cannot host an example because JasperReports is LGPL and the
showcase WAR ships in the release assembly.
JasperReport7TomcatTest boots Struts on tomcat-embed-core (test scope),
compiles the existing simple.jrxml into the webapp's docBase and asserts
that a real HTTP request returns a non-empty body of the right content
type for each of the six bundled formats. Against the providers as they
were before WW-5733 all six assertions fail with an empty body.
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
---
plugins/jasperreports7/pom.xml | 7 +
.../tomcat/JasperReport7TomcatTest.java | 148 +++++++++++++++++++++
.../views/jasperreports7/tomcat/ReportAction.java | 47 +++++++
.../src/test/resources/struts-tomcat.xml | 36 +++++
4 files changed, 238 insertions(+)
diff --git a/plugins/jasperreports7/pom.xml b/plugins/jasperreports7/pom.xml
index cb0467305..00017e256 100644
--- a/plugins/jasperreports7/pom.xml
+++ b/plugins/jasperreports7/pom.xml
@@ -34,6 +34,7 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jasperreports7.version>7.0.7</jasperreports7.version>
+ <tomcat-embed.version>10.1.55</tomcat-embed.version>
</properties>
<dependencies>
@@ -78,5 +79,11 @@
<artifactId>easymock</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ <version>${tomcat-embed.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/JasperReport7TomcatTest.java
b/plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/JasperReport7TomcatTest.java
new file mode 100644
index 000000000..bf1579981
--- /dev/null
+++
b/plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/JasperReport7TomcatTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.struts2.views.jasperreports7.tomcat;
+
+import net.sf.jasperreports.engine.JasperCompileManager;
+import org.apache.catalina.Context;
+import org.apache.catalina.servlets.DefaultServlet;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter;
+import org.apache.struts2.util.ClassLoaderUtil;
+import org.apache.tomcat.util.descriptor.web.FilterDef;
+import org.apache.tomcat.util.descriptor.web.FilterMap;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.net.URI;
+import java.net.URL;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Runs the plugin on a real servlet container: the mock response used by the
other tests
+ * keeps accepting writes after the stream is closed, a container does not.
+ */
+public class JasperReport7TomcatTest {
+
+ private static Tomcat tomcat;
+ private static String baseUrl;
+
+ @BeforeClass
+ public static void startTomcat() throws Exception {
+ Path baseDir =
Files.createTempDirectory(Files.createDirectories(Path.of("target")),
"tomcat").toAbsolutePath();
+ Path docBase = Files.createDirectories(baseDir.resolve("webapp"));
+ Path reports = Files.createDirectories(docBase.resolve("reports"));
+ URL jrxml =
ClassLoaderUtil.getResource("org/apache/struts2/views/jasperreports7/simple.jrxml",
JasperReport7TomcatTest.class);
+
JasperCompileManager.compileReportToFile(Path.of(jrxml.toURI()).toString(),
reports.resolve("simple.jasper").toString());
+
+ tomcat = new Tomcat();
+ tomcat.setBaseDir(baseDir.toString());
+ tomcat.setPort(0);
+ tomcat.getConnector().setProperty("address", "127.0.0.1");
+
+ Context context = tomcat.addContext("", docBase.toString());
+ Tomcat.addServlet(context, "default", new DefaultServlet());
+ context.addServletMappingDecoded("/", "default");
+ FilterDef filterDef = new FilterDef();
+ filterDef.setFilterName("struts");
+
filterDef.setFilterClass(StrutsPrepareAndExecuteFilter.class.getName());
+ filterDef.addInitParameter("config",
"struts-default.xml,struts-plugin.xml,struts-tomcat.xml");
+ context.addFilterDef(filterDef);
+ FilterMap filterMap = new FilterMap();
+ filterMap.setFilterName("struts");
+ filterMap.addURLPattern("/*");
+ context.addFilterMap(filterMap);
+
+ tomcat.start();
+ baseUrl = "http://127.0.0.1:" + tomcat.getConnector().getLocalPort();
+ }
+
+ @AfterClass
+ public static void stopTomcat() throws Exception {
+ if (tomcat != null) {
+ tomcat.stop();
+ tomcat.destroy();
+ }
+ }
+
+ @Test
+ public void exportsCsv() throws Exception {
+ HttpResponse<byte[]> response = report("csv");
+
+ assertThat(response.statusCode()).isEqualTo(200);
+
assertThat(response.headers().firstValue("Content-Type")).hasValueSatisfying(type
-> assertThat(type).startsWith("text/csv"));
+ assertThat(new String(response.body())).contains("Tomcat
Report").contains("Hello Foo Bar!");
+ }
+
+ @Test
+ public void exportsPdf() throws Exception {
+ HttpResponse<byte[]> response = report("pdf");
+
+ assertThat(response.statusCode()).isEqualTo(200);
+
assertThat(response.headers().firstValue("Content-Type")).hasValueSatisfying(type
-> assertThat(type).startsWith("application/pdf"));
+ assertThat(response.body()).startsWith("%PDF".getBytes());
+ }
+
+ @Test
+ public void exportsHtml() throws Exception {
+ HttpResponse<byte[]> response = report("html");
+
+ assertThat(response.statusCode()).isEqualTo(200);
+
assertThat(response.headers().firstValue("Content-Type")).hasValueSatisfying(type
-> assertThat(type).startsWith("text/html"));
+ assertThat(new String(response.body())).contains("Tomcat
Report").contains("Hello Foo Bar!");
+ }
+
+ @Test
+ public void exportsXml() throws Exception {
+ HttpResponse<byte[]> response = report("xml");
+
+ assertThat(response.statusCode()).isEqualTo(200);
+
assertThat(response.headers().firstValue("Content-Type")).hasValueSatisfying(type
-> assertThat(type).startsWith("text/xml"));
+ assertThat(new String(response.body())).contains("Tomcat
Report").contains("Hello Foo Bar!");
+ }
+
+ @Test
+ public void exportsRtf() throws Exception {
+ HttpResponse<byte[]> response = report("rtf");
+
+ assertThat(response.statusCode()).isEqualTo(200);
+
assertThat(response.headers().firstValue("Content-Type")).hasValueSatisfying(type
-> assertThat(type).startsWith("application/rtf"));
+ assertThat(new
String(response.body())).startsWith("{\\rtf").contains("Hello Foo Bar!");
+ }
+
+ @Test
+ public void exportsXlsx() throws Exception {
+ HttpResponse<byte[]> response = report("xlsx");
+
+ assertThat(response.statusCode()).isEqualTo(200);
+
assertThat(response.headers().firstValue("Content-Type")).hasValueSatisfying(type
->
assertThat(type).startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
+ assertThat(response.body()).startsWith("PK".getBytes());
+ }
+
+ private static HttpResponse<byte[]> report(String format) throws Exception
{
+ HttpRequest request = HttpRequest.newBuilder(URI.create(baseUrl +
"/report.action?format=" + format)).build();
+ return HttpClient.newHttpClient().send(request,
HttpResponse.BodyHandlers.ofByteArray());
+ }
+}
diff --git
a/plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/ReportAction.java
b/plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/ReportAction.java
new file mode 100644
index 000000000..2543436f2
--- /dev/null
+++
b/plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/ReportAction.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.apache.struts2.views.jasperreports7.tomcat;
+
+import org.apache.struts2.ActionSupport;
+import org.apache.struts2.interceptor.parameter.StrutsParameter;
+
+import java.util.List;
+import java.util.Map;
+
+public class ReportAction extends ActionSupport {
+
+ private String format;
+
+ public List<Map<String, String>> getPeople() {
+ return List.of(Map.of("firstName", "Foo", "lastName", "Bar"));
+ }
+
+ public Map<String, Object> getReportParameters() {
+ return Map.of("title", "Tomcat");
+ }
+
+ public String getFormat() {
+ return format;
+ }
+
+ @StrutsParameter
+ public void setFormat(String format) {
+ this.format = format;
+ }
+}
diff --git a/plugins/jasperreports7/src/test/resources/struts-tomcat.xml
b/plugins/jasperreports7/src/test/resources/struts-tomcat.xml
new file mode 100644
index 000000000..be465eada
--- /dev/null
+++ b/plugins/jasperreports7/src/test/resources/struts-tomcat.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+-->
+<!DOCTYPE struts PUBLIC
+ "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN"
+ "https://struts.apache.org/dtds/struts-6.0.dtd">
+<struts>
+ <package name="reports" extends="jasperreports7-default">
+ <action name="report"
class="org.apache.struts2.views.jasperreports7.tomcat.ReportAction">
+ <result type="jasperReport7">
+ <param name="location">/reports/simple.jasper</param>
+ <param name="dataSource">people</param>
+ <param name="reportParameters">reportParameters</param>
+ <param name="format">${format}</param>
+ </result>
+ </action>
+ </package>
+</struts>