All.
I found an example for a "Crystal Report PDF converter" on SAP's page. It works fine on "simple" reports, but when a report contains database connection it fails. Here's what I've got:
import com.crystaldecisions.sdk.occa.report.lib.*;
import com.crystaldecisions.sdk.occa.report.application.ReportClientDocument;
import com.crystaldecisions.sdk.occa.report.exportoptions.*;
//Java imports.
import java.io.*;
public class Reader {
// static final String REPORT_NAME = "C:\\works_fine.rpt";
static final String REPORT_NAME = "C:\\problematic.rpt";
static final String EXPORT_FILE = "C:\\myExportedReport.pdf";
public static void main(String[] args) {
try {
// Open report.
ReportClientDocument reportClientDoc = new ReportClientDocument();
reportClientDoc.open(REPORT_NAME, 0);
// NOTE: If parameters or database login credentials are required,
// they need to be set before.
// calling the export() method of the PrintOutputController.
// Export report and obtain an input stream that can be written to
// disk.
// See the Java Reporting Component Developer's Guide for more
// information on the supported export format enumerations
// possible with the JRC.
ByteArrayInputStream byteArrayInputStream = (ByteArrayInputStream) reportClientDoc
.getPrintOutputController().export(ReportExportFormat.PDF);
// Release report.
reportClientDoc.close();
// 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(EXPORT_FILE);
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();
System.out
.println("Successfully exported report to " + EXPORT_FILE);
} catch (ReportSDKException ex) {
ex.printStackTrace();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
I even added the following before the export call, but it still failed:
oracle.jdbc.pool.OracleDataSource ds
= new oracle.jdbc.pool.OracleDataSource();
ds.setDriverType("thin");
ds.setServerName("server");
ds.setPortNumber(123);
ds.setDatabaseName("database");
ds.setPassword("password");
ds.setUser("user");
As a mentioned before, when I use the "works_fine" report, It works like a champ, but once I use the "problematic" report, this happens:
com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: Error finding JNDI name (THENAME)---- Error code:-2147467259 Error code name:failed
at com.crystaldecisions.sdk.occa.report.application.PrintOutputController.if(SourceFile:237)
at com.crystaldecisions.sdk.occa.report.application.PrintOutputController.export(SourceFile:147)
at com.crystaldecisions.sdk.occa.report.application.PrintOutputController.export(SourceFile:128)
at com.crystaldecisions.sdk.occa.report.application.PrintOutputController.export(SourceFile:111)
at gac.read.Reader.main(Reader.java:49)
Caused by: com.crystaldecisions.reports.common.JndiNotFoundException: Error finding JNDI name (THENAME)
at com.crystaldecisions.reports.queryengine.Connection.a(SourceFile:1871)
at com.crystaldecisions.reports.queryengine.Connection.br(SourceFile:1815)
at com.crystaldecisions.reports.queryengine.Connection.bs(SourceFile:505)
at com.crystaldecisions.reports.queryengine.Connection.t4(SourceFile:3020)
at com.crystaldecisions.reports.dataengine.dfadapter.DFAdapter.a(SourceFile:697)
at com.crystaldecisions.reports.dataengine.dfadapter.DFAdapter.for(SourceFile:707)
at com.crystaldecisions.reports.reportdefinition.ReportHelper.a(SourceFile:198)
at com.businessobjects.reports.sdk.requesthandler.ReportViewingRequestHandler.long(SourceFile:958)
at com.businessobjects.reports.sdk.requesthandler.ReportViewingRequestHandler.a(SourceFile:636)
at com.businessobjects.reports.sdk.requesthandler.ReportViewingRequestHandler.int(SourceFile:673)
at com.businessobjects.reports.sdk.JRCCommunicationAdapter.do(SourceFile:1943)
at com.businessobjects.reports.sdk.JRCCommunicationAdapter.if(SourceFile:660)
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.ReportSource.a(SourceFile:1558)
at com.crystaldecisions.sdk.occa.report.application.ReportSource.a(SourceFile:337)
at com.crystaldecisions.sdk.occa.report.application.PrintOutputController.if(SourceFile:223)
... 4 more
Caused by: com.businessobjects.reports.jdbinterface.common.DBException: Error finding JNDI name (THENAME)
at com.crystaldecisions.reports.queryengine.driverImpl.jdbc.JDBCConnection.Open(Unknown Source)
at com.crystaldecisions.reports.queryengine.JDBConnectionWrapper.Open(SourceFile:123)
at com.crystaldecisions.reports.queryengine.Connection.br(SourceFile:1786)
... 30 more
It is worth mentioning that I'm new to Crystal Reports and creating JNDI names.
Any kind of help is much appreciated. Thanks.
I solved the issue by overwriting the connection properties:
package com.org;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import com.crystaldecisions.sdk.occa.report.application.ReportClientDocument;
import com.crystaldecisions.sdk.occa.report.data.ConnectionInfoKind;
import com.crystaldecisions.sdk.occa.report.data.IConnectionInfo;
import com.crystaldecisions.sdk.occa.report.data.ITable;
import com.crystaldecisions.sdk.occa.report.exportoptions.ReportExportFormat;
import com.crystaldecisions.sdk.occa.report.lib.PropertyBag;
import com.crystaldecisions.sdk.occa.report.lib.ReportSDKException;
public class YetAnotherReader {
public static void main(String[] args) {
try {
//Overwrite any existing properties with updated values.
//information Oracle database
String DBUSERNAME = "user";
String DBPASSWORD = "password";
String SERVERNAME = "server";
String PORT = "1521";
String DATABASE_NAME = "databaseName"; // SID or Instance
String URI = "!oracle.jdbc.driver.OracleDriver!jdbc:oracle:thin:{userid}/{password}@" + SERVERNAME + ":" + PORT + "/" + DATABASE_NAME; //1521/ or :1521
String DATABASE_DLL = "crdb_jdbc.dll";
//end
String report_name = "C:\\myReport.rpt";
String exportFileName = "C:\\fileName.pdf";
ReportClientDocument clientDoc = new ReportClientDocument();
clientDoc.open(report_name, ReportExportFormat._PDF);
// Obtain collection of tables from this database controller.
ITable table = clientDoc.getDatabaseController().getDatabase().getTables().getTable(0);
IConnectionInfo connectionInfo = table.getConnectionInfo();
PropertyBag propertyBag = connectionInfo.getAttributes();
propertyBag.clear();
//Overwrite any existing properties with updated values.
propertyBag.put("Trusted_Connection", "false");
propertyBag.put("Server Name", SERVERNAME); //Optional property.
propertyBag.put("Database Name", DATABASE_NAME);
propertyBag.put("Server Type", "JDBC (JNDI)");
propertyBag.put("URI", URI);
propertyBag.put("Use JDBC", "true");
propertyBag.put("Database DLL", DATABASE_DLL);
connectionInfo.setAttributes(propertyBag);
//Set database username and password.
//NOTE: Even if these the username and password properties don't change when switching databases, the
//database password is *not* saved in the report and must be set at runtime if the database is secured.
connectionInfo.setUserName(DBUSERNAME);
connectionInfo.setPassword(DBPASSWORD);
connectionInfo.setKind(ConnectionInfoKind.SQL);
table.setConnectionInfo(connectionInfo);
//Update old table in the report with the new table.
clientDoc.getDatabaseController().setTableLocation(table, table);
clientDoc.getDataDefController().getParameterFieldController().setCurrentValue("", "pk_id", 14);
//Writing into PDF file
ByteArrayInputStream bais = (ByteArrayInputStream) clientDoc.getPrintOutputController().export(ReportExportFormat.PDF);
int size = bais.available();
byte[] barray = new byte[size];
FileOutputStream fos = new FileOutputStream(new File(exportFileName));
ByteArrayOutputStream baos = new ByteArrayOutputStream(size);
int bytes = bais.read(barray, 0, size);
baos.write(barray, 0, bytes);
baos.writeTo(fos);
clientDoc.close();
bais.close();
baos.close();
fos.close();
//dbConn.close();
} catch (ReportSDKException ex) {
System.out.println("ReportSDKException" + ex);
} catch (Exception ex) {
System.out.println("Exception" + ex);
}
}
}
Also, please notice the use of a primary key on (You might want to change that, too):
clientDoc.getDataDefController().getParameterFieldController().setCurrentValue("", "pk_id", 14);
"pk_id" is a parameter used on the report. Example:
SELECT * FROM myTableOrView WHERE id < {?pk_id}
Source: Here
Edit: Are you getting the following error? com.crystaldecisions.sdk.occa.report.lib.ReportSDKException: Unexpected ValueType: ValueType=[255]
Check Marco Tizzano's answer