在 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>
现在一切正常!
这是我第一次使用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>
现在一切正常!