Birt 找不到 JDBC 驱动程序

Birt cannot find JDBC driver

我正在使用 Birt 报告,它对数据库有查询。通过 JDBC.

访问数据库

生成报表时出现如下错误:

сен 01, 2017 10:54:36 AM org.eclipse.birt.data.engine.odaconsumer.Driver createNewDriverHelper(Map)
SEVERE: Cannot get ODA data source driver helper.
org.eclipse.datatools.connectivity.oda.consumer.helper.OdaHelperException: Unable to load or instantiate the custom ODA driver class. (org.eclipse.birt.report.data.oda.jdbc.OdaJdbcDriver) ;
org.eclipse.datatools.connectivity.oda.OdaException ;
    java.lang.ClassNotFoundException: org.eclipse.birt.report.data.oda.jdbc.OdaJdbcDriver
    at org.eclipse.datatools.connectivity.oda.consumer.helper.OdaDriver.loadDriverInstance(OdaDriver.java:251)
    at org.eclipse.datatools.connectivity.oda.consumer.helper.OdaDriver.init(OdaDriver.java:198)
    at org.eclipse.datatools.connectivity.oda.consumer.helper.OdaDriver.<init>(OdaDriver.java:113)
    at org.eclipse.birt.data.engine.odaconsumer.Driver.createNewDriverHelper(Driver.java:99)
    at org.eclipse.birt.data.engine.odaconsumer.DriverManager.getDriverHelper(DriverManager.java:115)
    at org.eclipse.birt.data.engine.odaconsumer.DriverManager.getNewDriverHelper(DriverManager.java:101)
    at org.eclipse.birt.data.engine.odaconsumer.ConnectionManager.openConnection(ConnectionManager.java:150)
    at org.eclipse.birt.data.engine.executor.DataSource.newConnection(DataSource.java:224)
    at org.eclipse.birt.data.engine.executor.DataSource.open(DataSource.java:212)
    at org.eclipse.birt.data.engine.impl.DataSourceRuntime.openOdiDataSource(DataSourceRuntime.java:217)
    at org.eclipse.birt.data.engine.impl.QueryExecutor.openDataSource(QueryExecutor.java:437)
    at org.eclipse.birt.data.engine.impl.QueryExecutor.prepareExecution(QueryExecutor.java:325)
    at org.eclipse.birt.data.engine.impl.PreparedQuery.doPrepare(PreparedQuery.java:463)
    at org.eclipse.birt.data.engine.impl.PreparedDataSourceQuery.produceQueryResults(PreparedDataSourceQuery.java:190)
    at org.eclipse.birt.data.engine.impl.PreparedDataSourceQuery.execute(PreparedDataSourceQuery.java:178)
    at org.eclipse.birt.data.engine.impl.PreparedOdaDSQuery.execute(PreparedOdaDSQuery.java:179)
    at org.eclipse.birt.report.data.adapter.impl.DataRequestSessionImpl.execute(DataRequestSessionImpl.java:651)
    at org.eclipse.birt.report.engine.data.dte.DteDataEngine.doExecuteQuery(DteDataEngine.java:152)
    at org.eclipse.birt.report.engine.data.dte.AbstractDataEngine.execute(AbstractDataEngine.java:286)
    at org.eclipse.birt.report.engine.executor.ExecutionContext.executeQuery(ExecutionContext.java:1947)
    at org.eclipse.birt.report.engine.executor.QueryItemExecutor.executeQuery(QueryItemExecutor.java:80)
    at org.eclipse.birt.report.engine.executor.DynamicTextItemExecutor.execute(DynamicTextItemExecutor.java:77)
    at org.eclipse.birt.report.engine.internal.executor.dup.SuppressDuplicateItemExecutor.execute(SuppressDuplicateItemExecutor.java:43)
    at org.eclipse.birt.report.engine.internal.executor.wrap.WrappedReportItemExecutor.execute(WrappedReportItemExecutor.java:46)
    at org.eclipse.birt.report.engine.internal.executor.l18n.LocalizedReportItemExecutor.execute(LocalizedReportItemExecutor.java:34)
    at org.eclipse.birt.report.engine.layout.html.HTMLBlockStackingLM.layoutNodes(HTMLBlockStackingLM.java:65)
    at org.eclipse.birt.report.engine.layout.html.HTMLPageLM.layout(HTMLPageLM.java:92)
    at org.eclipse.birt.report.engine.layout.html.HTMLReportLayoutEngine.layout(HTMLReportLayoutEngine.java:100)
    at org.eclipse.birt.report.engine.api.impl.RunAndRenderTask.doRun(RunAndRenderTask.java:181)
    at org.eclipse.birt.report.engine.api.impl.RunAndRenderTask.run(RunAndRenderTask.java:77)
    at Birt4Py.executeReport(Birt4Py.java:90)
    at EntryPoint.getStack(EntryPoint.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:244)
    at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:357)
    at py4j.Gateway.invoke(Gateway.java:280)
    at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
    at py4j.commands.CallCommand.execute(CallCommand.java:79)
    at py4j.GatewayConnection.run(GatewayConnection.java:214)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.eclipse.datatools.connectivity.oda.OdaException ;
    java.lang.ClassNotFoundException: org.eclipse.birt.report.data.oda.jdbc.OdaJdbcDriver
    at org.eclipse.datatools.connectivity.oda.consumer.helper.DriverExtensionHelper.loadDriverClass(DriverExtensionHelper.java:134)
    at org.eclipse.datatools.connectivity.oda.consumer.helper.OdaDriver.loadDriverInstance(OdaDriver.java:224)
    ... 42 more
