From 7e28be30c9f1022c1e75c65a3af46d94d53a9260 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Sat, 12 Sep 2026 14:37:47 +0200 Subject: [PATCH] WW-5734 test(jasperreports7): run the plugin end-to-end on an embedded Tomcat 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) --- plugins/jasperreports7/pom.xml | 7 + .../tomcat/JasperReport7TomcatTest.java | 148 ++++++++++++++++++ .../jasperreports7/tomcat/ReportAction.java | 47 ++++++ .../src/test/resources/struts-tomcat.xml | 36 +++++ 4 files changed, 238 insertions(+) create mode 100644 plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/JasperReport7TomcatTest.java create mode 100644 plugins/jasperreports7/src/test/java/org/apache/struts2/views/jasperreports7/tomcat/ReportAction.java create mode 100644 plugins/jasperreports7/src/test/resources/struts-tomcat.xml diff --git a/plugins/jasperreports7/pom.xml b/plugins/jasperreports7/pom.xml index cb0467305a..00017e256b 100644 --- a/plugins/jasperreports7/pom.xml +++ b/plugins/jasperreports7/pom.xml @@ -34,6 +34,7 @@ UTF-8 7.0.7 + 10.1.55 @@ -78,5 +79,11 @@ easymock test + + org.apache.tomcat.embed + tomcat-embed-core + ${tomcat-embed.version} + test + 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 0000000000..bf15799816 --- /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 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 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 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 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 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 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 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 0000000000..2543436f22 --- /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> getPeople() { + return List.of(Map.of("firstName", "Foo", "lastName", "Bar")); + } + + public Map 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 0000000000..be465eadac --- /dev/null +++ b/plugins/jasperreports7/src/test/resources/struts-tomcat.xml @@ -0,0 +1,36 @@ + + + + + + + + /reports/simple.jasper + people + reportParameters + ${format} + + + +