如何用Java打开基于HANA DB的CR报告

问题描述 投票:0回答:1

我一直在尝试使用 SAP Crystal Report java 库打开 CR 报告,但我遇到了一个巨大的问题。

第一次实现我的代码后,我遇到了这样的异常:

com.crystaldecisions.sdk.occa.report.lib.ReportSDKException:查找 JNDI 名称(THENAME)时出错----错误代码:-2147467259 错误代码名称:失败

然后,我按照此链接给出的解决方案进行操作:如何将 JNDI 添加到 Crystal Report bean?

虽然所有执行的步骤看起来都正常,并且不知何故报告已正确加载,但最终它总是陷入此异常:

com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: Unexpected ValueType: ValueType=[255]
---- Error code:-2147467259 Error code name:failed
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.if(SourceFile:740)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.a(SourceFile:166)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter$2.a(SourceFile:528)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter$2.call(SourceFile:526)
    at com.crystaldecisions.reports.common.ThreadGuard.syncExecute(SourceFile:102)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.for(SourceFile:524)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.int(SourceFile:423)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.request(SourceFile:351)
    at com.businessobjects.sdk.erom.jrc.a.a(SourceFile:54)
    at com.businessobjects.sdk.erom.jrc.a.execute(SourceFile:67)
    at com.crystaldecisions.proxy.remoteagent.RemoteAgent$a.execute(SourceFile:716)
    at com.crystaldecisions.proxy.remoteagent.CommunicationChannel.a(SourceFile:125)
    at com.crystaldecisions.proxy.remoteagent.RemoteAgent.a(SourceFile:537)
    at com.crystaldecisions.sdk.occa.report.application.ds.a(SourceFile:186)
    at com.crystaldecisions.sdk.occa.report.application.an.a(SourceFile:108)
    at com.crystaldecisions.sdk.occa.report.application.b0.if(SourceFile:148)
    at com.crystaldecisions.sdk.occa.report.application.b0.b(SourceFile:95)
    at com.crystaldecisions.sdk.occa.report.application.bb.int(SourceFile:96)
    at com.crystaldecisions.proxy.remoteagent.UndoUnitBase.performDo(SourceFile:151)
    at com.crystaldecisions.proxy.remoteagent.UndoUnitBase.a(SourceFile:106)
    at com.crystaldecisions.sdk.occa.report.application.DatabaseController.a(SourceFile:2159)
    at com.crystaldecisions.sdk.occa.report.application.DatabaseController.a(SourceFile:543)
    at com.crystaldecisions.sdk.occa.report.application.DatabaseController.a(SourceFile:3898)
    at com.crystaldecisions.sdk.occa.report.application.DatabaseController.setTableLocation(SourceFile:2906)
    at it.fortresslab.reportmanager.launcher.ReportLauncherTest.shouldLaunchReportToo(ReportLauncherTest.java:65)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:727)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:156)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:147)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:86)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(InterceptingExecutableInvoker.java:103)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.lambda$invoke$0(InterceptingExecutableInvoker.java:93)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:92)
    at org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.invoke(InterceptingExecutableInvoker.java:86)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:217)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:213)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:138)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:68)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:147)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:127)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:90)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:55)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:102)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
    at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: java.lang.IllegalArgumentException: Unexpected ValueType: ValueType=[255]
    at com.crystaldecisions.reports.common.Utils.a(SourceFile:97)
    at com.crystaldecisions.reports.common.Utils.a(SourceFile:151)
    at com.businessobjects.reports.sdk.builder.ConnectionDatabaseBuilder.a(SourceFile:275)
    at com.businessobjects.reports.sdk.builder.ConnectionDatabaseBuilder.a(SourceFile:357)
    at com.businessobjects.reports.sdk.builder.EROMDatabaseBuilder.a(SourceFile:185)
    at com.businessobjects.reports.sdk.requesthandler.DatabaseRequestHandler.byte(SourceFile:1112)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.do(SourceFile:1166)
    at com.businessobjects.reports.sdk.JRCCommunicationAdapter.if(SourceFile:660)
    ... 95 more

请记住,我的代码与上面链接中的示例完全相同,执行以下行时会引发异常:

clientDoc.getDatabaseController().setTableLocation(table, table);

知道“Unexpected ValueType: ValueType=[255]”是什么意思吗?

有关我的运行时环境的一些信息

  • 我尝试打开的报表是使用 SAP Crystal Report 2016 版本 14.2.5.26.18 制作的
  • jdbc驱动程序是ngdbc-2.17.12
  • 代码是使用 Java 11(Amazon Corretto 版本 11.0.19.7.1)构建和启动的。

任何帮助将不胜感激。谢谢。

java crystal-reports hana
1个回答
1
投票

经过一番努力后,我很高兴告诉大家我终于成功了。 我将分享如何操作的快速指南。

