Как программно установить источник данных для отчета BIRT?

У меня есть отчет BIRT, который подключается к нашей тестовой базе данных. В продуктивной среде я хотел бы предоставить источник данных, который предоставляется контейнером через jndi.

Как я могу установить программный источник данных для данного отчета?

    ...
    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 ();
    ...

Думаю, мне пришлось бы изменить design, но, с другой стороны, task имеет метод setDataSource, но это немного похоже на то, что я должен был бы предоставить некоторые элементы xml dom.

Ответ 1

Посмотрите на следующий код, вы можете получить некоторую помощь в предоставлении источника данных во время выполнения.

По моим требованиям он отлично работает.

Я получил это с какого-то сайта, не помню.

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();
        }       

    }
 }

Ответ 2

Вы можете создать параметр отчета для строки подключения к базе данных.

Затем установите URL-адрес JNDI в разделе Источник данных → Связывание свойств → URL-адрес JNDI, как: params [ "Database" ]. Значение
(Где "База данных" - это имя параметра отчета)

Ответ 3

Настройка источника данных во время выполнения будет проблематичной, поскольку набор данных привязан к одному источнику данных, а ваши элементы управления в отчете привязаны к определенному набору данных. Эта иерархия была бы довольно липкой, чтобы пытаться строить себя каждый раз, когда отчет запускается.

Вы можете параметризовать все аспекты определения источника данных, делая ваш дизайн переносимым во всех средах. При редактировании источника данных просмотрите группировку свойств с левой стороны. Это должно дать вам достаточную гибкость, чтобы сделать ваш источник данных более переносимым. Вы можете указать параметры времени выполнения для элементов URL JDBC или профиля JNDI во время выполнения.

Надеюсь, что это поможет.

Ответ 4

Мне нравится подход Адамса. Вот как мы это делаем:

    /*
 * 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());
        }
    }
}

Здесь "lisa" - это имя источника данных, который мы хотели бы изменить во время выполнения. Функция get... возвращает значения, необходимые для "производственного" времени выполнения.

Ответ 5

Это сработало для меня. Я получил контекст и из контекста получил dataSource и передал соединение с сообщением Birt, как показано ниже

  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());