During these years with Publisher, I worked with many clients directly/indirectly to resolve there reporting issues and one of the very common requirment is about generate mutilple outputs against the single process/report. Here I am sharing one such requirment...
The company’s billing system generates around 30 thousands invoices/bills for each billing cycle. Each billing cycle correspond to a single process and generate a huge set of data for all the invoices.
The process, further consume this huge data and generate the individual Invoices. i.e. one report and multiple output.
The individual Invoice layout depends upon the recipient’s country and local preference, So it could be multiple templates and multiple local. .
The process should take care of document delivery as well. Delivery type and the destination depend on individual client’s preference. Beside it, a copy of each invoice should be save to specific file location or transferred to content management system. To achieve this, the process should allow to hook custom APIs/Logic before and after individual documents generation.
Beside the individual output, there should be another single consolidated output against the same set of data. i.e. a summary report.
So what do you think, Can we satisfy this requirement against the single process?
Yes, The Bursting take care of such type of requirements where single dataset, multiple conditional layouts/templates, multiple layout, multiple delivery and the listener to hook the custom logic at each stage of process.
There are two type of bursting implementation within BI Publisher. The Control File based bursting, which is well integrated with EBS and JDE and available through Public APIs as well. The other one is Delivery SQL based bursting, which is part of Enterprise Release. We will discuss the first one on this post.
The Bursting Control file holds the Meta Data or the bursting rules in XML format.Lets have a look on following control file and see, how far it satisfies the above requirement.
<?xml version="1.0" encoding="UTF-8"?>
<xapi:requestset xmlns:xapi="http://xmlns.oracle.com/oxp/xapi">
<xapi:globalData location="stream">
</xapi:globalData >
<xapi:request select="/DATA/LIST_DEPT/DEPT/LIST_EMPLOYEE/EMPLOYEE">
<xapi:delivery>
<xapi:email server="${EMAIL_SERVER}" port="${EMAIL_PORT}" from="${FROM_EMAIL_ADDRESS}"
reply-to ="${REPL_TO_ADDRESS}">
<xapi:message id="123" to="${TO_EMAIL_ADDRESS}" cc="${CC_EMAIL_ADDRESS}"
attachment="true" content-type="html/text"
subject="Employee Report for Empno ${EMPNO}"> Dear ${ENAME},
Please review the attached document.</xapi:message>
</xapi:email>
<xapi:print id="printer1" printer="${PRINT_URL}" copies="2"
orientation-requested="3" />
</xapi:delivery>
<xapi:document key="${EMPNO}" output="c:\burst\sample\${EMPNO}_${ENAME}.pdf"
output-type="pdf" delivery="123">
<xapi:template type="rtf" location="${EMP_TEMPLATE}">
</xapi:template>
</xapi:document>
</xapi:request>
</xapi:requestset>
|
A sample control file available
here.
This will not exactly satisfy the above requirement but it gives an idea, how we can proceed to achieve the above requirement.
Here is the sample usage of Bursting Engine. We can call bursting engine either directly or through DocumentPrecoessor. Calling directly gives more control over some of the internal methods. API accept the Control file, Data File and Temporary directory path.
Using BurstingProcessorEngine directly..
try {
BurstingProcessorEngine dp = new BurstingProcessorEngine();
dp.deleteTempOutputFile(false);
dp.setTempDirectory("c:\\burst\\sample");//Set the temp file
dp.setXMLAPI("C:\\burst\\sample\\SampleControlFile.xml"); //Set Bursting Control file.
dp.setData("c:\\burst\\sample\\employee.xml"); //Data File
dp.registerListener(this); //Set the listener
Properties prop = new Properties(); //add properties and variables//
prop.put("user-variable:EMAIL_SERVER", "myemailserver.com");
prop.put("user-variable:EMAIL_PORT", "25");
prop.put("user-variable:FROM_EMAIL_ADDRESS", “admin@xyz.com");
prop.put("user-variable:CC_EMAIL_ADDRESS", "cc@xyz.com");
prop.put("user-variable:PRINTER_URL", "ipp://myprintserver:631/printers/printer1");
prop.put("user-variable:EMP_TEMPLATE", "c:\\burst\\sample\\employee.rtf");
dp.setConfig(prop);
dp.process();
dp.deletTemporaryOutputFiles();
} catch (Exception e) {
Logger.log(e);
}
Using DocumentProcessor:
try {
DocumentProcessor dp = new DocumentProcessor("C:\\burst\\sample\\SampleControlFile.xml","c:\\burst\\sample\\employee.xml", "c:\\burst\\sample");
dp.setTempDirectory("c:\\burst\\sample");//Set the temp file
dp.setXMLAPI("C:\\burst\\sample\\SampleControlFile.xml"); //Set Bursting Control file.
dp.setData("c:\\burst\\sample\\employee.xml"); //Data File
dp.registerListener(this); //Set the listener
Properties prop = new Properties(); //add properties and variables//
prop.put("user-variable:EMAIL_SERVER", "myemailserver.com");
prop.put("user-variable:EMAIL_PORT", "25");
prop.put("user-variable:FROM_EMAIL_ADDRESS", “admin@xyz.com");
prop.put("user-variable:CC_EMAIL_ADDRESS", "cc@xyz.com");
prop.put("user-variable:PRINTER_URL", "ipp://myprintserver:631/printers/printer1");
prop.put("user-variable:EMP_TEMPLATE", "c:\\burst\\sample\\employee.rtf");
dp.setConfig(prop);
dp.process();
} catch (Exception e) {
Logger.log(e);
}
A sample test case including sample java application, control file, data file, rtf template is available here. Please make sure you have following libraries in class path
Collection.jar, xdo.jar, Xmlparserv2.jar, mail.jar, Activaton.jar, aolj.jar, i18n, xdoparser.jar,Versioninfo.jar and use 10.1.3.4+ release.
Try it out and let me know your experience. We will see some more interesting example during coming post, so stay tune…