Bug #51281 ClassCastException with proxied DataSource when invoking getMetaData().getTables
Submitted: 18 Feb 2010 13:59 Modified: 16 Dec 2010 13:15
Reporter: Mihai Postelnicu Email Updates:
Status: Can't repeat Impact on me:
None 
Category:Connector / J Severity:S3 (Non-critical)
Version:5.1.13 OS:Linux (Ubuntu 10.04)
Assigned to: CPU Architecture:Any
Tags: ClassCastException, getMetaData, JDBC4ResultSet, JRMPInvokerProxy

[18 Feb 2010 13:59] Mihai Postelnicu
Description:
ClassCastException is thrown when trying to retrieve the description of the tables (MetaData.getTables()) via a proxied JNDI DataSource.

- what i did: invoked ds.getConnection().getMetaData().getTables
- what i wanted to achieve: get a ResultSet with the table descriptions
- what it happened:
java.lang.ClassCastException: $Proxy3 cannot be cast to java.sql.ResultSet
	at $Proxy2.getTables(Unknown Source)

Software Versions used:
- JBoss AS 4.2.3 GA was used for the JCA Datasource provider
- MySQL-connector 5.1.11 as the JDBC driver
- MySQL-5.1.37 as the database server
- Ubuntu Linux 9.10 x86_64 as the operating system
- JDK 1.6.0_16 as the Java VM

Observations:
This error does not happen with MySQL-connector 5.0 but only with 5.1.
This error does not happen when the DataSource is queried directly, without going through the JNP proxy.

How to repeat:
use the JBoss 4.2.3 and add this in jboss/server/default/deploy/mysql-ds.xml:

<?xml version="1.0" encoding="UTF-8"?>
<datasources>
  <local-tx-datasource>
    <jndi-name>localDS</jndi-name>
    <connection-url>jdbc:mysql://localhost/information_schema</connection-url>
    <driver-class>com.mysql.jdbc.Driver</driver-class>
    <user-name>root</user-name>
    <password></password>
    <transaction-isolation>TRANSACTION_READ_COMMITTED</transaction-isolation>
    <use-java-context>false</use-java-context>
    <metadata>
       <type-mapping>mySQL</type-mapping>
    </metadata>
  </local-tx-datasource>
</datasources>

JUnit test case:

public void testClassCastExceptionJDBC4GetTables() throws Exception {
 Properties env = new Properties();
 env.setProperty(Context.INITIAL_CONTEXT_FACTORY,
    "org.jnp.interfaces.NamingContextFactory");
 env.setProperty(Context.PROVIDER_URL, "jnp://localhost:1099");
 env.setProperty(Context.URL_PKG_PREFIXES,
    "org.jboss.naming:org.jnp.interfaces");
 InitialContext ctx = new InitialContext(env);
 DataSource ds= (DataSource) ctx.lookup("localDS");
 ResultSet tables = ds.getConnection().getMetaData().getTables(null, null, "ROUTINES",new String[]{"TABLE", "VIEW"});	
 System.out.println(tables);
}
[18 Feb 2010 22:30] Mihai Postelnicu
i have confirmed this with Connector/J 5.1.12 as well.
[18 Feb 2010 22:38] Mark Matthews
Can you post a full stack trace? There's no way to tell what's going on here with just the top of the stack.
[18 Feb 2010 22:46] Mihai Postelnicu
Sure, here's the stack:

java.lang.ClassCastException: $Proxy3 cannot be cast to java.sql.ResultSet
	at $Proxy2.getTables(Unknown Source)
	at org.dgfoundation.amp.TestClassCastExceptionJDBC4GetTables.testProblem(TestClassCastExceptionJDBC4GetTables.java:50)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at junit.framework.TestCase.runTest(TestCase.java:154)
	at junit.framework.TestCase.runBare(TestCase.java:127)
	at junit.framework.TestResult$1.protect(TestResult.java:106)
	at junit.framework.TestResult.runProtected(TestResult.java:124)
	at junit.framework.TestResult.run(TestResult.java:109)
	at junit.framework.TestCase.run(TestCase.java:118)
	at junit.framework.TestSuite.runTest(TestSuite.java:208)
	at junit.framework.TestSuite.run(TestSuite.java:203)
	at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
	at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
	at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Thanks
[11 May 2010 8:55] Chris Price
Is there any update on this bug?  Target release?  We just ran into it trying to upgrade from 5.0.6 to 5.1.12.  Is there a suggested work around or features we can disable to get this to work without having to fully regression test a different version (or forego the upgrade completely)?
[11 May 2010 9:09] Mihai Postelnicu
Chris,
There has been little progress with this bug in the last months, so we have decided to use 5.0.8 for the moment.

But it would be really great to see it fixed, so we could start using 5.1.x...
[11 May 2010 9:12] Tonci Grgin
Chris, Mihai, I apologize but whenever there is a third party SW involved things tend to complicate, even in unexpected places...
[11 May 2010 9:14] Chris Price
Understood.  Any suggested workarounds?  Or ETA?
[11 May 2010 9:19] Tonci Grgin
No, not right now, sorry. However I'm keeping this in mind (thus "Analyzing" instead of just "Open").
[19 May 2010 9:52] Alex Gartner
Is there any news on this issue ? Will a fix be included in the next Connector/J version ?