Caused by: java.lang.ClassNotFoundException: org.eclipse.birt.report.data.oda.jdbc.OdaJdbcDriver
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Class.java:264)
    at org.eclipse.datatools.connectivity.oda.consumer.helper.DriverExtensionHelper.loadDriverClass(DriverExtensionHelper.java:130)
    ... 43 more

在这种情况下,报表本身已创建,但数据库中没有数据。

到目前为止我做了什么:

1) 下载了 Birt Framework 4.6.0 和 BIRT 运行时版本 (http://download.eclipse.org/birt/downloads/)
2) 下载 PostgreSQL JDBC 4.2 驱动程序,42.1.4 (https://jdbc.postgresql.org/)
2) 添加到目录/usr/lib/jvm/java-8-oracle/jre/lib/ext libraries

4) 已编译 java 个文件

javac Birt4Py.java
javac EntryPoint.java

5) 启动 Birt:

java EntryPoint

6) 推出 main.py

代码:

.rptdesign:

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
    <property name="createdBy">Eclipse BIRT Designer Version 4.6.0.v201606072122</property>
    <property name="units">in</property>
    <property name="iconFile">/templates/blank_report.gif</property>
    <property name="bidiLayoutOrientation">ltr</property>
    <property name="imageDPI">96</property>
    <data-sources>
        <oda-data-source extensionID="org.eclipse.birt.report.data.oda.jdbc" name="Data Source" id="4">
            <list-property name="privateDriverProperties">
                <ex-property>
                    <name>metadataBidiFormatStr</name>
                    <value>ILYNN</value>
                </ex-property>
                <ex-property>
                    <name>disabledMetadataBidiFormatStr</name>
                </ex-property>
                <ex-property>
                    <name>contentBidiFormatStr</name>
                    <value>ILYNN</value>
                </ex-property>
                <ex-property>
                    <name>disabledContentBidiFormatStr</name>
                </ex-property>
            </list-property>
            <property name="odaDriverClass">org.postgresql.Driver</property>
            <property name="odaURL">jdbc:postgresql://192.168.69.128:5432/expert</property>
            <property name="odaUser">visitor1</property>
            <encrypted-property name="odaPassword" encryptionID="base64">cXdlcnR5MTIz</encrypted-property>
        </oda-data-source>
    </data-sources>
    <data-sets>
        <oda-data-set extensionID="org.eclipse.birt.report.data.oda.jdbc.JdbcSelectDataSet" name="MyDS" id="5">
            <list-property name="columnHints">
                <structure>
                    <property name="columnName">c</property>
                    <text-property name="displayName">c</text-property>
                    <text-property name="heading">c</text-property>
                </structure>
            </list-property>
            <structure name="cachedMetaData">
                <list-property name="resultSet">
                    <structure>
                        <property name="position">1</property>
                        <property name="name">c</property>
                        <property name="dataType">decimal</property>
                    </structure>
                </list-property>
            </structure>
            <property name="dataSource">Data Source</property>
            <list-property name="resultSet">
                <structure>
                    <property name="position">1</property>
                    <property name="name">c</property>
                    <property name="nativeName">c</property>
                    <property name="dataType">decimal</property>
                    <property name="nativeDataType">-5</property>
                </structure>
            </list-property>
            <xml-property name="queryText"><![CDATA[select SUM(34) as c
]]></xml-property>
            <xml-property name="designerValues"><![CDATA[<?xml version="1.0" encoding="UTF-8"?>
<model:DesignValues xmlns:design="http://www.eclipse.org/datatools/connectivity/oda/design" xmlns:model="http://www.eclipse.org/birt/report/model/adapter/odaModel">
  <Version>2.0</Version>
  <design:ResultSets derivedMetaData="true">
    <design:resultSetDefinitions>
      <design:resultSetColumns>
        <design:resultColumnDefinitions>
          <design:attributes>
            <design:identifier>
              <design:name>c</design:name>
              <design:position>1</design:position>
            </design:identifier>
            <design:nativeDataTypeCode>-5</design:nativeDataTypeCode>
            <design:precision>19</design:precision>
            <design:scale>0</design:scale>
            <design:nullability>Unknown</design:nullability>
            <design:uiHints>
              <design:displayName>c</design:displayName>
            </design:uiHints>
          </design:attributes>
          <design:usageHints>
            <design:label>c</design:label>
            <design:formattingHints>
              <design:displaySize>20</design:displaySize>
            </design:formattingHints>
          </design:usageHints>
        </design:resultColumnDefinitions>
      </design:resultSetColumns>
      <design:criteria/>
    </design:resultSetDefinitions>
  </design:ResultSets>
</model:DesignValues>]]></xml-property>
        </oda-data-set>
    </data-sets>
    <page-setup>
        <simple-master-page name="Simple MasterPage" id="2">
            <page-footer>
                <text id="3">
                    <property name="contentType">html</property>
                    <text-property name="content"><![CDATA[<value-of>new Date()</value-of>]]></text-property>
                </text>
            </page-footer>
        </simple-master-page>
    </page-setup>
    <body>
        <text-data id="6">
            <property name="dataSet">MyDS</property>
            <list-property name="boundDataColumns">
                <structure>
                    <property name="name">c</property>
                    <text-property name="displayName">c</text-property>
                    <expression name="expression" type="javascript">dataSetRow["c"]</expression>
                    <property name="dataType">decimal</property>
                </structure>
            </list-property>
            <expression name="valueExpr">row['c'];</expression>
            <property name="contentType">html</property>
        </text-data>
    </body>
