在 tomcat 下使用 POJO 的 BIRT 报告

BIRT Report using POJOs unning under tomcat

这是我第一次使用BIRT引擎。我专注于使用 POJO 的问题。

我有简单的 POJO:

class Parent {
  private String name;
  public void setName(String name) {
     this.name = name;
  }

  public String getName() {
    return name;
  }
}

以及仅打印 Parent 名称的简单 BIRT 报告(我仅打印 1 Parent 的名称,这意味着 - 我仅发送包含 1 条记录的列表)。

我使用 JUnit 测试成功生成了名称为 Parent 的 PDF,而当我尝试在 Tomcat 中生成它时 - BIRT 不会从 POJO 插入值。

你关注过这个问题吗?

Birt 包装器 class:

public class BirtRenderer implements IBirtRenderer {

    private EngineConfig config;
    private IReportEngine engine;
    private IReportEngineFactory factory;

    public BirtRenderer() throws BirtException {
        config = new EngineConfig();
        config.setLogConfig("J:\BirtLogs", Level.WARNING);

        // config.setLogger(new Log4jHandler());

        Platform.startup(config);

        factory = (IReportEngineFactory) Platform.createFactoryObject(IReportEngineFactory.EXTENSION_REPORT_ENGINE_FACTORY);
        engine = factory.createReportEngine(config);
    }

    public void destroy() {
        engine.destroy();
        Platform.shutdown();
    }

    public ByteArrayOutputStream executeReport(String reportName, String fileFormat, @SuppressWarnings("rawtypes") Map context) throws EngineException {
        return executeReport(reportName, fileFormat, context, Locale.US);
    }

    public ByteArrayOutputStream executeReport(String reportName, String fileFormat, @SuppressWarnings("rawtypes") Map context, Locale locale) throws EngineException {

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();

        reportName = reportName + ".rptdesign";

        /* for testing */
        context = new HashMap();
        ArrayList list = new ArrayList();
        list.add(new TitleCustomerDao().next());
        context.put("APP_CONTEXT_KEY_TITLE_CUSTOMER_DATA", list);
        /* for testing end */

        InputStream reportStream = this.getClass().getClassLoader().getResourceAsStream(reportName);

        if (reportStream == null)
            throw new EngineException(new BirtException("File '" + reportName + "' was not found."));

        // Open the report design
        IReportRunnable design = null;
        // design =
        // engine.openReportDesign("J:/birt-workspace/test/hello_world.rptdesign");
        design = engine.openReportDesign(reportStream);
        IRunAndRenderTask task = engine.createRunAndRenderTask(design);
        // task.setParameterValue("Top Count", (new Integer(5)));
        // task.validateParameters();

        RenderOption renderOption = getRenderOption(fileFormat);
        renderOption.setOutputStream(outputStream);

        task.setRenderOption(renderOption);
        // task.setParameterValue("APP_CONTEXT_KEY_PARENTS", data);
        task.setAppContext(context);
        if (locale != null)
            task.setLocale(locale);

        if (!task.validateParameters()) {
            throw new IllegalArgumentException("Parameters do not validate");
        }

        task.run();
        task.close();

        return outputStream;
    }

    private RenderOption getRenderOption(String fileFormat) {
        if (fileFormat.equalsIgnoreCase("pdf")) {
            PDFRenderOption PDF_OPTIONS = new PDFRenderOption();
            // PDF_OPTIONS.setOutputFileName("J:/birt-workspace/test/hello_world.pdf");
            PDF_OPTIONS.setOutputFormat("pdf");

            return PDF_OPTIONS;
        } else if (fileFormat.equalsIgnoreCase("html")) {
            HTMLRenderOption HTML_OPTIONS = new HTMLRenderOption();
            // HTML_OPTIONS.setOutputFileName("J:/birt-workspace/test/hello_world.html");
            HTML_OPTIONS.setOutputFormat("html");

            return HTML_OPTIONS;
        } else
            return null;

    }

}

经过长时间的排查,我发现问题出在哪里。

问题是我在使用 BIRT 的同一个 Web 项目中使用 Apache FOP 库。 如果我们深入细节——问题出在 Apache Batik 库上,它被 Apache FOP 1.0(使用 >=1.7 Batik)和 BIRT 4.4.2(使用 1.6)使用。

而且很奇怪为什么 BIRT Runtime Java 库里面覆盖了 Batik groupIds 和 artifacts。

您有什么建议可以在同一 Web 项目中使用 Apache FOP 和 BIRT 4.4.2 运行时 Java 库吗?​​

这也取决于,你在上面指定了哪个依赖项。

使用这个POM.XML PDF 报告生成成功,所有 POJO 数据都正确绑定:

<dependency>
<groupId>org.eclipse.birt.runtime</groupId>
<artifactId>org.eclipse.birt.runtime</artifactId>
<version>4.4.2</version>
</dependency>

<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>fop</artifactId>
<version>1.0</version>
</dependency>

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

使用此 POM.XML PDF 报告呈现空 POJO 数据字段:

     <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>fop</artifactId>
        <version>1.0</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.eclipse.birt.runtime</groupId>
        <artifactId>org.eclipse.birt.runtime</artifactId>
        <version>4.4.2</version>
    </dependency>

我认为您的 POJO 在 Tomcat 中不起作用,因为您忘记为 BIRT 引擎提供类加载器。尝试添加:

import org.eclipse.birt.report.engine.api.EngineConstants;

在你的构造函数中:

config.getAppContext().put(EngineConstants.APPCONTEXT_CLASSLOADER_KEY, BirtRenderer.class.getClassLoader());

好的,我发现了一个问题

问题出在 Java 库上。 Apache FOP 使用的是 Apache Batik,它有一个神器 batik-js。这是一个瓶颈,因为 BIRT 运行时库使用较新的版本。

很难找到问题,因为 BIRT Runtime 使用 "org.mozilla.javascript-1.7.2.jar" 而 FOP 使用 "batik-js-1.7.jar"。它们都存储相同的 Java 类。

所以Java当我们在TOP上指定FOP依赖时,ClassLoader采用旧版本(FOP版本)的jar。

这仍然是一个问题 - 为什么 BIRT 运行时开发人员创建具有相同 Java 类 的不同 Maven 工件。

所以我的新 pom.xml 是:

    <dependency>
        <groupId>org.apache.xmlgraphics</groupId>
        <artifactId>fop</artifactId>
        <version>1.0</version>
        <exclusions>
            <exclusion>
                <artifactId>batik-js</artifactId>
                <groupId>org.apache.xmlgraphics</groupId>
            </exclusion>
        </exclusions>
    </dependency>

     <dependency>
        <groupId>org.eclipse.birt.runtime</groupId>
        <artifactId>org.eclipse.birt.runtime</artifactId>
        <version>4.4.2</version>
    </dependency>

现在一切正常!