Ping failed in MysqlValidConnectionChecker in JBoss/MySQL-ConnectorJ Combination
Today I was battling an issue for some of my colleagues. They were getting this exception from JBoss/Mysql ConnectorJ driver:
java.sql.SQLException: Ping failed: java.lang.IllegalArgumentException: object is not an instance of declaring class
in the JBoss console.
A look at the stacktrace told me, that it was coming from inside the method com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker.isValidConnection, so naturally, I dived into the sources for that file (aah, the wonders of open source). This is from the 3.1.14 version of ConnectorJ:
public MysqlValidConnectionChecker() {
....
Class mysqlConnection = Thread.currentThread()
.getContextClassLoader().loadClass(
"com.mysql.jdbc.Connection");
pingMethod = mysqlConnection.getMethod("ping", null);
....
}
public SQLException isValidConnection(Connection conn) {
if (pingMethod != null) {
try {
this.pingMethod.invoke(conn, NO_ARGS_OBJECT_ARRAY);
return null;
} catch (Exception ex) {
if (ex instanceof SQLException) {
return (SQLException) ex;
}
return new SQLException("Ping failed: " + ex.toString());
}
}
...
}
The interesting part is the this.pingMethod.invoke(conn, NO_ARGS_OBJECT_ARRAY) call, which was failing. Sadly, if you look at the catch block, it does not preserve or log the stacktrace of that exception (the ex instance), so I had to built a version of the driver myself.
After some trials, what I found was, that the Connection class, that is loaded in the constructor (the class from which the cached Method instance pingMethod is obtained), was coming from a different classloader (a webapp classloader), than the classloader that loaded the conn instance coming in as parameter in the call to isValidConnection. This made the reflection call bomb out.
Why the classloader was different I believe had to do with the way JBoss was started in our setup. It was being started from inside IDEA, which seemed to include the classpath of all the modules of the project.
A simple fix for the driver would be to do this:
Method method = conn.getClass().getMethod("ping", null);
method.invoke(conn, NO_ARGS_OBJECT_ARRAY);
instead of caching the Method instance.
But, who would want to patch the mysql-driver, when we can upgrade?
In ConnectorJ v5.1.x, this has been completely rewritten, to simply do SELECT 1 against the server, instead of trying the ping call on the connection. In v.5.0.x, there is a slightly altered version, though it has the same problem, as the v3.x does.
One other way to avoid the bug, if you are unable to upgrade the driver version, is to disable the connection-checker altogether. You do this by editing your datasource definition deployed in JBoss (typically named mysql-ds.xml) and remove/comment out the element:
<valid-connection-checker-class-name>com.mysql.jdbc.integration.jboss.MysqlValidConnectionChecker</valid-connection-checker-class-name>


Hey Per,
The interesting part is, that I had exact same configuration and setup with code and jars, and mysql did not force the same ping error??.. Still seems strange to me, but it might just be my mac that is concealing it for my console..
-Cheers!
April 16th, 2008 at 20:24/Steffen
Strange it is, indeed!
April 16th, 2008 at 20:35Hello
I got same exception on our server & UI get slower.
I was able to reproduce this exception on my local system.
but didn’t get why UI should go slow .
I have tried mysql-connector-java-5.1.6 & got same behaviour.
Is there any solution to this issue?
Regards
October 9th, 2008 at 10:38Abhijit
@abhijit:
I talked to my colleagues who experienced the problem, and they ended up solving the problem by putting the new mysql driver into the jboss “lib” directory.
October 9th, 2008 at 19:53Abhijit: The UI might get slower because of all the log messages that the bad mysql connector is throwing out and writing in the log. I/O sucks.. but hey thats life!
/Stef
October 9th, 2008 at 19:57The issue is likely that you’re packing your mysql driver jar with the application. It should only exist on the server glonb lib dir in “server/default/lib”, that way it is always loaded with the same class loader.
October 31st, 2008 at 22:50