</report>

Birt4py.java

import org.apache.commons.io.output.ByteArrayOutputStream;
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.EngineException;
import org.eclipse.birt.report.engine.api.HTMLRenderOption;
import org.eclipse.birt.report.engine.api.DocxRenderOption;
import org.eclipse.birt.report.engine.api.RenderOption;
import org.eclipse.birt.report.engine.api.EXCELRenderOption;
import org.eclipse.birt.report.engine.api.HTMLServerImageHandler;
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.model.api.SessionHandle;
import java.io.FileWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.HashMap;
import java.io.*;
import java.net.URL;


public class Birt4Py {

      private static String report;
      private static IReportEngine engine = null;
      private static EngineConfig  config = null;

      public static String getReport() {
        return report;
      }

      public Birt4Py() throws BirtException {
          // start up Platform
          config = new EngineConfig( );

          Platform.startup( config );

          // create new Report Engine
          IReportEngineFactory factory = (IReportEngineFactory) Platform.createFactoryObject( IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY );
          engine = factory.createReportEngine( config );
      }

      public void executeReport(ArrayList<String> params) throws EngineException {
          /*
            Params are passed through the /sirenaApp/data_helpers/report_extractor -> get_report_file() -> my_list:
                1st: .rptdesign full path -> String
                2nd: report file full path -> String
                3rd: report extension -> String

          */

          // open the report design
          IReportRunnable design = null;
          System.out.println(params);
          design = engine.openReportDesign(params.get(0));

          // create RunandRender Task
          IRunAndRenderTask task = engine.createRunAndRenderTask(design);

          // pass necessary parameters
          task.validateParameters();

          // set render options including output type
          RenderOption options;
          if (params.get(2) == "doc") {
            options = new RenderOption();
          }
          else if (params.get(2) == "xls") {
            options = new EXCELRenderOption();
          }
          else {
            options = new HTMLRenderOption();
          }

          ByteArrayOutputStream outs = new ByteArrayOutputStream();
          options.setOutputStream(outs);
          options.setImageHandler(new HTMLServerImageHandler());

          options.setOutputFileName(params.get(1));
          options.setOutputFormat(params.get(2));
          task.setRenderOption(options);

          String output;
          task.run();
          output = outs.toString();
          task.close();
          report = output;

          System.out.println(report);

      }
}

