docs.intersystems.com
Using Zen Reports
Configuring Zen Reports for PDF Output
[Home] [Back] [Next]
InterSystems: The power behind what matters   
Search:    

Configuring Zen Reports for PDF Output
When you load a Zen report class into a browser with a request to view the output as PDF, Caché uses Java to call out to a third-party PDF rendering tool. The rendering tool applies the XSLT stylesheet to the XML data and transforms the XML into XSL-FO. Finally, the tool transforms the XSL-FO into PDF. For information on how to run a Zen report from the browser, see the section Invoking Zen Reports from a Web Browser.
The Caché installation provides a version of Apache FOP that Zen reports uses as the PDF rendering engine. You can also use another rendering engine, such as XEP PDF from RenderX, or download and install FOP from Apache.
Using the Built-in PDF Rendering Engine
The PDF rendering process works only if you have performed the required configuration steps. This section discusses configuration for the built-in FOP. For information on configuring alternate PDF renderers, see the section Using Other Rendering Engines.”
  1. If you do not already have a Java Virtual Machine (JVM) and Java Developers Kit (JDK) version 1.7 or later installed, download and install these tools on your system. In order for Caché to find Java, you need to define the JAVA_HOME environment variable and set it to the location where you have installed Java. JAVA_HOME is described in the Java documentation.
  2. You must ensure that user privileges are set correctly, even if your Zen report does not use security features. To run a report with PDF output, the user must be logged into a user account that has the %System_CallOut:USE privilege.
    If the Zen report is part of a Zen application, and you have enabled Unauthenticated access using the Allowed Authentication Methods field on the Web Applications page (System Administration > Security > Applications > Web Applications), the UnknownUser account must have the %System_CallOut:USE privilege.
    To configure Zen application settings of all types, see the Zen Application Configuration section in the “Zen Applications” chapter of Developing Zen Applications. For information about privileges such as %System_CallOut:USE, see the Assets and Resources chapter in the Caché Security Administration Guide.
    You can use the Zen reports class-parameter RESOURCE to impose additional privilege requirements.
  3. If you are printing PDF directly via jPDFPrint, you need to define an environment variable that tells Zen reports the location of the jPDFPrint JAR file. On Windows, this variable is in the System Environment variables. For example, set the environment variable JPDFPRINT_HOME to c:\Program Files\jPDFPrint
  4. You can create custom configuration files for the built-in FOP as described in materials on the Apache FOP Web site:
    If you want the Caché callout to FOP to use a custom configuration file, you can set the global ^%SYS("zenreport","transformerconfig") to the path of the configuration file. Configuration files are important for adding fonts to FOP. You must first create font metrics, and then register them with FOP. The process is described on the Apache FOP Web site.
    If you modify the FOP configuration file fop.xconf, then a Caché install does not copy over it. The FOP configuration file that comes with your Caché distribution is named fop.xconf_dist. If your fop.xconf file becomes corrupted for any reason (such as running RenderX, which truncates the file if the parameter USEINSTALLEDFOP is not set to zero), you can revert to the file as distributed with Caché by copying fop.xconf_dist to fop.xconf.
