Birt Integration Part1
Birt Integration Part2
Birt is one of the powerful free report designing tool which comes with nice eclipse plugin having good report designing tool.
When I was designing reports with designer plugin in eclipse I found it very simple. But when it came to deployment we need to deploy it in separate web application provided by birt-runtime, but it was not the requirement for me.I was looking for birt integration with my existing application. So I started analysis for integrating birt report engine in my application and after 1 week of research I was successfully able to integrate with my application.
For better understanding I have created one simple web application.Go through following steps to achieve successful integration:
Index For Birt Integration
1) Overview
2) Installation
3) Java Classes For integration
4) Jsp and Sample Reports
5) JavaScript for loading report using ajax.
6) Sample report with pagination functionality (Under development).
7) Download
Overview
This simple birt integration web project which provides the same functionality provided by birt web application.Basic flow starts with ajax report request which is simply handled by one servlet and which is handover to report engine for processing and rendering output to the output response or downloading in pdf,xls and doc format.Note* Currently pagination feature is under progress.
Here we are using following technology:
- Birt 3.7.1 libs
- jquery-1.7.1.js (here any version will work as we are using for ajax call only)
- Simple servlet and jsp.
- Eclipse Plugin For Birt Report Designer.
Installation
Follow below steps for installation of this example web project.
1) Download this example web project from here.
Update :Check sample project for pagination support here
2) Import the project in eclipse
3) Download birt 3.7.1 runtime or other version from here
4) Copy all the jars from birt-runtime-3_7_1\birt-runtime-3_7_1\ReportEngine\lib To web
applications lib.
Java Classes For integration
These are the classes which are responsible for integrating birt engine in web application. These classes will simply instantiate ,initialise the report engine,process reports and destroy the engine when context is destroyed.
Below is short description of the classes in sample web project:
1) BirtReportController : This class handles request for the report rendering or downloading.
2) ReportProcessor : This is singleton class which takes care of starting report engine ,processing report ,rendering report and shutting down report engine.
3) ReportRenderer : This class actually process reports and renders it to httpresponse object.It also handles downloading report functionality.
4) BirtEngineFactory : This class configures birt engine using EngineConfig class object and returns
BirtEngine object.It has logging configuration.
.
5) ReportParameterConverter : Convert report parameter value between object and string.
Below is the source code of the some Class with explanation:
1) BirtReportController :
This class extends httpservlet which is responsible for handing report rendering request.
Method:
- init() : Initialise birt engine
- get() or post() : handles processing and downloading report request
- destroy() :Shutdown report engine.
code:
package BirtIntegration.Controller;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import BirtIntegration.BirtViewer.ReportProcessor;
public class BirtReportController extends HttpServlet {
//this is the single tone class.
private ReportProcessor processor ;
@Override
public void init(){
processor = ReportProcessor.getReportProcessor();
processor.initilizeBirtEngine();
System.out.println("Engine Initialized!!");
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processor.processReport(request, response);
System.out.println("processing report complete");
}
@Override
public void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
@Override
public void destroy(){
processor.shutDownBirtEngine();
}
}
2) ReportProcessor :
This is singleton class has BirtEngineFactory and ReportRenderer object.
This class performs following operations using ReportRenderer:
- Initializing Report Engine.
- Processing report for rendering and downloading.
- Destroying report engine.
Code:
package BirtIntegration.BirtViewer;
import java.io.File;
import java.util.logging.Level;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import BirtIntegration.factory.BirtEngineFactory;
/**
* This class is responsible for initlizing birt engine configuring birt *engine,and processing and rendering reports.
*
*/
public class ReportProcessor {
private BirtEngineFactory birtEngineFactory;
private ReportRenderer reportRenderer;
private static ReportProcessor reportProcessor =null;
//private constructor for single tone object.
private ReportProcessor(){
}
public boolean initilizeBirtEngine(){
boolean isInitialized =true;
reportRenderer = new ReportRenderer();
reportRenderer.setBirtEngine( this.getBitEngineFactory().getEngine() );
System.out.println("Bit Engine Successfully Started.");
return isInitialized;
}
/**
* Annotated with @ bean and will create BirtEngineFactory bean.
* @return
*/
private BirtEngineFactory getBitEngineFactory(){
birtEngineFactory = birtEngineFactory = BirtEngineFactory.getBirtEngineFactory() ;
//uncomment to use logging
//birtEngineFactory.setLogLevel( Level.FINEST);
//birt engine logs will be created under this directory.
//currently this line is commented
//birtEngineFactory.setLogDirectory( new File("E:/WorkSpaces/PracticeWorkspace/BirtIntegration/birtlogs"));
return birtEngineFactory;
}
public void shutDownBirtEngine(){
birtEngineFactory.destroy();
}
public void processReport(HttpServletRequest request,
HttpServletResponse response) {
reportRenderer.processReportDesignDocAndRenderReport(request, response);
}
public static ReportProcessor getReportProcessor() {
if(reportProcessor !=null){
return reportProcessor;
}
reportProcessor = new ReportProcessor();
return reportProcessor;
}
}
3) ReportRenderer
This class actually process the report request. This class has method processReportDesignDocAndRenderReport(request,response), the request object has following parameters :
- ReportName :ReportName which is processed (e.g books_report.rptdesign).
- ReportFormat : Html,Pdf,Xls,word. If it is other than html then it’s download request.
- pageNumber : This used to render particular page request in pagination.
- Other Request Parameter in request object will be converted in report parameter ,which will be given to query or other data sources as per the need.These parameters are used for filtering the reports data.
All the reports (.rptdesign ) are located in BirtIntegration\WebContent\Reports folder.
The report is processed in two phases by
1)IRunTask : Process .repdesign and generates temp.rptdocument and it also converts
request parameter to report parameter.
2)IRenderTask : Processes temp.rptdocument document and renders report to response
object based on type html,pdf,xls. It is responsible for setting the current page
and also getting the total count of pages.
Code of processReportDesignDocAndRenderRepor() is below for whole class code download the example project :
code:
Code:
/**
* This is overridden method which responsible for processing report i.e .rptdesign document.and also rendering the report.
*
It also handles downloading the report.
*
*/
protected void processReportDesignDocAndRenderReport(HttpServletRequest request,
HttpServletResponse response) {
try{
//get report name from request object.
String reportName = request.getParameter( this.reportNameRequestParameter );
//logger.info("Processing report:"+reportName);
//get format in which we are going to render report i.e:html,pdf,excel
String format = request.getParameter( this.reportFormatRequestParameter );
//pagination handling
String pageNumber = request.getParameter("pageNumber");
int currentPageNumber=0;
if(pageNumber!=null&&!pageNumber.equals(""))
{
currentPageNumber = Integer.valueOf(pageNumber);
}
//give the download report Name here.
String downloadFileName = "MyReport";
//Base URL
String baseUrl = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()+request.getContextPath();
ServletContext sc = request.getSession().getServletContext();
if( format == null ){
format="html";//default format
}
IReportRunnable runnable = null;
//opend design document
runnable = birtEngine.openReportDesign( sc.getRealPath("/Reports")+"/"+reportName );
//first process the report using Iruntask which will create the temp.rptdocument
IRunTask iRunTask = birtEngine.createRunTask(runnable);
iRunTask.getAppContext().put( EngineConstants.APPCONTEXT_BIRT_VIEWER_HTTPSERVET_REQUEST, request );
//put the parameter values from request to the report parameter
iRunTask.setParameterValues(discoverAndSetParameters( runnable, request ));
//create temp rpddocument
iRunTask.run(sc.getRealPath("/Reports")+"/temp.rptdocument");
iRunTask.close();
//now do the rendering operation
IReportDocument reportDoc = birtEngine.openReportDocument( sc.getRealPath("/Reports")+"/temp.rptdocument" );
IRenderTask iRenderTask= birtEngine.createRenderTask(reportDoc);
//set the format
response.setContentType( birtEngine.getMIMEType( format ));
IRenderOption options = null == this.renderOptions ? new RenderOption() : this.renderOptions;
//if html set html related options
if( format.equalsIgnoreCase("html")){
HTMLRenderOption htmlOptions = new HTMLRenderOption( options);
htmlOptions.setOutputFormat("html");
htmlOptions.setOutputStream(response.getOutputStream());
htmlOptions.setImageHandler(new HTMLServerImageHandler());
htmlOptions.setHtmlPagination(true);
htmlOptions.setBaseImageURL(baseUrl+"/images");//TODO:Change from local host to actual path
htmlOptions.setImageDirectory(sc.getRealPath("/images"));
htmlOptions.setSupportedImageFormats("PNG");
htmlOptions.setEmbeddable(true);
iRenderTask.setRenderOption(htmlOptions);
//if pdf set pdf related downloading options
}else if( format.equalsIgnoreCase("pdf") ){
PDFRenderOption pdfOptions = new PDFRenderOption( options );
pdfOptions.setSupportedImageFormats("PNG;GIF;JPG;BMP");
pdfOptions.setOutputFormat("pdf");
pdfOptions.setImageHandler(new HTMLServerImageHandler());
pdfOptions.setBaseURL(baseUrl);
//pdfOptions.setOutputFileName("my.pdf");
pdfOptions.setOption(IPDFRenderOption.PAGE_OVERFLOW, IPDFRenderOption.FIT_TO_PAGE_SIZE);
response.setHeader( "Content-Disposition", "attachment; filename="+downloadFileName );
pdfOptions.setOutputStream(response.getOutputStream());
iRenderTask.setRenderOption(pdfOptions);
//if XLS set XLS related downloading options
}else if(format.equalsIgnoreCase("xls")){
EXCELRenderOption xlsOptions = new EXCELRenderOption(options);
xlsOptions.setOutputFormat("xls");
response.setHeader( "Content-Disposition", "attachment; filename="+downloadFileName);
xlsOptions.setImageHandler(new HTMLServerImageHandler());
xlsOptions.setOutputStream(response.getOutputStream());
//xlsOptions.setOption(IRenderOption.EMITTER_ID, "org.uguess.birt.report.engine.emitter.xls");
xlsOptions.setOption(IRenderOption.EMITTER_ID, "org.eclipse.birt.report.engine.emitter.prototype.excel");
iRenderTask.setRenderOption(xlsOptions);
}else{
response.setHeader( "Content-Disposition", "attachment; filename=\"" + downloadFileName + "\"" );
options.setOutputStream(response.getOutputStream());
options.setOutputFormat(format);
iRenderTask.setRenderOption(options);
}
/*
* This is used for pagination and setting the page number we want to display
*/
long pageCount = iRenderTask.getTotalPage();
if(currentPageNumber!=0)
{
if(pageCount >=currentPageNumber){
iRenderTask.setPageNumber(currentPageNumber);
}
}
//save the page count in session to use for pagination.
//using this page count we can implement pagination.
request.getSession().setAttribute("pageCount", pageCount);
//render report
iRenderTask.render();
//close task and doc
iRenderTask.close();
reportDoc.close();
//logger.info("Processing report completed successfully:"+reportName);
}catch (Exception e) {
//logger.error("Exception while proceessing report ",e);
e.printStackTrace();
}
}
BirtEngineFactory and ReportParameterConverter classes are pretty straight forward.
Please click here to download source.
Jsp and Sample Reports
There is one Reports.jsp located in /WebContent/jsp/Reports.jsp which used for handling report loading . This is simple jsp which has left navigation div and center div. When report is selected from the left navigation it will be loaded in center div and this is an ajax call for loading report.Also download option are above the center div which allows user to download report in pdf,xls and doc format. Screen shots of jsp is in below section.
I have created two sample reports. These reports are located in /WebContent/Reports directory.
- First_Report.rptdesign (Hello World Report)
This is simple report contains one Hello world message and one image.
This report will show the details books in table and it will show pie chart of total price by book type below the table.This reports uses xml data source to load the details.The books.xml is located in /WebContent/ReportXmlDatasource/books.xml.
To locate the books.xml check the data source url is working by hitting test connection
as shown below. If it is not working then browse to the books.xm manually.
Currently url is :http://localhost:8080/BirtIntegration/ReportXmlDatasource/books.xml
Data Source window:
Screen Shot for Books Details Report: