Couple days ago I've run into curious issue, how to print Classic report from Apex 5 application.
I have no ORDS 3. on my humble Fedora VM, and I not realy want to install it. Oracle BI Publisher ain't option (unless you run corporate reports on OBIEE 11g/12c). Well Apex has the 3rd option - External - with Apache FOP.
Yeah, right! It has to be a servlet in your
apex/utilities/fop folder. OOps, it used to be there.
Well, not a big deal, anyway it is a single JSP application with Apache FOP libraries and one big issue - it works out of the box only on Oracle Application servers, for all other cases you should get somewhere O
racle XML Parser libraries (for example - download XDK). processors. Out of this great discussion you may find whole source of fop.war servlet.
Okay then, we will create our own servlet with b
lackjack & ..., oops with FOP and standard Java XML parser.
what APEX expects from our application. It sends two parameters:
- xml - document with report data
- template - XSLT stylesheet to process data
Application should respond back with PDF document.
To accomplish this simple task you need:
- Apache FOP runtime libraries.
- Some application server to run our JSP application. (Let's stick with Apache and get a Tomcat)
- JSP to get parameters from APEX and generate PDF page.
Let's chase to the source.
<%@ page import='org.w3c.dom.Document' %>
<%@ page import='java.io.*' %>
<%@ page import='org.xml.sax.InputSource' %>
<%@ page import='javax.xml.transform.stream.StreamSource' %>
<%@ page import='javax.xml.transform.stream.StreamResult' %>
<%@ page import='javax.xml.parsers.DocumentBuilderFactory' %>
<%@ page import='javax.xml.parsers.DocumentBuilder' %>
<%@ page import='javax.xml.transform.TransformerFactory' %>
<%@ page import='javax.xml.transform.Transformer' %>
<%@ page import='javax.xml.transform.dom.DOMSource' %>
<%@ page import='org.apache.fop.apps.Driver' %>
<%
//Set response type to PDF
response.setContentType("application/pdf");
// Prepare XML document
DocumentBuilder db = DocumentBuilderFactory.
newInstance().newDocumentBuilder();
// Parse parameter xml
Document v_xml = db.parse(new InputSource(
new java.io.StringReader(
request.getParameter("xml")
)));
// Create XSLT processor with instructions from template parameter
Transformer v_xsl = TransformerFactory.newInstance().newTransformer(
new StreamSource(
new java.io.StringReader(
request.getParameter("template"))
));
// Prepare output Stream
ByteArrayOutputStream v_out = new ByteArrayOutputStream();
// Transform data into XSL-FO document
v_xsl.transform(new DOMSource(v_xml),new StreamResult(v_out));
String v_fop = new String(v_out.toByteArray(),"UTF-8");
// Initialize FO driver
Driver drv = new Driver();
drv.setRenderer(Driver.RENDER_PDF);
// Prepare output for PDF document
v_out = new ByteArrayOutputStream();
drv.setOutputStream(v_out);
// Set Input source for FO driver
drv.setInputSource(new InputSource(new StringReader(v_fop)));
// Produce document
drv.run();
// Returnresult for client
// Fix to avoid Tomcat/JBoss double open exception
OutputStream outStream = response.getOutputStream();
response.setContentLength(v_out.size());
outStream.write(v_out.toByteArray());
outStream.flush();
%>
Now make sure, that your WEB-INF/lib folder contains libraries to run FOP driver. I've found old distribution with few libraries. that is how it looks like in my NetBeans Libraries list.
Well, that's all folks. If you use NetBeans or just have got my war archive - time to have fun.
Copy archive to your Tomcat webapps folder and try to open /fop page.
You should see this some ugly page as on picture below. This means your application is up and running and click on "test servlet" URL will show you generated PDF document.
I don't see how you may run into issues with that, on my Tomcat 7/JDK 1.7 it runs out of the box.
Now you are ready to change Apex print configuration.
Set Report printing properties as below.
Print Server: | External (Apache FOP) |
Print Server Protocol: | HTTP |
Print Server Host Address: | FQDN of your Tomcat server |
Print Server Port: | Your Tomcat listen port (8080 by default) |
Print Server Script: | /fop/pdf_print.jsp |
It's time to run "real-life" example. I have a tiny application with standard report page and to print reports you should enable printing. It's quite easy for primitive examples like mine. Go to report region and open Print Attributes tab and dig into Printing section (I left report customization for you, you've seen my index page design, right ). What I used to set for report:
Enable Report Printing | Yes |
Link Label | Get PDF |
I't just a name, put anything you like |
Response Header | Report Settings |
View File As | Inline |
Personally I prefer to open PDF in browser, you may pick attachment and download report as PDF file. |
Output format | PDF |
NO reason to select anything else. It is a PDF generator isn't it? |
If you know meaning of the other parameters you can change them. I left rest of the items intact. Save region settings and run your report page. You will see your Link label next to
Download and if you click on it - you will get your PDF printer like I've got mine.
Here is
web application to save your time and there is a GIT
source code and libraries.
Enjoy and take care.