Note:
PDF rendering can consume a lot of memory. If you run into trouble, you might want to modify the FOP.bat or XEP.bat file to increase the amount of memory available to the Java Virtual Machine. The respective products provide documentation that explains how to do this.
Using Other Rendering Engines
A version of Apache FOP is installed with Caché. If you chose to use another PDF rendering tool, you must perform the following additional configuration steps.
  1. Install the XSL-FO to PDF rendering tool. Two of the available options are:
  2. Configure Zen reports with the full pathname of the command file that invokes the rendering tool. For XEP or FOP on Windows or UNIX®, once you have installed the tool as instructed in Step 1, this command file is present on your system under the installation directory for the tool, for example C:\fop-0.95\fop.bat for Windows or /fop-0.95/fop on UNIX®.
    You can configure Zen reports from the Management Portal Zen Report Settings page (System Administration > Configuration > Zen Report Settings) as follows:
    Alternatively, you can enter commands to set the corresponding Caché global at the Terminal prompt.
    To set the configuration file, set ^%SYS("zenreport","transformerconfig") to the path of the configuration file.
  3. The default behavior of the Zen reports system is to use the installed FOP to render reports if you have not set an alternative renderer on the Management Portal Zen Report Settings page (System Administration > Configuration > Zen Reports > Settings). If you want Zen reports to generate an error if you have not specified a renderer, set the class-parameter USEINSTALLEDFOP to 0 from its default value of 1 in each Zen report, or in the Zen report's Application. To apply this change to all Zen reports at once, you can set the parameter in the default Application for Zen reports: %ZEN.Report.defaultApplication.
  4. For FOP version 0.94 or earlier
    If you are using FOP version 0.94 or earlier, you must set a flag to tell Zen reports that an older FOP version is the rendering tool. To do this, enter the following commands at the Terminal prompt:
     ZN "%SYS"
     SET ^%SYS("zenreport","oldfop")=1 
    Even with this measure in place, the following elements do not support percentage widths when FOP 0.94 or earlier is the rendering engine: <block> <caption> <img> and <p>. For alternate syntax that you can use to specify widths for these elements, or for any other Zen report display elements, see Dimension and Size in the chapter “Formatting Zen Report Pages”
  5. For rendering engines other than XEP or FOP
    Usually the choice of PDF rendering engine is XEP or FOP, each of which supports the same set of command line options for the transformation from XSL-FO to PDF. If you have completed the previous steps in this list, no further configuration work is necessary to make the XEP or FOP engines work with Zen reports.
    If you want Zen reports to use a PDF rendering engine other than XEP or FOP, this engine might require different command line options when it is invoked. In this case, you must specify the correct option syntax using class parameters in your Zen report class.
    The following table lists each relevant class parameter and describes the value it must have to use Zen reports with various PDF rendering engines. If the engine you are using is not listed here, check its documentation to verify which values you should use for these parameters.
    Class Parameter This Command Line Option Identifies the... Zen Reports Default Value XEP Value FOP Value Antenna House XSL Formatter Value
    PDFSWITCH PDF output file -pdf -pdf -pdf -o
    XMLSWITCH XSL-FO data file -xml -xml -xml -d
    XSLSWITCH XSL-FO stylesheet file -xsl -xsl -xsl -s
Splitting and Merging PDF Output
The PDF output for a very large report may exceed the memory restrictions of the FOP rendering engine. In this case, you can split the report into several smaller sections. Each section is written to disk as a separate temporary file, and merged into a single PDF file once the entire report has been processed. You need to set the following parameters in your report:
Computed page counts may not be valid in the merged report because there is no logic in the merge process to recalculate or change page counting. Any <masterreference> elements defined for specialized formatting of first or last pages are applied to each split section independently. Also be aware that elements that are not contained within a repeating element, such as final aggregates, may not appear in the final report.
Each of the parameters described previously has a corresponding property that you can also use to split and merge reports. The following example illustrates setting these properties when using GenerateReport to split and merge a report at the Caché terminal.
 zn "SAMPLES"
 do ##class(ZENDemo.Home).CreateDemoData() 
 s rpt1=##class(ZENApp.MyReport).%New()
 s rpt1.RepeatingElement="SalesRep"
 s rpt1.CountRepeatingElement=5
 s rpt1.SplitAndMerge=1
 s rpt1.Month=1
 s Status=rpt1.GenerateReport("c:\temp\MyReport1.pdf",0)
 d $System.Status.DisplayError(Status)
 w $System.Status.DisplayError(Status)