先决条件

  1. 报告中的数据库连接必须通过“JDBC (JNDI)”完成。甚至不要尝试使用 ODBC、ADO 或任何其他任何类型的数据源。请记住,您将使用 Java 打开报告,根据定义,Java 确实使用 JDBC 驱动程序。另外,不要忘记必须配置所有子报告
  2. 如果您决定使用其他数据源类型,请不要尝试以编程方式更改为 JDBC。我看到了一些教程或文章,即使在这个平台上,它也不起作用。特别是,当您需要处理包含多个子报表的复杂报表时,实现起来并不容易,更糟糕的是,速度非常慢。因此,我建议您甚至不要尝试采用这种方法
  3. 确保 Crystal Report 加载并使用 HANA 的 JDBC 驱动程序,该驱动程序通常随 SAP 一起分发,或者您可以在网上找到它。驱动程序的jar必须在CRReport.xml中配置。如果安装 SAP B1 客户端(32 位),则文件路径如下:C:\Program Files (x86)\SAP BusinessObjects\SAP BusinessObjects Enterprise XI 4.0\java\CRReport.xml jar的完整路径必须添加到标签中

编辑 --> 非常重要
4) 遗憾的是,Java 报表启动器无法在 Java 11 下运行,很可能是因为 Crystal Report 12 尚不支持它。Java 版本必须是 1.8。我个人使用过的版本是OpenJDK 1.8.0_202。

Crystal Report JDBC 数据源连接
请按照以下步骤在 HANA DB 上为您的报告创建 JDBC 连接:

  1. 选择“数据库”->“设置数据源路径” (注:我的水晶报告是意大利语,如有翻译错误,敬请谅解)

  2. 在弹出的窗口中,选择“创建新连接”->JDBC (JNDI)->“创建新连接链接”

  3. 然后添加连接请求参数:

    请记住,如果您想连接到特定模式,则要使用的参数是“currentSchema”而不是“databaseName”。然后点击“继续”。
  4. 填写其他要求的信息。

    请记住,“数据库名称”代表您要连接的 HANA 数据库实例的名称,而不是您要使用的包含所有表/视图/等的架构...
    然后单击“确定”。 从那一刻起,您就可以使用新的 JDBC 连接来实现并完成您的 CR 报告。

JAVA应用
彻底执行上述步骤后,现在您就可以实现 Java 应用程序来加载报告了。 这是我所做的简单 JUnit 测试,它加载报告并将其导出为 PDF。这并不是我自己的全部工作,因为我只是整理并简化了我在网上找到的一些示例:

package mypackage;

import com.crystaldecisions.sdk.occa.report.application.*;
import com.crystaldecisions.sdk.occa.report.exportoptions.ReportExportFormat;
import org.junit.jupiter.api.Test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;

public class ReportLauncherTest {

    private static final String TEST_REPORT_RPT = "MyReport.rpt";
    private static final String TEST_REPORT_FULL_PATH_PDF =  "C:\\MyReport.pdf";
    private static final String PARAMETER_NAME_1 = "param1";
    private static final String PARAMETER_NAME_2 = "param2";

    private static final Integer PARAMETER_VALUE_1 = 1;
    private static final Integer PARAMETER_VALUE_2 = 2;

    private static final String DB_USERNAME = "USERNAME";
    private static final String DB_PASSWORD = "PASSWORD";

    @Test
    public void shouldLaunchReportAndExportInPDF() throws Exception {
        ReportClientDocument reportClientDoc = new ReportClientDocument();
        reportClientDoc.open(ReportLauncherTest.class.getClassLoader().getResource(TEST_REPORT_RPT).getPath(), 0);
        reportClientDoc.getDatabaseController().logon(DB_USERNAME, DB_PASSWORD);
        DataDefController dataDC = reportClientDoc.getDataDefController();
        dataDC.getParameterFieldController().setCurrentValue("", PARAMETER_NAME_1, PARAMETER_VALUE_1);
        dataDC.getParameterFieldController().setCurrentValue("", PARAMETER_NAME_2, PARAMETER_VALUE_2);

        ByteArrayInputStream byteArrayInputStream = (ByteArrayInputStream)reportClientDoc.getPrintOutputController().export(ReportExportFormat.PDF);
        writeToFileSystem(byteArrayInputStream, TEST_REPORT_FULL_PATH_PDF);
    }


    private void writeToFileSystem(ByteArrayInputStream byteArrayInputStream, String exportFile) throws Exception {
        //Use the Java I/O libraries to write the exported content to the file system.
        byte byteArray[] = new byte[byteArrayInputStream.available()];
        //Create a new file that will contain the exported result.
        File file = new File(exportFile);
        FileOutputStream fileOutputStream = new FileOutputStream(file);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(byteArrayInputStream.available());
        int x = byteArrayInputStream.read(byteArray, 0, byteArrayInputStream.available());
        byteArrayOutputStream.write(byteArray, 0, x);
        byteArrayOutputStream.writeTo(fileOutputStream);
        //Close streams.
        byteArrayInputStream.close();
        byteArrayOutputStream.close();
        fileOutputStream.close();
    }
}

请记住,代码需要一些依赖项,我将在下面列出这些依赖项:

我想你可以在网上找到其中的大部分。有些 jar 可以免费下载,其他的恐怕只有订阅后才能在 SAP 网站上找到。

希望您喜欢本教程。

如有任何反馈,我们将不胜感激。

谢谢。

© www.soinside.com 2019 - 2024. All rights reserved.