EntryPoint.java

import org.eclipse.birt.core.exception.BirtException;
import org.eclipse.birt.report.engine.api.EngineException;

import py4j.GatewayServer;
import java.util.ArrayList;
import java.util.List;

public class EntryPoint {
  private Birt4Py birt;

  public EntryPoint() throws BirtException {
      birt  = new Birt4Py();

  }

  public Birt4Py getStack(ArrayList<String> params) throws EngineException {

      birt.executeReport(params);
      return birt;
  }

  public static void main(String[] args) throws BirtException {
      GatewayServer gatewayServer = new GatewayServer(new EntryPoint());
      gatewayServer.start();
      System.out.println("Birt4Py listener started!");
  }
}

main.py

# -*- coding: utf-8 -*-

import os
from py4j.java_gateway import JavaGateway, GatewayParameters

BIRT_PORT = 25333
BIRT_HOST = '127.0.0.1'


class BirtReport(object):

    def __init__(self, rptdesign_name, rptdesign_path):

        self.rptdesign_path = rptdesign_path
        self.rptdesign_name = rptdesign_name

    def get_report_file(self, ext, filename):
        """
        :param ext: str - file extension, i.e. .doc, .xls
        :param filename: str - filename
        :return: str - filename with extension of the resulting report
        """

        # Params passed to the Birt4Py.java report executor:
        #   1st: .rptdesign full path -> String
        #   2nd: report file full path -> String
        #   3rd: report extension -> String

        filepath = self.rptdesign_path + filename + '.' + ext
        my_list = [self.rptdesign_path + self.rptdesign_name, filepath, ext]

        try:
            gateway = JavaGateway(gateway_parameters=GatewayParameters(auto_convert=True,
                                                                       auto_field=True,
                                                                       port=BIRT_PORT,
                                                                       address=BIRT_HOST))
            gateway.entry_point.getStack(my_list)
        except Exception:
            raise

        return filepath


if __name__ == '__main__':
    rptdesign_name = 'jdbc_test.rptdesign'
    rptdesign_path = os.path.dirname(os.path.abspath(__file__)) + '/'

    birt_report = BirtReport(rptdesign_name, rptdesign_path)

    generated_file = birt_report.get_report_file('docx', 'GenerateDocxFile')
    print(generated_file)

问题:如何让 JDBC 驱动程序与 Birt 一起工作?
我的测试工程可以下载here.

谢谢Ramiz,我解决了问题。我找到文件夹

org.eclipse.birt.report.data.oda.jdbc_4.6.0.v201606072122

在 Eclipse 中并从中复制

中的所有库

/usr/lib/jvm/java-8-oracle/jre/lib/ext

复制的文件中有文件oda-jdbc.jar,其中缺少class OdaJdbcDriver