Wednesday, July 12, 2006

BIRT: Java Program Using BIRT API's to Run a Simple Report

My last article showed how to set up BIRT scheduled tasks without any programming. In this article I will demonstrate the same thing, however the report launching will be done from within a Java program. This demonstrates how to use the BIRT API’s to open, launch a report, and save to a specified location. The output location has been changed to C:\Temp instead of the working directory. Information about using the BIRT API’s was obtained from the BIRT Integration Tutorial. The Source Code is below:

package viewtest2;

import java.util.HashMap;
import org.eclipse.birt.report.engine.api.*;

public class viewtest2 {

     public static void main(String[] args) {
          //Variables used to control BIRT Engine instance
          EngineConfig conf = null;
          ReportEngine eng = null;
          IReportRunnable design = null;
          IRunAndRenderTask task = null;
          HTMLRenderContext renderContext = null;
          HashMap contextMap = null;
          HTMLRenderOption options = null;
          
          //Now, setup the BIRT engine configuration. The Engine Home is hardcoded
          //here, this is probably better set in an environment variable or in
          //a configuration file. No other options need to be set
          conf = new EngineConfig();
          conf.setEngineHome("C:/birt_runtime/birt-runtime-2_1_0/ReportEngine");
          
          //Create new Report engine based off of the configuration
          eng = new ReportEngine( conf );
          
          //With our new engine, lets try to open the report design
          try
          {
               design = eng.openReportDesign("C:/birt_runtime/birt-runtime-2_1_0/ReportEngine/samples/hello_world.rptdesign");
          }
          catch (Exception e)
          {
               System.err.println("An error occured during the opening of the report file!");
               e.printStackTrace();
               System.exit(-1);
          }
          
          //With the file open, create the Run and Render task to run the report
          task = eng.createRunAndRenderTask(design);
          
          //Set Render context to handle url and image locataions, and apply to the
          //task
          renderContext = new HTMLRenderContext();
          renderContext.setImageDirectory("image");
          contextMap = new HashMap();
          contextMap.put( EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, renderContext );
          task.setAppContext( contextMap );

          //This will set the output file location, the format to rener to, and
          //apply to the task
          options = new HTMLRenderOption();
          options.setOutputFileName("c:/temp/output.html");
          options.setOutputFormat("html");
          task.setRenderOption(options);
          
          //Cross our fingers and hope everything is set
          try
          {
               task.run();
          }
          catch (Exception e)
          {
               System.err.println("An error occured while running the report!");
               e.printStackTrace();
               System.exit(-1);
          }
          
          //Yeah, we finished. Now destroy the engine and let the garbage collector
          //do its thing
          System.out.println("All went well. Closing program!");
          eng.destroy();
     }
}

The next step after this would be to parameterize the input file, output file, and output format. Then this program could be used for any report, not just this specific report. I intend to build on this example a little more, and possibly use the parameters to specify a configuration file that will be built in XML and use Apache Xerces (or, in Java 1.5, the XML components that are now included with the standard Java libraries). However, since the Xerces components are already included with the BIRT Runtime libraries, I am leaning more towards using those.

14 comments:

Confused with BIRT said...

I can't initiate the reportengine class. I am wondering how you configure your library file or environment.

John Ward said...

I have it setup this way:

I have the BIRT Runtime library setup under C:\birt_runtime\birt-runtime-2_1_0

As for my project, under Eclipse, go to the Project Explorer, right-mouse click on properties for the project, go to Java Build path, Click on the External Jars button, then select all the libraries under C:\birt_runtime\birt-runtime-2_1_0\ReportEngine\lib\ folder.

Now, there is alternative way to create a ReportEngine class using factories, which Actuate recommends since creating an instance of the Reportengine class is costly. I used the method I did above since I was only using 1 instance of the class.

If I were to use the Factory method as outlined by the BIRT group, I would change my example above to something like:

package f;

import java.util.HashMap;
import org.eclipse.birt.report.engine.api.*;
//Added the Platform import to create factories
import org.eclipse.birt.core.framework.Platform;