You can also set these parameters in the URL of the report by appending a $ in front of the symbol name: $SPLITANDMERGE, $REPEATINGELEMENT and $COUNTREPEAINGELEMENT.
The following sample URI illustrates passing these parameters in the URL. It contains a line break for typesetting purposes only; a correct URI is all on one line.
http://localhost:57772/csp//samples/ZENApp.MyReport.cls
?$MODE=pdf&$SPLITANDMERGE=1&$REPEATINGELEMENT=SalesRep
&$COUNTREPEATINGELEMENT=5
You can also use SPLITANDMERGE to generate a report as several PDF files. You would use this approach in a situation such as a billing application where you need to generate an individual PDF file for each customer bill from a large master XML file. You must set the three parameters described previously, and in addition, you must set the property SplitOnly to true. The default value is false. When SplitOnly is true, the PDF files are generated and written to disk, but they are not merged at the end. The names of the individual PDF files are returned in the property %SplitReturnedPDFs. There may be situations, such as debugging, in which you want to specify the directory and filename of the generated PDF files. The property SplitDir specifies the directory, and SplitRootName specifies the root name for the generated files, to which a sequential integer is appended for each file.
The HotJVM Render Server
Zen reports provides HotJVM Render Server capability to improve PDF rendering performance. The HotJVM Render Server is a Java Virtual Machine process which runs in the background and renders Zen reports as PDF files. By running as a background process, HotJVM eliminates the overhead of starting the Java Virtual Machine, and allows faster PDF rendering.
The Management Portal Render Servers page (System Administration > Configuration > Zen Reports > Render Servers) lists currently configured Render Servers. When Caché is first installed, there are no Render Servers configured. Because the Render Server consumes system memory, you should not configure and run a Render Server unless you need the improved rendering performance. If you have configured a Render Server, it starts automatically when you try to generate a report using the Render Server port.
Creating a HotJVM Render Server
The New Render Server button opens the New Zen Report Render Server page, which lets you configure a new Render Server. The first three fields are required, the remaining fields are optional.
For additional information on Initial Queue Size, Memory Threshold, and Threshold Polling Period (ms) see Memory Management for the HotJVM Render Server.
If you configure a Render Server to use RenderX XEP, additional fields appear on the configuration page:
RenderX can consume memory as it runs, so a cleaning operation needs to be performed periodically. Cleaning also consumes resources, so fields are provided to let you set the parameters that determine when cleaning takes place. The need for cleaning is determined by the number of files RenderX has processed. Use the field Num. Files Before Clean (XEP) to set this number. The value set in How Often To Clean (XEP) determines how often the Render Server checks whether RenderX has reached the file limit.
Once you have saved your changes, use the Cancel button to return to the Render Servers page, where you see that the new Render Server has been added to the list.
Using a HotJVM Render Server
The Manage button, which is located to the right of each listing on the Render Servers page (System Administration > Configuration > Zen Reports > Render Servers), lets you edit values and perform additional tasks:
In your Zen report you can set the RENDERSERVER class parameter to the port the Render Server is listening on. Then load the page with the mode set to PDF. You can also set RENDERSERVER class parameter for an entire Zen Application. Another alternative is to pass the port number in the URL using the reserved keyword $RENDERSERVER. You can also use this keyword to run a report on the server from the command line to generate a report into a user defined output file like the sample outlined below:
 zn "SAMPLES"
 set rpt1=##class(ZENApp.MyReport).%New()
 set rpt1.Month=1
 set Status=rpt1.GenerateReport("c:\temp\MyReport.pdf",2,0,57777)
 do $System.Status.DisplayError(Status)
The fourth parameter to GenerateReport gives the port of the HotJVM rendering server.
The Zen report property RenderTimeOut controls the length of time the report waits for the Render Server before timing out. A positive integer specifies the number of seconds to wait before timing out. A value of 0 means timeout immediately, and a value of –1 means never timeout. You can also pass the timeout interval in the URL using $RENDERTIMEOUT. The default value is null ("" in Caché), which means never timeout.
Communicating with the HotJVM Render Server
The class %ZEN.Report.Ping provides the ping method that you can use to communicate with the HotJVM Render Server.
In addition to the port and server type, ping returns the maximum memory available, the committed memory, and the amount of memory used. The Render Server attempts to use the Java tenured generation pool to get information about memory and return this information to ping. If the Render Server cannot find the Java tenured generation pool, it returns a blank string ("") for the value of maximum memory and used memory.
The ping method also returns the runtime name in the form pid@hostname. You can use $PIECE to process the string and get the process id.
The following example shows how to use ping:
 set Status=##class(%ZEN.Report.Ping).ping("1234",30,.port,.servertype,.memMax,.memCommitted,.memUse,.runtimeName)
 write !,"port="_port
 write !,"servertype="_servertype
 write !,"memMax="_memMax
 write !,"memCommitted="_memCommitted
 write !,"memUse="_memUse
 write !,"runtimeName="_runtimeName
