Learn how to add custom code to the HTML head and body elements within Pull Reports™ Ad Hoc reports.
Three Export Report REST API formats, html
,
htmltree
,
and map
return complete HTML documents to be displayed in a web browser. By default, the HTML is undecorated
such that the Pull Reports™ export content fills the entire <body>
element.
Pull Reports™ provides two techniques to decorate the exported HTML with additional HTML content: Servlet includes and SiteMesh.
Configure the inclusion of html
or jsp
content via
export.report.include
-prefixed configuration properties.
The value of these properties is a resource path within the deployed WAR to be include via
RequestDispatcher#include
into one of three places within the HTML DOM:
before the close of the <head>
element
after the start of the <body>
element
before the close of the <body>
element
The export.report.include
-prefixed configuration properties may be specified multiple
times within pullreports.properties
to specify or override behavior for specific formats, HTTP
response codes, <catalog>
s, or <report>
s.
export.report.include
property name structureThe structure of export.report.include
-prefixed configuration property names is:
export.report.include[.html|.htmltree|.map].(head.end|body.start|body.end)[.400|.500][.catalogId][.reportId]
Where (...)
demarcated terms are required and [...]
demarcated terms are optional.
The |
character separates the permitted values for a particular term.
When resolving an inclusion value for a particular report, Pull Reports™ follows these rules to determine precedence:
Properties specified for a particular report via [.catalogId][.reportId]
take
precedence over values specified for a particular catalog via [.catalogId]
which take
precedence over values specified without reference to a catalog or report.
Properties specified for either the html
, htmltree
,
or map
format via [.html|.htmltree|.map]
take precedence over values specified without a format.
In the case of a 400 or 500 HTTP response, properties specified with a
[.400|.500]
status code take precedence over values specified without status.
Simple example:
Here is a simple example which includes a navigation.html
header at the top of all html
, htmltree
, and map
export formats:
export.report.include.body.start=/WEB-INF/content/navigation.html
To override the property for a all <report>
s in <catalog id='my-catalog'>
,
add a second property suffixed with the catalog id:
export.report.include.body.start=/WEB-INF/content/navigation.html export.report.include.body.start.my-catalog=/WEB-INF/content/my-catalog-navigation.html
export.report.include
property name terms[.html|.htmltree|.map]
Specify either the html
, htmltree
, or map
term to apply the property
to the html
, htmltree
, or map
format
respectively. If not specified,
the value of the property applies to all formats.
(head.end|body.start|body.end)
(Required)Specify the inclusion location with the HTML document via one of the three following terms.
head.end: before the close of the <head>
element
body.start: after the start of the <body>
element
body.end: before the close of the <body>
element
[.400|.500]
Specify either the 400
or 500
term to apply the property
to the respective HTML response code. If not specified,
the value of the property applies to all response codes.
[.catalogId][.reportId]
Specify a <catalog>
id
and, optionally, <report>
id
to limit the property to a specific catalog or report.
export.report.include
property examplesThe following example pullreports.properties
contains several
permutations of the export.report.include
-prefixed properties with
explanatory comments.
# Configures default body.start and body.end includes for all responses # of 500 (error) status export.report.include.body.start.500=/WEB-INF/error-header.html export.report.include.body.end.500=/WEB-INF/error-footer.html # Configures default body.start and body.end includes for all responses # of 400 (bad request / validation error) status export.report.include.body.start.400=/WEB-INF/validation-error-header.html export.report.include.body.end.400=/WEB-INF/validation-error-footer.html # Configures default head.end include for all export results of format type # map. The included file might contain CSS or JavaScript code to customize # the map export. export.report.include.map.head.end=/WEB-INF/map-head-include.jsp # Configures default body.start and body.end includes for all responses. # These includes could contain common header navigation and common footer # elements respectively. export.report.include.body.start=/WEB-INF/page-header.jsp export.report.include.body.end=/WEB-INF/page-footer.jsp # Override the includes for <catalog id='my-catalog'>. export.report.include.body.start.my-catalog=/WEB-INF/my-catalog-page-header.jsp export.report.include.body.end.my-catalog=/WEB-INF/my-catalog-page-footer.jsp # Override the 400 head include for the html format for <report id='my-report'> # within <catalog id='my-catalog'>. export.report.include.html.head.end.400.my-catalog.my-report=\ /WEB-INF/validation-error-html-head-include-my-report.html
Follow these steps to decorate the exported HTML with the SiteMesh framework. The following steps assume SiteMesh version 2.4.
Make the SiteMesh JAR available to the web application into which Pull Reports™ is installed
by placing the JAR within the WEB-INF/lib
directory.
If using Gradle for dependency management, add the following dependency to include SiteMesh:
runtime 'opensymphony:sitemesh:2.4.2'
Install the SiteMesh filter in web.xml
.
<filter> <filter-name>sitemesh</filter-name> <filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class> </filter> <filter-mapping> <filter-name>sitemesh</filter-name> <url-pattern>/pullreports/catalog/*</url-pattern> </filter-mapping>
Install the sitemesh.xml
file within the
WEB-INF
directory. Configure a ParameterDecoratorMapper
within the <decorator-mappers>
list. The value
attribute must be set to format
to correspond to the Export Report REST API
format
parameter.
<?xml version="1.0" encoding="UTF-8"?> <sitemesh> <property name="decorators-file" value="/WEB-INF/decorators.xml" /> <excludes file="${decorators-file}"/> <page-parsers> <parser content-type="text/html" class="com.opensymphony.module.sitemesh.parser.HTMLPageParser" /> </page-parsers> <decorator-mappers> <mapper class="com.opensymphony.module.sitemesh.mapper.ParameterDecoratorMapper"> <param name="decorator.parameter" value="format" /> </mapper> <mapper class="com.opensymphony.module.sitemesh.mapper.ConfigDecoratorMapper"> <param name="config" value="${decorators-file}" /> </mapper> </decorator-mappers> </sitemesh>
Install the decorators.xml
file within the
WEB-INF
directory. Configure two <decorators>
with the names html
, htmltree
, and map
respectively.
<?xml version="1.0" encoding="UTF-8"?> <decorators defaultdir="/WEB-INF/decorators"> <decorator name="html" page="my-html-decorator.jsp"></decorator> <decorator name="map" page="my-map-decorator.jsp"></decorator> <decorator name="htmltree" page="my-html-decorator.jsp"></decorator> </decorators>
Place the decorator JSP files referenced within the previous step
into the WEB-INF/decorators
directory. Then use the SiteMesh
custom tags within these JSP files to apply the decoration.
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <!DOCTYPE html> <html> <head> <title>Demonstration HTML format decorator</title> <decorator:head /> <script> // Custom javascript here. </script> </head> <body> <header><!-- Custom header here --></header> <decorator:body /> <footer><!-- Custom footer here --></footer> </body> </html>
This decorator demonstrates the use of the
mapConfig
JavaScript variable to customize the Leaflet Mapper.
<%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> <!DOCTYPE html> <html> <head> <title>Demonstration Map format decorator</title> <decorator:head /> <script> var baseLayers = []; baseLayers['ESRI World Topo'] = L.tileLayer('http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}', { attribution: 'Tiles © Esri — Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community' ,maxZoom:18 }); baseLayers['Open Street Map'] = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors' ,maxZoom: 18 }); function initializeMap(map,geojsonLayer){ L.control.layers(baseLayers, {'Student residences':geojsonLayer}).addTo(map); } var mapConfig = { options: { layers:[baseLayers['Open Street Map']] } ,initCallback:initializeMap ,geoJsonOptions: { // Customize the Leaflet popup. onEachFeature:function(feature,layer){ layer.bindPopup(function(){ return '<h3>' + feature.properties['Some Property'] + '</h3>'; }); } // Customize the GeoJSON style ,style:{"color": "#FA8072", "weight": 5, "opacity": 0.8 } } }; </script> </head> <body> <header><!-- Custom header here --></header> <decorator:body /> <footer><!-- Custom footer here --></footer> </body> </html>
After performing these steps, a request to
[/context]/pullreports/catalog/my-catalog/report/my-report/export?format=html
will be decorated with the my-html-decorator.jsp
decorator and
a request to
[/context]/pullreports/catalog/my-catalog/report/my-report/export?format=map
will be decorated with the my-map-decorator.jsp
decorator.
For more information about configuring SiteMesh, see the SiteMesh documentation.