-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* set up a report that includes images from inside the application, from the static resources of the application, and from an external source * added a unit test to validate that the HTML export includes `img` tags with not-empty `src` attributes * added endpoints for PDF and XLSX output * added an application-wide HTML file resource handler to deal with storing the images in a temp folder * setup and tear down the temp folder and any files in it with the application lifecycle * added a REST endpoint to serve images from the temp directory for HTML reports Signed-off-by:Nathan Erwin <[email protected]>
- Loading branch information
Showing
11 changed files
with
378 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,3 +64,4 @@ pom.xml.releaseBackup | |
pom.xml.versionsBackup | ||
release.properties | ||
ObjectStore | ||
/integration-tests/nbproject/ |
31 changes: 31 additions & 0 deletions
31
integration-tests/src/main/jasperreports/ImagesReport.jrxml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<!-- Created with Jaspersoft Studio version 7.0.0.final using JasperReports Library version 7.0.0 --> | ||
<jasperReport name="ImagesReport" language="java" pageWidth="612" pageHeight="792" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="7ed005ff-df0a-4cda-8daa-ffa0721c8e4f"> | ||
<parameter name="QUARKUS_URL" class="java.lang.String"> | ||
<defaultValueExpression><![CDATA["http://localhost:8080"]]></defaultValueExpression> | ||
</parameter> | ||
<title height="530" splitType="Stretch"> | ||
<element kind="staticText" uuid="465ce796-bd9a-432d-b0fe-70672e692e72" x="0" y="0" width="572" height="30" hTextAlign="Center" vTextAlign="Middle"> | ||
<text><![CDATA[Images]]></text> | ||
</element> | ||
<element kind="staticText" uuid="fa677fd0-4085-4b99-9dab-2262569dfb15" x="0" y="40" width="280" height="50" hTextAlign="Center" vTextAlign="Middle"> | ||
<text><![CDATA[Relative to report]]></text> | ||
</element> | ||
<element kind="image" uuid="63ad371f-62a0-4324-bae6-4088e6b359bd" x="280" y="40" width="50" height="50" hImageAlign="Center" vImageAlign="Middle"> | ||
<expression><![CDATA["images/jasperreports.svg"]]></expression> | ||
</element> | ||
<element kind="staticText" uuid="ae851b5b-8475-43bb-9d82-9e2d020c7d41" x="0" y="100" width="280" height="50" hTextAlign="Center" vTextAlign="Middle"> | ||
<text><![CDATA[URL to localhost, gif]]></text> | ||
</element> | ||
<element kind="image" uuid="72c0a16f-5b16-4a1d-9132-00387f80b179" x="280" y="100" width="50" height="50" hImageAlign="Center" vImageAlign="Middle"> | ||
<expression><![CDATA[$P{QUARKUS_URL} + "/jasperreports.gif"]]></expression> | ||
</element> | ||
<element kind="staticText" uuid="f8eb2a65-ed08-4dd4-9d93-da923703a386" x="0" y="160" width="280" height="50" hTextAlign="Center" vTextAlign="Middle"> | ||
<text><![CDATA[URL to remote server]]></text> | ||
</element> | ||
<element kind="image" uuid="183403c6-1aef-410a-b6f1-5767241f28bf" x="280" y="160" width="50" height="50" linkType="Reference" linkTarget="Blank" hImageAlign="Center" vImageAlign="Middle"> | ||
<expression><![CDATA["https://raw.githubusercontent.com/quarkiverse/quarkus-jasperreports/refs/heads/main/docs/modules/ROOT/assets/images/jasperreports.svg"]]></expression> | ||
<hyperlinkReferenceExpression><![CDATA["https://raw.githubusercontent.com/quarkiverse/quarkus-jasperreports/refs/heads/main/docs/modules/ROOT/assets/images/jasperreports.svg"]]></hyperlinkReferenceExpression> | ||
<hyperlinkTooltipExpression><![CDATA["Image from GitHub"]]></hyperlinkTooltipExpression> | ||
</element> | ||
</title> | ||
</jasperReport> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
integration-tests/src/main/java/io/quarkiverse/jasperreports/it/Application.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package io.quarkiverse.jasperreports.it; | ||
|
||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
|
||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.enterprise.event.Observes; | ||
|
||
import org.jboss.logging.Logger; | ||
|
||
import io.quarkus.runtime.ShutdownEvent; | ||
import io.quarkus.runtime.StartupEvent; | ||
import net.sf.jasperreports.engine.export.FileHtmlResourceHandler; | ||
|
||
@ApplicationScoped | ||
public class Application { | ||
|
||
private static final Logger LOG = Logger.getLogger(Application.class); | ||
|
||
private FileHtmlResourceHandler imageHandler; | ||
|
||
private Path tempFolder; | ||
|
||
void onStart(@Observes StartupEvent evt) throws IOException { | ||
tempFolder = Files.createTempDirectory("jasperreports"); | ||
imageHandler = new FileHtmlResourceHandler(tempFolder.toFile(), "/images/{0}"); | ||
} | ||
|
||
void onStop(@Observes ShutdownEvent evt) throws IOException { | ||
if (null != tempFolder) { | ||
Files.walk(tempFolder).forEach((p) -> { | ||
try { | ||
Files.delete(p); | ||
} catch (IOException ex) { | ||
LOG.warn(ex.getMessage()); | ||
} | ||
}); | ||
|
||
if (Files.exists(tempFolder)) { | ||
Files.delete(tempFolder); | ||
} | ||
} | ||
} | ||
|
||
public FileHtmlResourceHandler getImageHandler() { | ||
return imageHandler; | ||
} | ||
|
||
public Path getTempFolder() { | ||
return tempFolder; | ||
} | ||
|
||
} |
44 changes: 44 additions & 0 deletions
44
integration-tests/src/main/java/io/quarkiverse/jasperreports/it/ImageResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package io.quarkiverse.jasperreports.it; | ||
|
||
import static jakarta.ws.rs.core.Response.Status.NOT_FOUND; | ||
|
||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.nio.file.Files; | ||
|
||
import jakarta.enterprise.context.RequestScoped; | ||
import jakarta.inject.Inject; | ||
import jakarta.ws.rs.GET; | ||
import jakarta.ws.rs.Path; | ||
import jakarta.ws.rs.PathParam; | ||
import jakarta.ws.rs.core.Response; | ||
|
||
import org.jboss.logging.Logger; | ||
|
||
@Path("images") | ||
@RequestScoped | ||
public class ImageResource { | ||
|
||
private static final Logger LOG = Logger.getLogger(ImageResource.class); | ||
|
||
@Inject | ||
Application app; | ||
|
||
@GET | ||
@Path("{fileName}") | ||
public Response get(@PathParam("fileName") final String fileName) throws IOException { | ||
final var path = java.nio.file.Path.of(app.getTempFolder().toString(), fileName); | ||
|
||
if (Files.exists(path) && Files.isRegularFile(path) && Files.isReadable(path)) { | ||
final String contentType = Files.probeContentType(path); | ||
|
||
LOG.debugf("Loading file %s of type %s", path.toString(), contentType); | ||
|
||
try (final InputStream is = Files.newInputStream(path)) { | ||
return Response.ok(is.readAllBytes(), contentType).build(); | ||
} | ||
} | ||
|
||
return Response.status(NOT_FOUND).build(); | ||
} | ||
} |
117 changes: 117 additions & 0 deletions
117
...ation-tests/src/main/java/io/quarkiverse/jasperreports/it/JasperReportsImageResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package io.quarkiverse.jasperreports.it; | ||
|
||
import static io.quarkiverse.jasperreports.it.ExtendedMediaType.APPLICATION_PDF; | ||
import static io.quarkiverse.jasperreports.it.ExtendedMediaType.APPLICATION_XLSX; | ||
import static jakarta.ws.rs.core.MediaType.TEXT_HTML; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.util.HashMap; | ||
import java.util.Locale; | ||
import java.util.Map; | ||
|
||
import jakarta.enterprise.context.ApplicationScoped; | ||
import jakarta.inject.Inject; | ||
import jakarta.ws.rs.GET; | ||
import jakarta.ws.rs.Path; | ||
import jakarta.ws.rs.core.Context; | ||
import jakarta.ws.rs.core.HttpHeaders; | ||
import jakarta.ws.rs.core.Response; | ||
import jakarta.ws.rs.core.UriInfo; | ||
|
||
import org.eclipse.microprofile.openapi.annotations.media.Content; | ||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse; | ||
|
||
import io.quarkiverse.jasperreports.repository.ReadOnlyStreamingService; | ||
import io.quarkus.logging.Log; | ||
import net.sf.jasperreports.engine.JREmptyDataSource; | ||
import net.sf.jasperreports.engine.JRException; | ||
import net.sf.jasperreports.engine.JRParameter; | ||
import net.sf.jasperreports.engine.JasperFillManager; | ||
import net.sf.jasperreports.engine.JasperPrint; | ||
import net.sf.jasperreports.engine.SimpleReportContext; | ||
|
||
@Path("jasper/image") | ||
@ApplicationScoped | ||
public class JasperReportsImageResource extends AbstractJasperResource { | ||
|
||
private static final String TEST_REPORT_NAME = "ImagesReport.jasper"; | ||
|
||
@Context | ||
UriInfo uriInfo; | ||
|
||
@Inject | ||
ReadOnlyStreamingService repo; | ||
|
||
@APIResponse(responseCode = "200", description = "Fetch an HTML report with images", content = @Content(mediaType = TEXT_HTML)) | ||
@GET | ||
@Path("html") | ||
public Response getHtml() throws JRException, IOException { | ||
final SimpleReportContext reportContext = new SimpleReportContext(); | ||
final Map<String, Object> params = new HashMap<>(); | ||
params.put(JRParameter.REPORT_LOCALE, Locale.US); | ||
params.put(JRParameter.REPORT_CONTEXT, reportContext); | ||
params.put("QUARKUS_URL", uriInfo.getBaseUri().toString()); | ||
|
||
final long start = System.currentTimeMillis(); | ||
final JasperPrint jasperPrint = JasperFillManager.getInstance(repo.getContext()).fillFromRepo(TEST_REPORT_NAME, params, | ||
new JREmptyDataSource()); | ||
|
||
final Response.ResponseBuilder response = Response.ok(); | ||
ByteArrayOutputStream outputStream = exportHtml(jasperPrint, reportContext); | ||
Log.infof("HTML creation time : %s", (System.currentTimeMillis() - start)); | ||
response.entity(outputStream.toByteArray()); | ||
response.type(TEXT_HTML); | ||
|
||
return response.build(); | ||
} | ||
|
||
@APIResponse(responseCode = "200", description = "Fetch a PDF report with images", content = @Content(mediaType = APPLICATION_PDF)) | ||
@GET | ||
@Path("pdf") | ||
public Response getPdf() throws JRException { | ||
final SimpleReportContext reportContext = new SimpleReportContext(); | ||
final Map<String, Object> params = new HashMap<>(); | ||
params.put(JRParameter.REPORT_LOCALE, Locale.US); | ||
params.put(JRParameter.REPORT_CONTEXT, reportContext); | ||
params.put("QUARKUS_URL", uriInfo.getBaseUri().toString()); | ||
|
||
final long start = System.currentTimeMillis(); | ||
final JasperPrint jasperPrint = JasperFillManager.getInstance(repo.getContext()).fillFromRepo(TEST_REPORT_NAME, params, | ||
new JREmptyDataSource()); | ||
|
||
final Response.ResponseBuilder response = Response.ok(); | ||
ByteArrayOutputStream outputStream = exportPdf(jasperPrint); | ||
Log.infof("PDF creation time : %s", (System.currentTimeMillis() - start)); | ||
response.entity(outputStream.toByteArray()); | ||
response.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=jasper.pdf"); | ||
response.type(APPLICATION_PDF); | ||
|
||
return response.build(); | ||
} | ||
|
||
@APIResponse(responseCode = "200", description = "Fetch an XLSX report with images", content = @Content(mediaType = APPLICATION_XLSX)) | ||
@GET | ||
@Path("xlsx") | ||
public Response getXlsx() throws JRException { | ||
final SimpleReportContext reportContext = new SimpleReportContext(); | ||
final Map<String, Object> params = new HashMap<>(); | ||
params.put(JRParameter.REPORT_LOCALE, Locale.US); | ||
params.put(JRParameter.REPORT_CONTEXT, reportContext); | ||
params.put("QUARKUS_URL", uriInfo.getBaseUri().toString()); | ||
|
||
final long start = System.currentTimeMillis(); | ||
final JasperPrint jasperPrint = JasperFillManager.getInstance(repo.getContext()).fillFromRepo(TEST_REPORT_NAME, params, | ||
new JREmptyDataSource()); | ||
|
||
final Response.ResponseBuilder response = Response.ok(); | ||
ByteArrayOutputStream outputStream = exportXlsx(jasperPrint); | ||
Log.infof("XLSX creation time : %s", (System.currentTimeMillis() - start)); | ||
response.entity(outputStream.toByteArray()); | ||
response.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=jasper.xlsx"); | ||
response.type(APPLICATION_XLSX); | ||
|
||
return response.build(); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.