I have a BIRT report which connects to our test database. In the productive environment I would like to supply a datasource which is provided by the container through jndi.
How would I set the datasource programmatically for the given report?
...
IReportRunnable design = birtEngine.openReportDesign ( new File ( properties.getProperty ( "reportPath" ), report + ".rptdesign" ).getAbsolutePath () );
IRunAndRenderTask task = birtEngine.createRunAndRenderTask ( design );
PDFRenderOption options = new PDFRenderOption ();
options.setOutputFormat ( PDFRenderOption.OUTPUT_FORMAT_PDF );
options.setOutputStream ( out );
task.setRenderOption ( options );
for ( Entry<String, Object> entry : parameters.entrySet () )
{
task.setParameterValue ( entry.getKey (), entry.getValue () );
}
task.run ();
task.close ();
...
I guess I would have to modify the design
but on the other hand task
has a method setDataSource
but that looks a bit like I would have to supply some xml dom elements.
Look at following code you may get some help in providing data source at runtime.
For my requirements it works fine.
I got this from some site do not remember.
import java.io.IOException;
import java.util.ArrayList;
import org.eclipse.birt.core.framework.Platform;
import org.eclipse.birt.report.model.api.CellHandle;
import org.eclipse.birt.report.model.api.DataItemHandle;
import org.eclipse.birt.report.model.api.DesignConfig;
import org.eclipse.birt.report.model.api.ElementFactory;
import org.eclipse.birt.report.model.api.IDesignEngine;
import org.eclipse.birt.report.model.api.IDesignEngineFactory;
import org.eclipse.birt.report.model.api.LabelHandle;
import org.eclipse.birt.report.model.api.OdaDataSetHandle;
import org.eclipse.birt.report.model.api.OdaDataSourceHandle;
import org.eclipse.birt.report.model.api.PropertyHandle;
import org.eclipse.birt.report.model.api.ReportDesignHandle;
import org.eclipse.birt.report.model.api.RowHandle;
import org.eclipse.birt.report.model.api.SessionHandle;
import org.eclipse.birt.report.model.api.StructureFactory;
import org.eclipse.birt.report.model.api.TableHandle;
import org.eclipse.birt.report.model.api.activity.SemanticException;
import org.eclipse.birt.report.model.api.elements.structures.ComputedColumn;
import com.ibm.icu.util.ULocale;
/**
* Dynamic Table BIRT Design Engine API (DEAPI) demo.
*/
public class DECreateDynamicTable
{
ReportDesignHandle designHandle = null;
ElementFactory designFactory = null;
StructureFactory structFactory = null;
public static void main( String[] args )
{
try
{
DECreateDynamicTable de = new DECreateDynamicTable();
ArrayList al = new ArrayList();
al.add("USERNAME");
al.add("COUNTRY");
de.buildReport(al, "From GTM_REPORT_APP_USER" );
}
catch ( IOException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch ( SemanticException e )
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
void buildDataSource( ) throws SemanticException
{
OdaDataSourceHandle dsHandle = designFactory.newOdaDataSource(
"Data Source", "org.eclipse.birt.report.data.oda.jdbc" );
dsHandle.setProperty( "odaDriverClass",
"oracle.jdbc.driver.OracleDriver" );
dsHandle.setProperty( "odaURL", "jdbc:oracle:thin:@xeon:1521:ora9i" );
dsHandle.setProperty( "odaUser", "AIMS_GTMNE" );
dsHandle.setProperty( "odaPassword", "AIMS_GTMNE" );
designHandle.getDataSources( ).add( dsHandle );
}
void buildDataSet(ArrayList cols, String fromClause ) throws SemanticException
{
OdaDataSetHandle dsHandle = designFactory.newOdaDataSet( "ds",
"org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" );
dsHandle.setDataSource( "Data Source" );
String qry = "Select ";
for( int i=0; i < cols.size(); i++){
qry += " " + cols.get(i);
if( i != (cols.size() -1) ){
qry += ",";
}
}
qry += " " + fromClause;
dsHandle.setQueryText( qry );
designHandle.getDataSets( ).add( dsHandle );
}
void buildReport(ArrayList cols, String fromClause ) throws IOException, SemanticException
{
//Configure the Engine and start the Platform
DesignConfig config = new DesignConfig( );
config.setProperty("BIRT_HOME", "D:/Softwares/Frame Works - APIs-Tools/birt-runtime-2_6_1/birt-runtime-2_6_1/ReportEngine");
IDesignEngine engine = null;
try{
Platform.startup( config );
IDesignEngineFactory factory = (IDesignEngineFactory) Platform.createFactoryObject( IDesignEngineFactory.EXTENSION_DESIGN_ENGINE_FACTORY );
engine = factory.createDesignEngine( config );
}catch( Exception ex){
ex.printStackTrace();
}
SessionHandle session = engine.newSessionHandle( ULocale.ENGLISH ) ;
try{
//open a design or a template
designHandle = session.openDesign("D:/tempBirtReport/test.rptdesign");
designFactory = designHandle.getElementFactory( );
buildDataSource();
buildDataSet(cols, fromClause);
TableHandle table = designFactory.newTableItem( "table", cols.size() );
table.setWidth( "100%" );
table.setDataSet( designHandle.findDataSet( "ds" ) );
PropertyHandle computedSet = table.getColumnBindings( );
ComputedColumn cs1 = null;
for( int i=0; i < cols.size(); i++){
cs1 = StructureFactory.createComputedColumn();
cs1.setName((String)cols.get(i));
cs1.setExpression("dataSetRow[\"" + (String)cols.get(i) + "\"]");
computedSet.addItem(cs1);
}
// table header
RowHandle tableheader = (RowHandle) table.getHeader( ).get( 0 );
for( int i=0; i < cols.size(); i++){
LabelHandle label1 = designFactory.newLabel( (String)cols.get(i) );
label1.setText((String)cols.get(i));
CellHandle cell = (CellHandle) tableheader.getCells( ).get( i );
cell.getContent( ).add( label1 );
}
// table detail
RowHandle tabledetail = (RowHandle) table.getDetail( ).get( 0 );
for( int i=0; i < cols.size(); i++){
CellHandle cell = (CellHandle) tabledetail.getCells( ).get( i );
DataItemHandle data = designFactory.newDataItem( "data_"+(String)cols.get(i) );
data.setResultSetColumn( (String)cols.get(i));
cell.getContent( ).add( data );
}
designHandle.getBody( ).add( table );
// Save the design and close it.
designHandle.saveAs( "D:/tempBirtReport/test.rptdesign" ); //$NON-NLS-1$
designHandle.close( );
System.out.println("Finished");
}catch (Exception e){
e.printStackTrace();
}
}
}
You can create a Report Parameter for the database connection string.
Then, set the JNDI URL under Data Source -> Property Binding -> JNDI URL, as: params["Database"].value
(Where "Database" is the name of the report parameter)
Setting just the data source at run-time will be problematic because the data set is bound to a single data source and your controls on the report are then bound to a specific data set. This hierarchy would be pretty sticky to try and build yourself each time the report runs.
You can parameterize all aspects of the Data Source definition making your design portable through all environments. When editing your Data Source, look at the Property Binding grouping on the left hand side. This should give you ample flexibility to make your data source more portable. You can specify run-time parameters for JDBC URL elements or a run-time JNDI profile.
Hope this helps.
I like Adams approach.
Here's how we do it:
/*
* Change the data sources in the .rptdesign
*/
void changeDataSource(ElementFactory designFactory,
ReportDesignHandle designHandle, String userConnect)
throws SemanticException {
SlotHandle datasources = designHandle.getDataSources();
SlotIterator iter = (SlotIterator) datasources.iterator();
while (iter.hasNext()) {
DesignElementHandle dsHandle = (DesignElementHandle) iter.next();
if (dsHandle instanceof OdaDataSourceHandle && dsHandle.getName().equals("lisa")) {
log.debug("changeDataSource: Changing datasource "
+ dsHandle.getName() + " new url=" + getLisaDbUrl());
dsHandle.setProperty("odaDriverClass",
"oracle.jdbc.driver.OracleDriver");
dsHandle.setProperty("odaURL", getLisaDbUrl());
dsHandle.setProperty("odaUser", getLisaUser());
dsHandle.setProperty("odaPassword", getLisaPassword());
} else {
log.debug("changeDataSource: Ignoring DS " + dsHandle.getName());
}
}
}
Here, "lisa" ist he name of the datasource we would like to change at runtime.
The get... function return the values needed at "production" run time.
This worked for me. I got the context and from context got the dataSource and passed the connection to Birt report like below
Context initialContext = new InitialContext();
if ( initialContext == null){
System.out.println("JNDI problem. Cannot get InitialContext.");
}
DataSource datasource = (DataSource)initialContext.lookup("java:/datasources/SAMPLE");
task.getAppContext().put("OdaJDBCDriverPassInConnection", datasource.getConnection());