jasperreports
jasperreports copied to clipboard
Template source hardcoded as string for style collecting
In the JRFillReportTemplate::loadTemplate
the different kind of inputs are handled properly, so I can easily use my own service to return an intercepted input stream instead of a simple string path, something like this:
<template><![CDATA[$P{MY_SERVICE}.intercept("my-template.jrtx")]]></template>
And everything works, until a template includes another template.
In the JRBaseFiller::collectIncludedTemplates
function, a simple string is used to locate the included template. And because it's a string, the loadTemplate
tries to locate the report template instead of evaluating the expression and using the InputStream
provided by the service.
The use case
Added a "global variable" support for our reports by intercepting the input stream - parsing the input as an XML, renaming, replacing some things and then returning the modified XML document as an InputStream
.
With this addition, it became easy to write something like this:
<style backcolor="{{ my_global_variable }}"/>
It works for jrxml
reports and first level jrtx
templates, however templates included by other templates break things.
All resources including jrxml and jrtx files are loaded by JasperReports from a virtual repository. Repository implementations can be configured as extensions to the library and it would allow you to intercept resources when they are loaded and process them before delivering them. Repository implementations are an ordered list of net.sf.jasperreports.repo.RepositoryService objects that can be added to the configuration as JasperReports extensions.
For example, in a custom RepositoryService implementation that you configure to be the first to be called in the list, you could establish a convention in which all resource URIs that start with a path prefix such as /MYPROCESS/path/to/resource would be intercepted by your custom repository implementation and processed the way you need. This custom repository implementation would read the original resource/file from its actual repository location by delegating the operation to the other repository implementations and making sure it skips itself on the subsequent call. If the resource is loaded successfully through the delegated call, they are then processed to have the variables replaced and all before you return it to the caller.
You can see how to implement repository interface by looking at the ones that are included in the library itself. You would need to register your extension using a jasperreports_extension.properties file. This is briefly explained in the JasperReports Ultimate Guide.
I hope this helps. Teodor
Hi,
Just want to mention that in the 6.20.0 release, we have introduced support for conditional styles in external style templates, which might help in what you wanted to achieve with the global variable.
I hope this helps. Teodor