Wrapping Up on XML Publisher

For this last posting on XML Publisher I thought I'd take a look at how reports are deployed into production. The approach I've used so far - build a report template using the XML Publisher Desktop product, then preview it as a PDF - is obviously the way that you'd develop and test reports, rather than roll them out, so I thought I'd take a look at how you can distribute the reports you've created (see also A First Look At XML Publisher and More on XML Publisher posted earlier this week, for a look at the XML Publisher Desktop component.)

The XML Publisher 5.5 download comes with two products; XML Publisher Desktop, the add-in to Microsoft Word that allows you to add XML Publisher data fields and report layout commands to an RTF document, and XML Publisher Server, a product that I hadn't taken a look at yet but that obviously looked promising as a delivery mechanism for reports I'd created using the Desktop product. The download also came with a number of demos for both Desktop and Server, and so I thought the best way of seeing the Server product in action was to run through the demos.

After installing Oracle Containers for Java 10.1.2, the Sun Java JDK 1.5.02 for Windows and installing them both, the next step was to install XML Publisher Server - or not as the case may be. Looking through the instructions for the server product, and the demos, it turns out that what you do is actually just copy the application you've created using the XML Publisher libraries, as an EAR or a WAR file, to the /applications directory of your application server, and then when you restart the application server the archive file should auto-deploy, containing with it the libraries to implement the XML Publisher Server functionality. There isn't a server product to install as such, the server is actually implemented as a servlet that runs within (in my instance) OC4J 10.1.2 - Apache Tomcat is also supported but it doesn't come with the XML Parser and JDBC libraries that you need to get XML Publisher working, I tried this first but couldn't get the demo applications working.

The most interesting demo that comes with XML Publisher Server is the "Online Reporting" demo. This demo gives you a web site where you can upload XML Publisher reports, and then run them on demand - as such it's a good pointer to how you might end up deploying XMLP reports in real life. When you get the application up and running, you get presented with a page looking like this:

Note the distinction between the report - which is an XML file - and the template - which is something separate. From reading through the documentation, it turns out that an XML Publisher "report definition" is actually an XML file with the extension ".xdo" - this is analogous to the ".rdf" or ".jsp" report definition file for Oracle Reports. This XML file actually references within it either the XML or SQL data source, and the RTF template file that defines how the report is layed out. Here's a quick excerpt from the docs:

"XDO Format : XML publisher report definition follows an XML-based format and is named with the .xdo suffix. The definition specifies where and how data should be retrieved, and which RTF layout templates are associated with the report. A report is divided into three major sections: data sets, report parameters and layout. The following example is a simple report definition (\samples\onlinereport\dbtest\EmpDept.xdo) that illustrates how a report can be created: 

<?xml version="1.0" encoding="UTF-8"?>
 
<report xmlns="http://xmlns.oracle.com/xdo/servlet" xmlns:xdo="http://xmlns.oracle.com/xdo/servlet">
  <dataSets>
    <dataSet name="xml-data" >      
      <sqlQuery dataSourceRef="demo">
        <sql>
          SELECT E.EMPNO, E.ENAME, E.JOB, E.SAL, D.DNAME
          FROM EMP E, DEPT D
          WHERE E.DEPTNO = D.DEPTNO
             {$if ${jobtitle}='*' $}
             {$else $}
          AND E.JOB = :jobtitle
             {$endif $}
             {$if ${dept}='*' $}
             {$else $}
          AND E.DEPTNO = :dept
             {$endif $}
          AND E.SAL > :lowsal
          ORDER BY ENAME
        </sql>
        <input name="jobtitle" value="${jobtitle}" dataType="xdo:STRING"/>
        <input name="dept" value="${dept}" dataType="xdo:INTEGER"/>
        <input name="lowsal" value="${lowsal}" dataType="xdo:INTEGER"/>
        <output name="result" dataType="xdo:XML"/> 
      </sqlQuery>
    </dataSet>
    <dataSet name="job-list" >
      <sqlQuery dataSourceRef="ipg">
        <sql>
          SELECT DISTINCT(JOB) FROM EMP ORDER BY JOB
        </sql>
        <output name="result" dataType="xdo:MAP"/>
      </sqlQuery>
    </dataSet>
    <dataSet name="dept-list" >
      <sqlQuery dataSourceRef="ipg">
        <sql>
            {$if ${jobtitle}='*' $}
          SELECT DISTINCT(D.DNAME), D.DEPTNO FROM DEPT D ORDER BY DNAME
            {$else $}
          SELECT DISTINCT(D.DNAME), D.DEPTNO FROM DEPT D, EMP E WHERE D.DEPTNO = E.DEPTNO AND E.JOB = :jobtitle ORDER BY DNAME
            {$endif $}          
        </sql>
        <input name="jobtitle" value="${jobtitle}" dataType="xdo:STRING"/>
        <output name="result" dataType="xdo:MAP"/>
      </sqlQuery>
    </dataSet>
  </dataSets>
 
  <layOut>
    <renderer type="uix" title="Sample Report" columns="3"/>
    <templates>
      <template name="Sample" type="rtf" url="sample.rtf" isDefault="true"/>
      <template name="Unicode" type="rtf" url="unicode2.rtf"/>
    </templates>
    <data bind="${xml-data.result}"/>
  </layOut>
 
  <reportParameters>
    <reportParameter name="jobtitle" defaultValue="MANAGER" submitOnChange="true">
      <select label="Job Title:" all="true">
        <item label="${job-list.result.JOB}" value="${job-list.result.JOB}"/>
      </select>
    </reportParameter>
    <reportParameter name="dept" defaultValue="*" submitOnChange="false">
      <select label="Department:" all="true">
        <item label="${dept-list.result.DNAME}" value="${dept-list.result.DEPTNO}"/>
      </select>
    </reportParameter>
    <reportParameter name="lowsal" defaultValue="0">
      <input label="Salary Greater Than:"/>
    </reportParameter>
  </reportParameters>
 