I ran into a similar problem on JBoss 4.2.3, Connector/J 5.1.12, MySQL 5.1.46 on openSuse 11.2  .
[2 Aug 2010 13:53] Mihai Postelnicu
Same problem found in the new connector/j 5.1.13, same testing environment as above, same exception
[2 Aug 2010 14:01] Tonci Grgin
Sure there is a same problem, haven't fixed it yet.
[16 Dec 2010 11:47] Tonci Grgin
As expected, this took long time to get checked. I find no problems using latest snapshot and JBoss 4.2.3:
101216 12:42:19	   13 Connect	root@localhost on test
		   13 Query	/* mysql-connector-java-5.1.15-SNAPSHOT ( Revision: mark.matthews@oracle.com-20101209174100-kuoilq0a8u08v6d7 ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'init_connect'
		   13 Query	/* mysql-connector-java-5.1.15-SNAPSHOT ( Revision: mark.matthews@oracle.com-20101209174100-kuoilq0a8u08v6d7 ) */SELECT @@session.auto_increment_increment
		   13 Query	SHOW COLLATION
		   13 Query	SET NAMES utf8mb4
		   13 Query	SET character_set_results = NULL
		   13 Query	SET autocommit=1
		   13 Query	SET sql_mode='STRICT_TRANS_TABLES'
		   13 Query	SELECT VERSION()
		   14 Connect	root@localhost on test
		   14 Query	/* mysql-connector-java-5.1.15-SNAPSHOT ( Revision: mark.matthews@oracle.com-20101209174100-kuoilq0a8u08v6d7 ) */SHOW VARIABLES WHERE Variable_name ='language' OR Variable_name = 'net_write_timeout' OR Variable_name = 'interactive_timeout' OR Variable_name = 'wait_timeout' OR Variable_name = 'character_set_client' OR Variable_name = 'character_set_connection' OR Variable_name = 'character_set' OR Variable_name = 'character_set_server' OR Variable_name = 'tx_isolation' OR Variable_name = 'transaction_isolation' OR Variable_name = 'character_set_results' OR Variable_name = 'timezone' OR Variable_name = 'time_zone' OR Variable_name = 'system_time_zone' OR Variable_name = 'lower_case_table_names' OR Variable_name = 'max_allowed_packet' OR Variable_name = 'net_buffer_length' OR Variable_name = 'sql_mode' OR Variable_name = 'query_cache_type' OR Variable_name = 'query_cache_size' OR Variable_name = 'init_connect'
		   14 Query	/* mysql-connector-java-5.1.15-SNAPSHOT ( Revision: mark.matthews@oracle.com-20101209174100-kuoilq0a8u08v6d7 ) */SELECT @@session.auto_increment_increment
		   14 Query	SHOW COLLATION
		   14 Query	SET NAMES utf8mb4
		   14 Query	SET character_set_results = NULL
		   14 Query	SET autocommit=1
		   14 Query	SET sql_mode='STRICT_TRANS_TABLES'
		   14 Query	SHOW FULL TABLES FROM `test` LIKE '%'
		   13 Quit	

However, due to javax.naming.NameNotFoundException: MySqlDS not bound I had to modify the test case as follows:
		com.mysql.jdbc.jdbc2.optional.MysqlDataSource ds = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();
		ds.setServerName("localhost") ;
		ds.setPort(xxx) ;
		ds.setDatabaseName("test") ;
		ds.setUser("xxx") ;
		ds.setPassword("xxx") ; 
		
--same--	
		ctx.bind("mysql", ds);

Anyone still having this problem with latest driver?
[16 Dec 2010 11:48] Tonci Grgin
Oh yes, one more change:
ResultSet tables = ds.getConnection().getMetaData().getTables("test", null, "%",new String[]{"TABLE", "VIEW"});
[16 Dec 2010 13:15] Tonci Grgin
With some more modifications:
Loading JDBC driver 'com.mysql.jdbc.Driver'
Done.

Done.

Connected to 5.5.6-rc-log
java.vm.version         : 1.5.0_17-b04
java.vm.vendor          : Sun Microsystems Inc.
java.runtime.version    : 1.5.0_17-b04
os.name                 : Windows Server 2008
os.version              : null
sun.management.compiler : HotSpot Client Compiler
com.mysql.jdbc.ResultSetImpl@cbdb20

Column 'TABLE_CAT', value test
Column 'TABLE_SCHEM', value null
Column 'TABLE_NAME', value b`a`d`d`d
Column 'TABLE_TYPE', value TABLE
Column 'REMARKS', value 

Column 'TABLE_CAT', value test
Column 'TABLE_SCHEM', value null
Column 'TABLE_NAME', value log
Column 'TABLE_TYPE', value TABLE
Column 'REMARKS', value 

Column 'TABLE_CAT', value test
Column 'TABLE_SCHEM', value null
Column 'TABLE_NAME', value user
Column 'TABLE_TYPE', value TABLE
Column 'REMARKS', value