Programmatically overwritting the Database Connection of a Crystal Report File from Java

Recently I’ve had the “pleasure” of decommissioning existing applications in lieu of new systems coming online and as part of the process there was the need to Export Crystal Reports for Archival to ensure no loss of data. During this process the main stumbling block I experienced was how to overwrite the jndi DataSource defined in the report file so that I could execute the report from outside a web container.

The short answer to the question is that you need to overwrite the IConnectionInfo object for each Table used in the Crystal Report. For a first attempt I tried to simply iterate over each Table entry and update their ConnectionInfo.

DatabaseController dbController = clientDoc.getDatabaseController();

String connString = "jdbc:oracle:thin:@server:port:db";
			
PropertyBag bag = new PropertyBag();
bag.put("Connection URL", connString);
bag.put("Server Type", "JDBC (JNDI)");
bag.put("Database DLL", "crdb_jdbc.dll");
bag.put("Database Class Name", "oracle.jdbc.driver.OracleDriver");

for(Object table : dbController.getDatabase().getTables()) {

    ITable t = (ITable)table;

    // modifying t, bag is an existing instance of class PropertyBag
    t.getConnectionInfo().setAttributes(bag);        
    t.getConnectionInfo().setUserName("user");
    t.getConnectionInfo().setPassword("password");

}

However as it turns out when you modify the table connection information the Tables object is updated and the positioning of table objects is modified and as such during iteration not all Table connections are updated. To correct for this positioning change you can clone the Table objects and use a map to update the properties of the original table connections after updating the cloned Table ConnectionInfo.

DatabaseController dbController = clientDoc.getDatabaseController();
			
String connString = "jdbc:oracle:thin:@server:port:db";

PropertyBag bag = new PropertyBag();
bag.put("Connection URL", connString);
bag.put("Server Type", "JDBC (JNDI)");
bag.put("Database DLL", "crdb_jdbc.dll");
bag.put("Database Class Name", "oracle.jdbc.driver.OracleDriver");

Map oldNewMap = new HashMap();

for(Object table : dbController.getDatabase().getTables()) {

    ITable t = (ITable)((ITable)table).clone(true);

    // modifying t, bag is an existing instance of class PropertyBag
    t.getConnectionInfo().setAttributes(bag);        
    t.getConnectionInfo().setUserName("user");
    t.getConnectionInfo().setPassword("password");
	         
    // WORKAROUND CODE
    oldNewMap.put((ITable)table, t);
}

// WORKAROUND CODE
for (Entry e : oldNewMap.entrySet()) {
    dbController.setTableLocation(e.getKey(), e.getValue());
}
// Java //

Comments & Questions

Add Your Comment