</report>

The Data sets section defines data sets used either for parameter LOVs or for the report. There are five types of data sets supported: SQL, Oracle PL/SQL, HTTP, Web services (document/literal only), and Oracle data templates, corresponding to sqlQuery, plsqlQuery, http, webservice and advancedQuery. Each data set must have a unique name inside the report, and optionally can have multiple input parameters and output parameters. Also note that the data source a data set uses must already be defined in the configuration file. 

The XDO format supports an object model that is similar to the Javascript DOM model; that is, an object can be referenced directly by its name using the format ${VARIABLE_NAME}. For example, for an output variable with the name result inside a data set with the name xml-data, its value is referenced as ${xml-data.result}. The object types supported are: xdo:STRING, xdo:STRINGARRAY, xdo:INTEGER, xdo:XML, xdo:MAP. 

IF-ELSE IF-ELSE-ENDIF logic is supported in the format demonstrated in the above example, and the test condition must be either equal(=) or not-equal(!=). Note the * in the test condition means all for the tested object. 

Report parameters are dynamic values that a report is dependent upon. Usually end users decide specific values for those report parameters, if any, and then a report document can be generated with data based on the parameter values. A report parameter is either an input field (input) or an LOV (select). For the LOV type parameter, if all attribute is set to be true, an all option is added automatically to the LOV. As stated above, the value of a report parameter can be referenced as ${PARAMETER_NAME}. 

Report templates must be uploaded through the application administration page and defined inside the layOut section of a report definition. The value of name attribute is the display name and the value of url attribute must be the same as the uploaded template file name.
"

Interesting. So the way this works is that the RTF file you generate using XML Publisher Desktop, together with the XML document if your report is based on XML data as opposed to an SQL query, is accompanied in real life by an XML .xdo file that ties it all together. I'm not sure how you would create this .xdo file at the moment - I don't think XML Publisher Desktop creates it for you, although I expect it creates one "on the fly" when you preview a report, so I guess with this version you have to create it yourself.

To use the demo you first upload the ".xdo" file - in this case, EmpDept.xdo, the same as the example I've reproduced above, and a template file to define how the report is layed out. These get uploaded by the demo application to a location on the server filesystem, and you can then switch from the upload tab to the repository tab to run the report, like this:

You can then click on the View button to view the templates associated with a report name, like this:

and then run the report by using the Run button. The report looks like this:

Note how you can change the report layout by changing the template that you're using, the language and the output format. Note also that the report parameters - job title, department, salary and so on - are defined in the .xdo file and are render automatically when the report is displayed.

So, in summary, what does this tell us about XML Publisher, and deploying reports in a production situation? Well, firstly, XML Publisher Server isn't a product you  install as such, it's a set of libraries you include within a Java application, that you then deploy to an application server as a WAR or an EAR file. XML Publisher is then implemented as a servlet that then takes a minimum of two files you create - an XML file with a ".xdo" extension that defines the report, a template file that defines the report layout, and an optional XML file that contains the data - and renders your report as either a HTML page, a PDF, an RFT (Word) document, an Excel spreadsheet or an XML file. All of the aspects around the production of the report - securing access to reports, providing a framework to list out available reports, scoping access to data, providing a means to report against non-XML or SQL data - is outside the scope of XML Publisher and would need to be provided by the host application.

As a final wrap-up I noticed a few interesting postings on the XML Publisher OTN Forum that I though worth making a note of:

There's also a section in the readme.html for the server product that goes through how you can add XML Publisher functionality to your Java application - what you have to do here is copy the XML Publisher libararies into your java project, together with the fonts, and include a configuration file called "xdo.cfg" to define how the XML Publisher functionality works.

That's it for me on XML Publisher for now. If anyone has any successes with the product or any tips or tricks, let me know. My understanding is that another version - 5.6 - should be out afer Christmas, so when that's out I'll try and do an update.