public class d {

public static void main(String[] args) {
//Variables used to control BIRT Engine instance
EngineConfig conf = null;
IReportEngine eng = null;
IReportRunnable design = null;
IRunAndRenderTask task = null;
HTMLRenderContext renderContext = null;
HashMap contextMap = null;
HTMLRenderOption options = null;


//Now, setup the BIRT engine configuration. The Engine Home is hardcoded
//here, this is probably better set in an environment variable or in
//a configuration file. No other options need to be set
conf = new EngineConfig();
conf.setEngineHome("C:/birt_runtime/birt-runtime-2_1_0/ReportEngine");

//Create new Report engine based off of the configuration
//removed to show starting using the Platform
//eng = new ReportEngine( conf );


//With our new engine, lets try to open the report design
try
{
//Startup the platform, and load any plugins
Platform.startup(conf);

//Create a report engine factory and create an instance of the ReportEngine using the IReportEngine interface
IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );
eng = factory.createReportEngine( conf );

//Open the design
design = eng.openReportDesign("C:\\birt_runtime\\birt-runtime-2_1_0\\ReportEngine\\samples\\hello_world.rptdesign");
}
catch (Exception e)
{
System.err.println("An error occured during the opening of the report file!");
e.printStackTrace();
System.exit(-1);
}

//With the file open, create the Run and Render task to run the report
task = eng.createRunAndRenderTask(design);

//Set Render context to handle url and image locataions, and apply to the
//task
renderContext = new HTMLRenderContext();
renderContext.setImageDirectory("image");
contextMap = new HashMap();
contextMap.put( EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT, renderContext );
task.setAppContext( contextMap );

//This will set the output file location, the format to rener to, and
//apply to the task
options = new HTMLRenderOption();
options.setOutputFileName("c:/temp/output.html");
options.setOutputFormat("html");
task.setRenderOption(options);

//Cross our fingers and hope everything is set
try
{
task.run();
}
catch (Exception e)
{
System.err.println("An error occured while running the report!");
e.printStackTrace();
System.exit(-1);
}

//Yeah, we finished. Now destroy the engine and let the garbage collector
//do its thing
System.out.println("All went well. Closing program!");
eng.destroy();
}
}

Sorry for the lack of formatting, Blogger seemed to strip it out. But see http://www.eclipse.org/birt/phoenix/deploy/reportEngineAPI.php and http://wiki.eclipse.org/index.php/Simple_Execute for more info.

Hope that helps.

zaratin said...

Hello John,
I have the following error using factory example (using BIRT 2.1.1 on Eclipse 3.2.1):

Exception in thread "main" java.lang.NoClassDefFoundError: org/mozilla/javascript/Scriptable
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory.createReportEngine(ReportEngineFactory.java:13)
at viewtest2.viewtest2.main(viewtest2.java:40)


Could you give me a hint? Many thanks...

John Ward said...

Zaratin,

You getting this error since, for some reasaon, it cannot instantiate the report engine. Check to make sure that you have the correct paths at lines 22 and 30. I have these set to where I have the BIRT Runtime extracted. Also make sure you have included all the JARs under the Report Engine directory in your BIRT Runtime folder in your Eclipse project. I have found that selective package inclusion leads to issues, so out of habit I typically just include all of them.

en said...

Thanks for the example John. I found it very helpful.

HTMLRenderContext is now deprecated so setImageDirectory is available on HTMLRenderOption instead.

kiranpv said...

Hello,
I am trying to run a simple BIRT report with ur java prog. (note: it is not a servlet or web app).
It is giving me this the below error. Please , please help me on this or mail me the solution at kiran.vaidya@gmail.com.

Thanks in advance
-Kiran

The error is:

org.eclipse.birt.report.engine.api.ReportEngine
SEVERE: Cant startup the OSGI framework
org.eclipse.birt.core.exception.BirtException: Cant startup the OSGI framework
at org.eclipse.birt.core.framework.Platform.startup(Platform.java:91)
at org.eclipse.birt.report.engine.api.ReportEngine.(ReportEngine.java:59)
at org.eclipse.birt.demo.viewtest2.main(viewtest2.java:31)
Caused by: org.eclipse.birt.core.exception.CoreException
at org.eclipse.birt.core.framework.osgi.OSGILauncher.startup(OSGILauncher.java:90)
at org.eclipse.birt.core.framework.Platform.startup(Platform.java:79)
... 2 more
Can't load the report engine
An error occured during the opening of the report file!
java.lang.NullPointerException
at org.eclipse.birt.report.engine.api.ReportEngine.openReportDesign(ReportEngine.java:126)
at org.eclipse.birt.demo.viewtest2.main(viewtest2.java:36)

Vijay V said...

Check if the line "conf.setEngineHome("C:/birt_runtime/birt-runtime-2_1_0/ReportEngine")" is pointing to the right location on your machine.

suku said...

Hi John,

I tried with the sample example you have posted its working fine...But when i tried to use the report designed by me which contains oracle database connectivity.My design contains one table and a pie chart which access data from the oracle database.I am getting the following error when i tried to view it as html file.

The following items have errors:

Table (id = 9):
+ An exception occurred during processing. Please see the following message for details:
Cannot open the connection for the driver: org.eclipse.birt.report.data.oda.jdbc.
Cannot load JDBC Driver class: oracle.jdbc.driver.OracleDriver.

Chart (id = 28):
+ An exception occurred during processing. Please see the following message for details:
Cannot open the connection for the driver: org.eclipse.birt.report.data.oda.jdbc.
Cannot load JDBC Driver class: oracle.jdbc.driver.OracleDriver.

I just changed the report design in the example qupted by you...

Please help me out

srik said...

