Archive for the ‘Oracle Reports’ Category

The Oracle Report Bean

Sunday, August 23rd, 2009

(Originally posted on the “old” Jason Bennett’s Developer Corner, Sunday, June 15, 2008)

The Oracle Report Bean is a cool little bit of code I developed this week that will let you to execute an Oracle Report from within your JEE or plain old Java application.  The bean allows you to configure all of the report execution parameters and contains methods to execute the report as a printed report or have the report streamed back to the client if the chosen format (PDF, RTF, HTML, XML, etc).  The code basically constructs the URL you need to access the Oracle Reports servlet (rwservlet). I’m actually using the Oracle Report Bean as the interface to Oracle Reports in my current ADF Faces project.

Hitting the highlights …

The bean provides a set of constants (static variables) that represent rwservlet keywords (commands).   The code uses two Hash Maps (HashMap classes) for storing parameters.  One Hash Map holds the reports servlet keywords and values, and the other holds input parameters and values for the actual report being executed.  The Hash Maps are hidden behind getter and setter methods.  When setting a reports servlet key word, the developer may either use one of the static keyword references provided by the bean, or simply add one of their choosing (it’s up to them to make sure it’s a legitimate keyword/parameter at that point).  Using the Hash Maps makes it easier to construct the URL later using a simple loop.

The bean provides two methods for executing the report. One method, executePrintedReport, passes the fully constructed URL to the reports servlet and returns the response (either HTML or XML) as a String.  A helper method, formatXMLResponse, is provided to format the response returned by the reports server in client friendly manner (NOTE: The developer needs to set the status format to XML to use this helper method). This method is specifically intended for use with reports bound for external destinations (printers, email, etc.).  The other method, executeBinaryReport, passes the fully constructed URL to the reports servlet and then returns a data stream (InputStream class).  This method is intended for use with reports whose content will be returned directly to the client (the destination for these reports should be set to CACHE).  Use the executeBinaryReport method when you need to return report results directly to the client (desformats PDF, RTF, HTML, XML).  The bean also provides a method that simply returns the URL for executing the report: getReportServerURL.

Sample Bean Usages …

The following code snippet demonstrates how to setup the bean to execute a printed report:

{

OracleReportBean testBean = new OracleReportBean(“appserver”,”7778″,null);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_SERVER,”my_repserv”);

testBean.setKeyMap(“db_key”);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_ENVID,”orcl”);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_DESTYPE,

OracleReportBean.DESTYPE_PRINTER);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_DESNAME,

“myPrinter-01″);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_REPORT,

“MyReport.rdf”);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_ORIENTATION,

OracleReportBean.ORIENTATION_PORTRAIT);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_DESFORMAT,

OracleReportBean.DESFORMAT_HTML);

testBean.setReportParameter(“p_id”,”50″);

testBean.setReportParameter(“p_user”,”JASON BENNETT”);

System.out.println(testBean.formatXMLResponse(testBean.executePrintedReport()));

}

This code snippet demonstrates how to setup the bean to execute and retrieve a binary report (PDF, HTML, XML, RTF, …):

{

OracleReportBean testBean = new OracleReportBean(“appserver”,”7778″,null);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_SERVER,”my_repserv”);

testBean.setKeyMap(“db_key”);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_ENVID,”orcl”);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_DESTYPE,

OracleReportBean.DESTYPE_CACHE);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_REPORT,

“MyReport.rdf”);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_ORIENTATION,

OracleReportBean.ORIENTATION_PORTRAIT);

testBean.setReportServerParam(OracleReportBean.RS_PARAM_DESFORMAT,

OracleReportBean.DESFORMAT_HTML);

testBean.setReportParameter(“p_id”,”50″);

testBean.setReportParameter(“p_user”,”JASON BENNETT”);

try{

BufferedReader br;

br = new BufferedReader(

new    InputStreamReader(testBean.executeBinaryReport()));

String inputString = null;

while((inputString = br.readLine()) != null){

System.out.println(inputString);

};

}catch(Exception e){

e.printStackTrace();

}

}

The Code …

Finally, here is the code for the Oracle Report Bean:

import java.io.BufferedReader;
import java.io.InputStream;

import java.net.URLConnection;
import java.net.URL;
import java.io.InputStreamReader;
import java.io.StringReader;

import java.util.HashMap;
import java.util.Iterator;