Memory Management for the HotJVM Render Server
PDF rendering can be very memory intensive, especially if you are producing very large reports. If the rendering engine exhausts available physical memory, degraded performance and out of memory errors result. The most robust solution to out of memory errors is to put enough physical memory on the machine running the Render Server so that out of memory errors do not occur. The book Java Performance by Charlie Hunt and Binu John describes how to set up the JVM so that it logs out of memory errors. You can then test the system with what you anticipate to be a maximum load, and use the log to determine when out of memory errors occur. Add additional memory until the machine has enough memory to render all reports.
Zen reports has features that help to manage memory usage during report rendering. The first is a queuing discipline on the Render Server. Instead of directly processing rendering requests, the Render Server stores them in a queue. The Render Server queue gates rendering in the following manner:
Using a queuing size allows you to decrease the number of reports sent to threads and queue up rendering requests until a thread is available to process the request. The field Initial Queue Size on the Render Servers page (System Administration > Configuration > Zen Reports > Render Servers) lets you set the maximum size of the queue. The default value for the queue size is the number of Render threads, and you usually set it to a value less than or equal to the number of threads. A smaller queue size means that fewer reports are rendered simultaneously. You must determine the optimal queue size by benchmarking. Making the number of threads greater than the number of cores or processors probably results in little performance gain. Note that having a finite number of threads already causes queuing when there are more requests to render that arrive at the Render Server than there are available threads to perform rendering.
The Render Server queueing discipline helps prevent out of memory caused by trying to render too many reports at once but cannot solve all memory use problems, because you can still send a single report to the Render Server, which is large enough to cause out of memory errors.
An additional memory management feature allows you to define a threshold size for the tenured generation pool. When the Render Server receives a rendering request and the threshold size is exceeded the Render Server sleeps for the specified number of milliseconds. The Render Server polls the size of the tenured generation pool until memory usage is below the threshold size then performs the requested rendering. This algorithm allows the Render Server to adapt to low memory conditions by delaying rendering until used memory falls below a threshold you have set. The field Memory Threshold on the Render Servers page (System Administration > Configuration > Zen Reports > Render Servers) lets you set the memory threshold. For information on setting the Memory Threshold and other memory management parameters through the Management Portal, see Creating a HotJVM Render Server.
The Render Server does a System.exit(1) whenever it encounters an out of memory condition. This allows the Render Server to behave more deterministically when out of memory conditions occur.
The Print Server
Zen reports provides Print Server capability to improve PDF printing performance. The Print Server is a Java Virtual Machine process which runs in the background and prints Zen report PDF files.
The Management Portal Print Servers page (System Administration > Configuration > Zen Reports > Print Servers) lists currently configured Print Servers. When Caché is first installed, there are no Print Servers configured. If you have configured a Print Server, it starts automatically when you try to print a report using the Print Server port.
Tip:
In addition to using the instructions here, make sure that the user under whose name the Caché instance is running has adequate permissions to access the printer.
Creating a Print Server
The New Print Server button opens the New Zen Report Print Server page, which lets you configure a new Print Server. The first three fields are required, the remaining fields are optional.
Use the save button to save your changes, or the Cancel button to return to the Zen Report Print Servers page. Once you have saved your changes, you see that the new Print Server has been added to the list.
Print Engine
The Print Server print engine available is jPDFPrint from Qoppa Software.
When you use jPDFPrint, you need to define an environment variable that shows the location of the jPDFPrint JAR file. On Windows, this variable is in the System Environment variables. For example, set the environment variable JPDFPRINT_HOME to c:\Program Files\jPDFPrint
Managing the Print Server
The Manage button, which is located to the right of each listing on the Print Servers page (System Administration > Configuration > Zen Reports > Print Servers), lets you edit values and perform additional tasks:
In your Zen report you can set the PRINTSERVER class parameter to the port the Print Server is listening on. Then load the page with the mode set to pdfprint. You can also set PRINTSERVER class parameter for an entire Zen Application.
The Zen report property PrintTimeOut controls the length of time the report waits for the Print Server before timing out. A positive integer specifies the number of seconds to wait before timing out. A value of 0 means timeout immediately, and a value of –1 means never timeout. You can also pass the timeout interval in the URL using $PRINTTIMEOUT. The default value is null ("" in Caché), which means never timeout.
Communicating with the Print Server
The class %ZEN.Report.Ping provides the ping method that you can use to communicate with the Print Server.
In addition to the port and server type, ping returns the maximum memory available, the committed memory, and the amount of memory used. The Print Server attempts to use the Java tenured generation pool to get information about memory and return this information to ping. If the Print Server cannot find the Java tenured generation pool, it returns a blank string ("") for the value of maximum memory and used memory.
The ping method also returns the runtime name in the form pid@hostname. You can use $PIECE to process the string and get the process id.
The following example shows how to use ping:
 set Status=##class(%ZEN.Report.Ping).ping("1234",30,.port,.servertype,.memMax,.memCommitted,.memUse,.runtimeName)
 write !,"port="_port
 write !,"servertype="_servertype
 write !,"memMax="_memMax
 write !,"memCommitted="_memCommitted
 write !,"memUse="_memUse
 write !,"runtimeName="_runtimeName


Send us comments on this page
Copyright © 1997-2019 InterSystems Corporation, Cambridge, MA