Hi ,
I used the same code as above & changed the path of Runtime but i am getting this error if i run as a java program
Exception in thread "main" java.lang.NoClassDefFoundError: org/eclipse/core/runtime/CoreException
at org.eclipse.birt.report.engine.api.impl.ReportEngine.(ReportEngine.java:105)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory$1.run(ReportEngineFactory.java:18)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory$1.run(ReportEngineFactory.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory.createReportEngine(ReportEngineFactory.java:14)
at org.eclipse.birt.report.engine.api.ReportEngine.(ReportEngine.java:71)
at com.tecnotree.mdx.product.utils.ExampleReport.main(ExampleReport.java:29)

Please help me regarding this,....

Thanks

srik said...

Hi,

I am getting NullPointerException while creating the report engine.But i am passing EngineHome & logConfig to the ReportEngine.

This is my Code..

package com.tecnotree.mdx.product.utils;

import java.util.HashMap;
import java.util.logging.Level;

import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.engine.api.EngineConfig;
import org.eclipse.birt.report.engine.api.EngineConstants;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.IReportEngine;
import org.eclipse.birt.report.engine.api.IReportEngineFactory;
import org.eclipse.birt.report.engine.api.IReportRunnable;
import org.eclipse.birt.report.engine.api.IRunAndRenderTask;
import org.eclipse.birt.report.engine.api.ReportEngine;


public class ExampleReport {

public static void main(String[] args) {
// Variables used to control BIRT Engine instance
EngineConfig conf = null;
ReportEngine eng = null;
IReportRunnable design = null;
IRunAndRenderTask task = null;
HTMLRenderOption renderContext = null;
HashMap contextMap = null;
HTMLRenderOption options = null;
conf = new EngineConfig();
conf
.setEngineHome("C:\\birt-runtime-2_5_2\\birt-runtime-2_5_2\\ReportEngine");
System.out.println("conf " + conf.getBIRTHome());

conf.setLogConfig("C:\\temp", Level.FINE);
try {
Platform.startup(conf);
} catch (BirtException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
IReportEngineFactory factory = (IReportEngineFactory) Platform
.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );
System.out.println("Factory : " + factory);
System.out.println(conf.toString());
IReportEngine engine = factory.createReportEngine( conf );
System.out.println("Engine : " + engine);


try {
design = eng
.openReportDesign("D:\\birt-runtime-2_5_2\\birt-runtime-2_5_2\\ReportEngine\\samples\\hello_world.rptdesign");
} catch (Exception e) {
System.err
.println("An error occured during the opening of the report file!");
e.printStackTrace();
System.exit(-1);
}
task = eng.createRunAndRenderTask(design);
renderContext = new HTMLRenderOption();
renderContext.setImageDirectory("image");
contextMap = new HashMap();
contextMap.put(EngineConstants.APPCONTEXT_HTML_RENDER_CONTEXT,
renderContext);
task.setAppContext(contextMap);

options = new HTMLRenderOption();
options.setOutputFileName("c:/temp/output.html");
options.setOutputFormat("html");
task.setRenderOption(options);
try {
task.run();
} catch (Exception e) {
System.err.println("An error occured while running the report!");
e.printStackTrace();
System.exit(-1);
}
System.out.println("All went well. Closing program!");
eng.destroy();

}
}


STACKTRACE :


Exception in thread "main" java.lang.NullPointerException
at org.eclipse.birt.report.engine.api.impl.ReportEngine$EngineExtensionManager.(ReportEngine.java:794)
at org.eclipse.birt.report.engine.api.impl.ReportEngine.(ReportEngine.java:105)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory$1.run(ReportEngineFactory.java:18)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory$1.run(ReportEngineFactory.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory.createReportEngine(ReportEngineFactory.java:14)
at com.tecnotree.mdx.product.utils.ExampleReport.main(ExampleReport.java:45)

Please help me ...............

Thanks in Advance.....

subba said...

Hi,
We have used the code provided by you. We have a .rptdesign file with some tables, images and text. The problem is when we try to generate a pdf for this using the code provided by you..we are able to get the file created at the specified location but the content is blank inside the pdf. What is the problem??

raghul said...

I used this code. HTMLRenderConext is deprecated.
What class is used instead.
Also while launching the application there is an error.
The project: org.eclipse.birt.report.engine which is referenced by the classpath, does not exist.
And there is a red exclamation on the project in the project explorer.

Anonymous said...

thanks dudu...

successfully run the code.

Akshay R P said...

Hi,

I am using the code changed the runtime to 4.3 now getting an error

Exception in thread "main" java.lang.NoSuchMethodError: org.eclipse.birt.report.engine.api.EngineConfig.getLogRollingSize()I
at org.eclipse.birt.report.engine.api.impl.ReportEngine.intializeLogger(ReportEngine.java:220)
at org.eclipse.birt.report.engine.api.impl.ReportEngine.(ReportEngine.java:134)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory$1.run(ReportEngineFactory.java:18)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory$1.run(ReportEngineFactory.java:1)
at java.security.AccessController.doPrivileged(Native Method)
at org.eclipse.birt.report.engine.api.impl.ReportEngineFactory.createReportEngine(ReportEngineFactory.java:14)
at org.eclipse.birt.report.engine.api.ReportEngine.(ReportEngine.java:71)
at com.pg.o2.test.synch.ReportTest.main(ReportTest.java:33)