import oracle.xml.parser.v2.DOMParser;
import oracle.xml.parser.v2.XMLConstants;
import oracle.xml.parser.v2.XMLDocument;
import oracle.xml.parser.v2.XMLElement;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/***
* This bean performs the following functions:
* Constructing the Report URL with various parameters passed in by client.
* Sending the report request.
* Execute printed report and retrieve return status in the indicated format.
* Execute a binary report (PDF, RTF, XML, with DESTYPE CACHE) and return the
* InputStream for processing.
*/
public class OracleReportBean {

/* Report Servlet Host Settings */
private String http_host = null;
private String http_port = null;

/* Default path as per generic Oracle Appserver install */
private String servlet_path = “/reports/rwservlet”;

/* Report Servlet URL params */
public static final String RS_PARAM_SERVER = “server”;
public static final String RS_PARAM_REPORT = “report”;
public static final String RS_PARAM_ENVID = “envid”;
public static final String RS_PARAM_DESTYPE = “destype”;
public static final String RS_PARAM_DESFORMAT = “desformat”;
public static final String RS_PARAM_STATUSFORMAT = “statusformat”;
public static final String RS_PARAM_DESNAME = “desname”;
public static final String RS_PARAM_PAGESTREAM = “pagestream”;
public static final String RS_PARAM_DELIMITER = “delimiter”;
public static final String RS_PARAM_ORIENTATION = “orientation”;
public static final String RS_PARAM_DISTRIBUTE = “distribute”;

private String value_keyMap = null;

/* Static values for destination formats */
public static final String DESFORMAT_PDF = “PDF”;
public static final String DESFORMAT_HTML = “HTML”;
public static final String DESFORMAT_POSTSCRIPT = “POSTSCRIPT”;
public static final String DESFORMAT_DELIMITED = “DELIMITED”;
public static final String DESFORMAT_XML = XML;
public static final String DESFORMAT_RTF = “RTF”;

/* Static values for destination types*/
public static final String DESTYPE_MAIL = “mail”;
public static final String DESTYPE_PRINTER = “printer”;
public static final String DESTYPE_FILE = “file”;
public static final String DESTYPE_LOCAL_FILE = “localFile”;
public static final String DESTYPE_CACHE = “cache”;

/* Static values for distribute */
public static final String DISTRIBUTE_YES = “YES”;
public static final String DISTRIBUTE_NO = “NO”;

/*Static values for status format */
public static final String STATUSFORMAT_XML = XML;
public static final String STATUSFORMAT_HTML = “HTML”;

/* Static values for report orientation */
public static final String ORIENTATION_PORTRAIT = “PORTRAIT”;
public static final String ORIENTATION_LANDSCAPE = “LANDSCAPE”;
public static final String ORIENTATION_DEFAULT = DEFAULT;

/* HashMap to hold individual report parameters*/
private HashMap reportParams = new HashMap();

/* HashMap to hold report server params */
private HashMap reportServerParams = new HashMap();

/* Report Servlet */
private StringBuffer reportURL = new StringBuffer();
private String XMLReturnStatus = null;

/***
* Constructor
*/
public OracleReportBean(String p_http_host,
String p_http_port,
String p_servlet_path)
{
http_host = p_http_host;
http_port = p_http_port;

/* If the servlet path is null, we assign the default path. */
if (p_servlet_path != null){
servlet_path = p_servlet_path;
}

/* Default the status format to XML */
setReportServerParam(RS_PARAM_STATUSFORMAT,STATUSFORMAT_XML);

}

/*****
* Private utility methods …
*
*/
private String buildKeyValueString(HashMap p_map){

String map_key = null;
String param_sep = “&”;
String param_equal = “=”;
StringBuffer keyValueBuffer = new StringBuffer();

if (!p_map.isEmpty()){

Iterator mapKeys = p_map.keySet().iterator();

while (mapKeys.hasNext()){
map_key = (String)mapKeys.next();
keyValueBuffer.append(map_key).append(param_equal).append(p_map.get(map_key));

if(mapKeys.hasNext()){
keyValueBuffer.append(param_sep);
}
}
}

return keyValueBuffer.toString();

}

/* Construct the URL for accessing the Oracle Reports Servlet */
private void constructURL(){

String param_sep = “&”;

/* Clearout current URL */
reportURL = new StringBuffer();

/* HOST Section */

reportURL.append(“http://”);

reportURL.append(http_host);

if (http_port != null){
reportURL.append(“:”).append(http_port);
}

/* Add “/” separator if necessary. */
if (servlet_path.indexOf(“/”) > 0){
reportURL.append(“/”);
}

reportURL.append(servlet_path);
reportURL.append(“?”);

if(value_keyMap != null){
reportURL.append(value_keyMap).append(param_sep);
}

/*Construct Report Server Parameter URL component*/
reportURL.append(buildKeyValueString(reportServerParams));

if(!reportServerParams.isEmpty()){
reportURL.append(param_sep);
}

/*Construct Report Parameters URL Component*/
reportURL.append(buildKeyValueString(reportParams));
}

/***
* Getters and Setters for the Reports Servlet
* URL parameter values.
*/

public void setReportServerParam(String p_param,
String p_value){
reportServerParams.put(p_param,p_value);
}

public String getReportServerParam(String p_param){
if(reportServerParams.containsKey(p_param)){
return (String)reportServerParams.get(p_param);
} else {
return null;
}
}

/* Set/Get the value of a Reports KeyMap file */
public void setKeyMap(String p_keyMap){
value_keyMap = p_keyMap;
}

public String getKeyMap(){
return value_keyMap;
}

/* Add/Update and retrieve individual report parameters */
public void setReportParameter(String paramName,
String paramValue){

reportParams.put(paramName,paramValue);
}

public String getReportParameter(String paramName){

if (reportParams.containsKey(paramName)){
return (String)reportParams.get(paramName);
} else {
return null;
}

}

/****
* Construct and return a URL that can be used to execute the report.
*/
public String getReportServerURL(){
constructURL();
return reportURL.toString();
}

/***
* Execute a report whose destination is a printer or other
* non-client destination. (i.e. the report is not coming back
* to the calling client in binary format …)
*/
public String executePrintedReport(){

String v_return_status = null;
StringBuffer serverResponse = new StringBuffer();

try{

BufferedReader br;

br = new BufferedReader(new InputStreamReader(executeBinaryReport()));

String inputString = null;
while((inputString = br.readLine()) != null){
serverResponse.append(inputString);
};

v_return_status = serverResponse.toString();

}catch(Exception e){
e.printStackTrace();
v_return_status = “Error printing report: “+e.getMessage();
}
return v_return_status;
}

/***
* This method is used to execute a binary report
* that is intended to be returned to the
* A binary report is a report that is returned as
* a physical file such as PDF, RTF, etc
* DESTYPE needs to be CACHE in order to get a return
* stream (file …).
*/
public InputStream executeBinaryReport() throws Exception{

URL url = new URL(getReportServerURL());
URLConnection urlc= url.openConnection();

return urlc.getInputStream();
}

/****
* This method takes the XML response generated by the Oracle Reports Server
* servlet and generates a more user friendly response message.
* NOTE: This only works for the XML statusformat type.
*/
public String formatXMLResponse(String p_response){

StringBuffer formattedResponse = new StringBuffer();

try{

DOMParser parser = new DOMParser();
parser.showWarnings(false);
parser.setValidationMode(XMLConstants.NONVALIDATING);
parser.parse(new InputSource(new StringReader(p_response)));

XMLDocument doc = parser.getDocument();

XMLElement elements = (XMLElement)doc.getDocumentElement();

NodeList nl = elements.getElementsByTagName(“error”);

if (nl.getLength() > 0){
String err_component = doc.selectSingleNode(“//error[1]/@component”).getNodeValue();
String err_code = doc.selectSingleNode(“//error[1]/@code”).getNodeValue();
String err_message = doc.selectSingleNode(“//error[1]/@message”).getNodeValue();

formattedResponse.append(“Oracle Reports job submit error; “).append(err_component);
formattedResponse.append(“-”).append(err_code).append(“: “).append(err_message);
}else{

String job_id = doc.selectSingleNode(“//job[1]/@id”).getNodeValue();
String job_status = doc.selectSingleNode(“//status[1]/text()”).getNodeValue();
String job_status_code = doc.selectSingleNode(“//status[1]/@code”).getNodeValue();

if ((job_id == null)||(job_status==null)||(job_status_code==null)){

formattedResponse.append(“Oracle Reports job submit problem; “).append(“Job Id=”).append(job_id);
formattedResponse.append(“, Code=”).append(job_status_code).append(“, Status=”).append(job_status);

}else{

formattedResponse.append(“Report submitted successfully!”);

}

}

}catch(Exception e){
e.printStackTrace();
String error = “Error processing Oracle Report Server response: “+e.getMessage();
System.err.println(error);
formattedResponse.append(error);
}

return formattedResponse.toString();

}
}

Automatically Print Web-based Oracle Reports (PDF format) to a User’s Local/Default Printer

Saturday, August 22nd, 2009

(Originally posted in the “old” Jason’s Developer Corner, Tuesday, November 29, 2005)

Working for a major metropolitan police department, I get some interesting development assignments. One such assignment was to allow officers connected to our network via VPN to send their printed reports to the default printer assigned to the machine they are using. No problem! Oracle Reports has a setting that will send a PDF version of the report back to the user’s web browser using the Adobe Acrobat plug-in. They can just hit the print button in the Acrobat viewer and print the report to any printer available to the machine! No sweat! Oh … by the way … the officer is not allowed to save the report to his/her machine (for security and privacy reasons). This is where the task got sticky. The Acrobat Viewer has a ‘Save’ button. This feature cannot be turned off programmatically. A command has to be impeded in PDF document at the time it is created to keep it from being saved. Unfortunately, Oracle Reports doesn’t offer this as an option for reports being created in a PDF format (at least in our version). After a little searching, I found a solution. The rest of this entry will show you how to do it using an open source tool and some standard browser features. Nothing is impossible …

The Solution …

The solution to the problem was to imbed a JavaScript command in the PDF document that forced an auto print to the default printer while accessing the document from a hidden IFRAME (width 0, height 0).  The only hitch � how the heck do we imbed a JavaScript command in a PDF document that is being generated by Oracle Reports.  This is where the open source option came into play.  After some searching, I came across an open source project called iText (http://www.lowagie.com/iText/). iText is a library that allows you to generate or modify (to some extent) PDF files on the fly.  iText is available in both Java and .NET flavors.  Being a Java fan and an Oracle Application Server customer, I chose the Java flavored iText solution.  I created a servlet that acted as a proxy to the Oracle Reports Servlet.  The servlet, acting as a proxy, is then able to received the data stream from the Oracle Reports servlet.  In this case, the data stream is a PDF document.  Using the iText library, I added the auto print command to the PDF document and then had the proxy servlet pass the altered document to the user’s browser.  To keep the user from saving this document, I had the request for the report sent to the proxy servlet through an IFRAME with a width and height of 0This kept the user from seeing the document in the Adobe Acrobat plug-in and kept them from saving the document.

The Code …

Being a left-handed right-brained developer, I tend to learn more from actually seeing the code than reading about it.  The iText APIs are well documented at the iText website (http://www.lowagie.com/iText) along with examples.  JavaScript commands as they relate to PDF documents can be found at http://partners.adobe.com/public/developer/pdf/library/index.html.   I have included comments in the code in key locations.  As usual, if you have questions, shoot me an email.  Here is the code for the servlet:

import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.PdfWriter;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLConnection;
import javax.servlet.*;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.net.URL;
import java.net.MalformedURLException;

//iText Open Source PDF APIs … awesome code!

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfImportedPage;

public class PDFLocalPrint extends HttpServlet
{

private static final String CONTENT_TYPE = “application/pdf”;

public void init(ServletConfig config) throws ServletException
{

super.init(config);

}

private ByteArrayOutputStream getDoc(String p_url)
{

Document document = null;

PdfCopy writer = null;

PdfImportedPage page;

ByteArrayOutputStream baos = null;

int v_pages = 0;

try{

URL url = new URL(p_url);

URLConnection urlc= url.openConnection();

int length = urlc.getContentLength();

InputStream in = urlc.getInputStream();

baos = new ByteArrayOutputStream();

PdfReader oracleReport = new PdfReader(in);

oracleReport.consolidateNamedDestinations();

v_pages = oracleReport.getNumberOfPages();

document = new Document(oracleReport.getPageSizeWithRotation(1));

writer = new PdfCopy(document,baos);

document.open();

//Copy content from PDF streaming from Reports Server to new PDF Document.

for(int i=0;i0)

{

//Pass the altered document back to the requesting browser or application.

doc = getDoc(v_report_url);

response.setContentType(CONTENT_TYPE);

response.setContentLength(doc.size());

doc.writeTo(out);

doc.close();

out.flush();

}else{
out.println(“No Data”);
out.close();

}

}

}