Quantcast
Channel: SCN : Popular Discussions - Java SDK Application Development
Viewing all articles
Browse latest Browse all 1701

RAS API Changing Oracle Datasource

$
0
0

In the past, I had attempted to use the JRC API to modify reports and it did most of what I wanted, but did not support dynamic report parameters.  So I had to abandon that approach.  The suggested replacement is using the RAS API.

 

I have seen the sample RAS code for modifying a datasource, but it is rather specific and not what I need.  It would be interesting to see a document that addressed all of the different types of datasources and what is needed to modify them programmatically, but I have not seen such a document.  If there is one, please point me to it.

 

I have a collection of reports that use the 'Oracle Server' type of connection with OS authentication.  I want to programmatically change their datasource to point to a different database and also modify the schema owner (by changing the qualified table name and schema owner names in 'command' tables.

 

Since I worked with JRC in the past, I had got that working to use a JDBC connection.  The RAS and JRC APIs are actually quite similar.  But it turns out that the stuff that goes in the PropertyBag for RAS is different than JRC (even when using JDBC for both APIs).

 

Instead of using JDBC in RAS, I would actually prefer to use the Oracle Server type of connection, but I realize that using OS authentication for logging in would not be a good idea.  Since the OS authentication would be done using the Crystal Report Server instead of the end user (which works OK for Crystal Reports Designer).

 

Anyway, here is a Java class that I have written to be called from JSP.  It currently deals with an 'Oracle Server' type of connection, but has some stuff in it related to JDBC from my original JRC coding.  Ignore the JDBC stuff please.  I'm just leaving that there in case I decide to switch to JDBC if I cannot make the Oracle Server stuff work.

 

package com.ppllc.PASReportUtilities;

/*

 

  • Datasource.java

*

 

  • Created on October 29, 2008, 1:19 PM

*

*/

 

import com.crystaldecisions.sdk.occa.report.application.DatabaseController;

import com.crystaldecisions.sdk.occa.report.application.ReportClientDocument;

import com.crystaldecisions.sdk.occa.report.application.ISubreportClientDocument;

import com.crystaldecisions.sdk.occa.report.lib.ReportSDKException;

import com.crystaldecisions.sdk.occa.report.lib.IStrings;

import com.crystaldecisions.sdk.occa.report.lib.PropertyBag;

import com.crystaldecisions.sdk.occa.report.lib.PropertyBagHelper;

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.data.Tables;

import com.crystaldecisions.sdk.occa.report.data.CommandTable;

import com.crystaldecisions.sdk.occa.report.application.ReportSaveAsOptions;

 

import java.lang.System;

import java.text.MessageFormat;

import java.util.Collection;

import java.util.HashSet;

import java.util.Iterator;

 

/**

*

 

  • @author mcfadden

*/

public class DatabaseConnectionInfo {

     

    private String databaseName;

    private String databaseSchemaName;

    private String hostName;

    private int portNumber = 1521;

    private String loginUserName;

    private String loginPassword; 

     

    /** Creates a new instance of Datasource */

    public DatabaseConnectionInfo() {

        databaseName = null;

        databaseSchemaName = null;

        hostName = null;

        portNumber = 1521;

        loginUserName = null;

        loginPassword = null;

    }

 

    public String getDatabaseName() {

        return databaseName;

    }

 

    public void setDatabaseName(String databaseName) {

        this.databaseName = databaseName;

    }

 

    public String getDatabaseSchemaName() {

        return databaseSchemaName;

    }

 

    public void setDatabaseSchemaName(String databaseSchemaName) {

        this.databaseSchemaName = databaseSchemaName;

    }

 

    public String getHostName() {

        return hostName;

    }

 

    public void setHostName(String hostName) {

        this.hostName = hostName;

    }

 

    public int getPortNumber() {

        return portNumber;

    }

 

    public void setPortNumber(int portNumber) {

        this.portNumber = portNumber;

    }

 

    public String getLoginUserName() {

        return loginUserName;

    }

 

    public void setLoginUserName(String loginUserName) {

        this.loginUserName = loginUserName;

    }

 

    public String getLoginPassword() {

        return loginPassword;

    }

 

    public void setLoginPassword(String loginUserPassword) {

        this.loginPassword = loginUserPassword;

    }

     

    @SuppressWarnings ("unchecked")

    private void switch_tables(DatabaseController databaseController) throws ReportSDKException {

 

        final String DBUSERNAME = getLoginUserName();

        final String DBPASSWORD = ((DBUSERNAME != null)

                                    ? getLoginPassword()

                                    : null

                                  );

        final String DATABASE_NAME = getDatabaseName();

        final String DATABASE_SCHEMA = getDatabaseSchemaName();

        final String HOST_NAME = getHostName();

        final String PORT_NUMBER = Integer.toString(getPortNumber());

        final String JDBC_URL_PREFIX = "jdbc:oracle:thin:";

        final String JDBC_URL_SUFFIX = MessageFormat.format("@{0}",                                                            ((HOST_NAME == null)                                                              ? ""                                                              : MessageFormat.format("::", HOST_NAME, PORT_NUMBER)

                                                            ),

                                                            DATABASE_NAME

                                                           );

        final String DATABASE_URL = JDBC_URL_PREFIX + JDBC_URL_SUFFIX;

        final String DATABASE_CLASS_NAME = "oracle.jdbc.OracleDriver";

        final String JDBC_CONNECTION_STRING = MessageFormat.format("!!",                                                                   DATABASE_CLASS_NAME,                                                                   JDBC_URL_PREFIX,                                                                   ((DBUSERNAME != null)                                                                     ? "/"                                                                     : ""                                                                   ),                                                                   JDBC_URL_SUFFIX                                                                  );        final String CONNECTION_STRING = MessageFormat.format("Use JDBC=b(true);Connection URL=s();Database Class Name=s();Password=;Trusted_Connection=b();JDBC Connection String=s()",

                                                              DATABASE_URL,

                                                              DATABASE_CLASS_NAME,

                                                              ((DBUSERNAME != null)

                                                                ? MessageFormat.format("User ID=s();", DBUSERNAME)

                                                                : ""

                                                              ),

                                                              ((DBUSERNAME == null)

                                                                ? "true"

                                                                : "false"

                                                              ),

                                                              JDBC_CONNECTION_STRING

                                                             );

        final String DATABASE_DLL = "crdb_jdbc.dll";

 

        //Obtain collection of tables from this database controller.

        Tables tables = databaseController.getDatabase().getTables();

 

        // Build a set of old schema names for substitution in CommandTable sql.

        Collection<String> oldSchemaNames = new HashSet<String>();

        oldSchemaNames.add("OPS$PASPROD");

        for (int i = 0; i < tables.size(); i++) {

          ITable table = tables.getTable(i);

          if (!(table instanceof CommandTable)) {

            String name = table.getQualifiedName();

            int indexOfPeriod = name.indexOf('.');

            if (indexOfPeriod > 0) {

              oldSchemaNames.add(name.substring(0, indexOfPeriod));

            }

          }

        }

 

        //Set the datasource for all main report tables.

        String newSchemaNameWithDollarSignsEscaped = DATABASE_SCHEMA.replaceAll("
$", "


$");

        for (int i = 0; i < tables.size(); i++) {

 

          ITable table = tables.getTable(i);

 

          //Change the schema name in the table or command table.

          if (DATABASE_SCHEMA != null) {

            if (table instanceof CommandTable) {

              CommandTable commandTable = (CommandTable)table;

              String sql = commandTable.getCommandText();

              Iterator<String> it = oldSchemaNames.iterator();

              while (it.hasNext()) {

                sql = sql.replaceAll("(?i)(?m)
Q" + it.next() + "
E
.", newSchemaNameWithDollarSignsEscaped + ".");

              }

              commandTable.setCommandText(sql);

            }

            else {

              table.setQualifiedName(DATABASE_SCHEMA.toUpperCase() + "." + table.getName());

            }

          }

 

          //Change connection information properties.

          IConnectionInfo connectionInfo = table.getConnectionInfo();

           

          System.out.println("existing PropertyBag: " + connectionInfo.getAttributes().toString());

 

/*         

          //Set new table connection property attributes.

          PropertyBag propertyBag = new PropertyBag();

 

          //Overwrite any existing properties with updated values.

          propertyBag.putBooleanValue("Trusted_Connection", (DBUSERNAME == null));

          propertyBag.put("Server Type", "JDBC (JNDI)");

          propertyBag.put("Database DLL", DATABASE_DLL);

          propertyBag.put("Connection String", CONNECTION_STRING);

          propertyBag.put("Database Class Name", DATABASE_CLASS_NAME);

          propertyBag.putBooleanValue("Use JDBC", true);

          propertyBag.put("URI", JDBC_CONNECTION_STRING);

*/

           

          PropertyBag connInfoProperties = new PropertyBag();

          PropertyBag logonProperties = new PropertyBag();

           

          logonProperties.putBooleanValue("Trusted_Connection", false);

          logonProperties.put("Server", DATABASE_NAME);

          //Overwrite any existing properties with updated values.

          connInfoProperties.putBooleanValue(PropertyBagHelper.CONNINFO_SSO_ENABLED, false);

          connInfoProperties.put(PropertyBagHelper.CONNINFO_CRQE_DATABASETYPE, "Oracle Server");

          connInfoProperties.put(PropertyBagHelper.CONNINFO_DATABASE_DLL, "crdb_oracle.dll");

          connInfoProperties.put(PropertyBagHelper.CONNINFO_CRQE_DATABASENAME, null);

          connInfoProperties.putBooleanValue(PropertyBagHelper.CONNINFO_CRQE_SQLDB, true);

          connInfoProperties.put(PropertyBagHelper.CONNINFO_CRQE_LOGONPROPERTIES, logonProperties);

          connInfoProperties.put(PropertyBagHelper.CONNINFO_CRQE_SERVERDESCRIPTION, DATABASE_NAME);

 

/*

          System.out.println("Connection String: " + CONNECTION_STRING);

          System.out.println("Datagbase Class Name: " + DATABASE_CLASS_NAME);

          System.out.println("URI: " + JDBC_CONNECTION_STRING);

*/

   

          connectionInfo.setAttributes(connInfoProperties);

           

          System.out.println("new PropertyBag: " + connectionInfo.getAttributes().toString());         

 

          //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.

          if (DBUSERNAME != null) {

               

            System.out.println("old Username: " + connectionInfo.getUserName().toString());

            System.out.println("old Password: " + connectionInfo.getPassword().toString());

             

            connectionInfo.setUserName(DBUSERNAME);

            connectionInfo.setPassword(DBPASSWORD);

             

            System.out.println("UserName: " + DBUSERNAME);

            System.out.println("Password: " + DBPASSWORD);

          }

          connectionInfo.setKind(ConnectionInfoKind.SQL);

 

          table.setConnectionInfo(connectionInfo);

 

          //Update old table in the report with the new table.

          databaseController.setTableLocation(table, tables.getTable(i));

        }

    }

     

    public void modifyReportDatabaseConnection(ReportClientDocument reportClientDoc) throws Exception {

        

        try {

            // modify the main report

            switch_tables(reportClientDoc.getDatabaseController());

 

            // modify all of the subreports

            IStrings subreportNames = reportClientDoc.getSubreportController().getSubreportNames();

            for (int i = 0; i < subreportNames.size(); i++ ) {

              ISubreportClientDocument subreportClientDoc = reportClientDoc.getSubreportController().getSubreport(subreportNames.getString(i));

              switch_tables(subreportClientDoc.getDatabaseController());

            }

        }

        catch (ReportSDKException ex) {

           throw ex;

        }

        catch (Exception ex) {

            throw ex;

        }

    }

}

 

The problem that I'm getting is a failure to log into the database, as indicated by this message that gets displayed on my JSP error page:

 

Logon failed. Error in File C:\WINDOWS\TEMP\{BC03F943-58A5-4446-AE51-F180D90B6865}.rpt: Unable to connect: incorrect log on parameters.

 

In switch_tables, I have some code that dumps the "existing" ProperyBag and the "new" PropertyBag.

 

Essentially, I'm currently debugging a really simple report (and this report does not use OS Authentication to login, like all of our current reports).  This simple report had been successfully schedule in Crystal Reports Server.

 

What seems odd to me is that I can supply connection information that is not different than what is already in the report, buy I still get the login error.  Here is the debug information from my Tomcat log:

 

existing PropertyBag: {SSO Enabled=false, QE_DatabaseType=Oracle Server, Database DLL=crdb_oracle.dll, QE_DatabaseName=, QE_SQLDB=true, QE_LogonProperties={Trusted_Connection=false, Server=dev51pr}, QE_ServerDescription=dev51pr}

new PropertyBag: {QE_DatabaseType=Oracle Server, SSO Enabled=false, Database DLL=crdb_oracle.dll, QE_DatabaseName=null, QE_LogonProperties={Trusted_Connection=false, Server=dev51pr}, QE_SQLDB=true, QE_ServerDescription=dev51pr}

old Username: ops$mcfadden

old Password:

UserName: ops$mcfadden

Password: ********

 

Of course in the case of the existing report, the password is not there, as the report does not save that.  And I have replaced the password that I'm using with '********', above, as the value is not important.

 

Perhaps I'm missing a step here.  Is there something else I need to do other than setting the PropertyBag, the user name and user password?


Viewing all articles
Browse latest Browse all 1701

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>