1

I use c3p0 version 0.9.5.1. The unwrap() method bug with this error :

java.lang.AbstractMethodError: Method com/mchange/v2/c3p0/impl/NewProxyStatement.unwrap(Ljava/lang/Class;)Ljava/lang/Object; is abstract at com.mchange.v2.c3p0.impl.NewProxyStatement.unwrap(NewProxyStatement.java)

This is my code :

com.mysql.jdbc.Statement stm =  proxyStatement.unwrap(com.mysql.jdbc.Statement.class)

I saw some post said that it should work since 0.9.5. Is it still a bug?

How can I get the original Statement/Connection from c3p0 Statement/Connection then? Thanks a lot

Nam HUYNH
  • 33
  • 5
  • Possible duplicate of [c3p0 ResultSet.unwrap throws an AbstractMethodError](http://stackoverflow.com/questions/1971617/c3p0-resultset-unwrap-throws-an-abstractmethoderror) – MWiesner Jul 08 '16 at 16:22
  • I saw this question but I use a newer version than in the answer and still got the same error – Nam HUYNH Jul 09 '16 at 13:36

1 Answers1

2

You almost certainly have an old version of c3p0 somewhere in your applcation's effective CLASSPATH. Please check your logs at INFO for c3p0's banner, something like

INFO: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]

To be sure of this, I just verified that Statement unwrapping works as specified within c3p0-0.9.5.2. I apologize that this is Scala REPL code rather than Java. That's just what's handy. But the underlying actions are the same at the JVM level.

[info] Starting scala interpreter...
[info] 
Welcome to Scala version 2.11.5 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_31).
Type in expressions to have them evaluated.
Type :help for more information.

scala> import com.mchange.v2.c3p0._
import com.mchange.v2.c3p0._

scala> val cpds = new ComboPooledDataSource()
Jul 08, 2016 1:44:43 PM com.mchange.v2.log.MLog 
INFO: MLog clients using java 1.4+ standard logging.
Jul 08, 2016 1:44:43 PM com.mchange.v2.c3p0.C3P0Registry 
INFO: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
cpds: com.mchange.v2.c3p0.ComboPooledDataSource = com.mchange.v2.c3p0.ComboPooledDataSource[ identityToken -> 2u6yea9h1khti8o11c1oj2|2407f8d8, dataSourceName -> 2u6yea9h1khti8o11c1oj2|2407f8d8 ]

scala> cpds.setUser("root")

scala> cpds.setJdbcUrl("jdbc:mysql://localhost/test?useSSL=false&serverTimezone=UTC")

scala> val conn = cpds.getConnection()
Jul 08, 2016 1:45:03 PM com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
INFO: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2u6yea9h1khti8o11c1oj2|2407f8d8, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> null, extensions -> {timezone=HKT}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2u6yea9h1khti8o11c1oj2|2407f8d8, idleConnectionTestPeriod -> 0, initialPoolSize -> 3, jdbcUrl -> jdbc:mysql://localhost/test?useSSL=false&serverTimezone=UTC, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 0, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
conn: java.sql.Connection = com.mchange.v2.c3p0.impl.NewProxyConnection@6044a933 [wrapping: com.mysql.cj.jdbc.ConnectionImpl@4318f07b]

scala> val proxyStatement = conn.createStatement()
proxyStatement: java.sql.Statement = com.mchange.v2.c3p0.impl.NewProxyStatement@57b482ea [wrapping: com.mysql.cj.jdbc.StatementImpl@b120337]

scala> val nativeStmt = proxyStatement.unwrap(classOf[com.mysql.cj.jdbc.StatementImpl])
nativeStmt: com.mysql.cj.jdbc.StatementImpl = com.mysql.cj.jdbc.StatementImpl@b120337

I am using MySQL Connector/J version 6.0.3, which is probably newer than yours (thus the different Statement class name). You can unwrap the Statement in a more implementation-class neutral way:

scala> val nativeStmt2 = proxyStatement.unwrap(classOf[java.sql.Statement])
nativeStmt2: java.sql.Statement = com.mysql.cj.jdbc.StatementImpl@b120337

Note that Scala's classOf[java.sql.Statement] is equivalent to Java's class literal, java.sql.Statement.class

Steve Waldman
  • 13,689
  • 1
  • 35
  • 45
  • Thanks for replying so fast. In my classpath of my OSGi bundle, I only have **hibernate-c3p0-3.6.5.Final.jar** and now **c3p0-0.9.5.2.jar**. The problem still persist. Since I use a tier framework, it does not print in the log but I search in the MANIFEST.MF of all bundles OSGi of my server, these are the only ones. Also I use **mysql-connector-java-5.1.37**.
    May be it's the hibernate-c3p0 jar that's to old?
    – Nam HUYNH Jul 09 '16 at 13:36
  • Btw I looked at the source code of com.mchange.v2.c3p0.impl.NewProxyStatement and find no unwrap function, is it normal? – Nam HUYNH Jul 09 '16 at 13:41
  • It's there, see [line 1402](https://gist.github.com/swaldman/4f58039f49fe5077cf6e397ec7471a3d). Note that this is a code-generated file. You have to build it, you won't find the source directly. (It is bundled into the Maven src jar, though.) – Steve Waldman Jul 20 '16 at 01:12
  • You're right. There was another package of c3p0 was imported through another bundle in older version. Exclude it and it work like a charm. Thanks a lot – Nam HUYNH Jul 22 '16 at 13:09