JDK-6322649 : There is no way to plug SyncProvider for CachedRowSet implementation
  • Type: Bug
  • Component: core-libs
  • Sub-Component: javax.sql
  • Affected Version: 6
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2005-09-12
  • Updated: 2014-02-27
  • Resolved: 2006-12-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 6 JDK 7
6u1 b01Fixed 7Fixed
Related Reports
Relates :  
Relates :  
Description
In accordance with the javadoc and "JDBC RowSet Implementations Tutorial" I try to implement and register my own SyncProvider instance in the following manner:
----------------MyProvider.java--------------------------------------------------
package com.sun.spb.rowset.providers;

import java.sql.Types;
import javax.sql.rowset.spi.*;
import javax.sql.rowset.*;
import javax.sql.*;

/**
 *
 * @author aag
 */
public class MyProvider extends SyncProvider implements RowSetReader,
        RowSetWriter {

    protected int datasource_lock = SyncProvider.DATASOURCE_NO_LOCK;

    /** Creates a new instance of MyProvider */
    public MyProvider() {
        System.out.println("New instance of " + getProviderID() +
                " created");
    }

    public void setDataSourceLock(int datasource_lock)
    throws SyncProviderException {
        this.datasource_lock = datasource_lock;
    }

    public int supportsUpdatableView() {
        return SyncProvider.UPDATABLE_VIEW_SYNC;
    }

    public String getVersion() {
        return "1.0";
    }

    public String getVendor() {
        return "Spb JCK Team";
    }

    public RowSetWriter getRowSetWriter() {
        return this;
    }

    public RowSetReader getRowSetReader() {
        return this;
    }

    public String getProviderID() {
        return this.getClass().getName();
    }

    public int getProviderGrade() {
        return SyncProvider.GRADE_NONE;
    }

    public int getDataSourceLock() throws SyncProviderException {
        return datasource_lock;
    }

    public boolean writeData(RowSetInternal caller) throws
            java.sql.SQLException {
        System.out.println("writeData");
        return true;
    }

    public void readData(RowSetInternal caller) throws java.sql.SQLException {
        System.out.println("readData");
        CachedRowSet crs = (CachedRowSet) caller;
        RowSetMetaData rsmd = new RowSetMetaDataImpl();
        crs.setReadOnly(false);
        crs.setType(RowSet.TYPE_SCROLL_INSENSITIVE);
        rsmd.setColumnCount(1);
        rsmd.setColumnName(1, "FIELD1");
        rsmd.setColumnType(1, Types.VARCHAR);
        crs.setMetaData(rsmd);
        crs.moveToInsertRow();
        crs.updateString(1, "VALUE1");
        crs.insertRow();
        crs.moveToCurrentRow();
        crs.beforeFirst();
    }

    public static void main(String[] argv) throws Exception {
        final String providerID = "com.sun.spb.rowset.providers.MyProvider";
        SyncFactory.registerProvider(providerID);
        /*final Hashtable<String, String> env = new Hashtable<String, String>();
        env.put(SyncFactory.ROWSET_SYNC_PROVIDER, providerID);
        final CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl(env); */
        final CachedRowSet crs = new com.sun.rowset.CachedRowSetImpl();
        crs.setSyncProvider(providerID);
        crs.execute();
    }
}
-------------------------------------------------------------------------------------
But unexpected exception occurs:
run:
New instance of com.sun.spb.rowset.providers.MyProvider created
Exception in thread "main" java.lang.ClassCastException:
com.sun.spb.rowset.providers.MyProvider
        at
com.sun.rowset.CachedRowSetImpl.setSyncProvider(CachedRowSetImpl.java:1380)
        at com.sun.spb.rowset.Test.main(Test.java:36)
Java Result: 1


I've looked into CachedRowSetImpl.java file and find the public interface type casts to non-public API type. Please have a look:
------------------------------------------------------------------------------
...
public void execute(Connection conn) throws SQLException {

        // store the connection so the reader can find it.
        setConnection(conn);

        if(getPageSize() != 0){
            crsReader = (CachedRowSetReader)provider.getRowSetReader();
            crsReader.setStartPosition(1);
            callWithCon = true;
            crsReader.readData((RowSetInternal)this);
        }

        // Now call the current reader's readData method
        else {
           rowSetReader.readData((RowSetInternal)this);
        }
        RowSetMD = (RowSetMetaDataImpl)this.getMetaData();

        if(conn != null){

          try {
                 dbmslocatorsUpdateCopy = conn.getMetaData().locatorsUpdateCopy();
          } catch(SQLException sqle) {
                  /*
                   * Since the Lobs and this method is not mandated by J2EE spec,
                   * drivers are not implementing it. We need to catch this
                   * and do nothing in this block and help populate()
                   * method do it's task
                   */
          } //end catch

        } else {

                  CachedRowSetReader crsTempReader = (CachedRowSetReader)rowSetReader;
                  ^^^^^^^^^^^^^^^^^^^
                  type cast to non-public API com.sun.rowset.internal.CachedRowSetReader
                  Connection tempCon = crsTempReader.connect((RowSetInternal)this);
...
----------------------------------------------------------------------
It looks like the user is not able to plug the own RowSetReader implementation into CachedRowSet.

Comments
EVALUATION This is being deferred for next release of jdk
20-07-2006