I'm using JRuby 1.7.1 with a Rails 3.2.9 application. The application
uses
Java code in a JAR file which is loaded via a 'require' statement.
When I execute some JRuby code that uses the Java classes in the rails
console things work fine. However, when I execute that same JRuby code
via
a Rails controller action running with "rails s" I get an error related
to
trying to dynamically load an HSQLDB JDBC driver.
The relevant portion of the stacktrace:
Cannot create JDBC driver of class '' for connect URL
'jdbc:hsqldb:file:/private/var/folders/ww/__zw8nvj6blfn0tfgvs1gs240000gq/T/1357181247259-0/data/'
java.sql.SQLException: No suitable driver
at java.sql.DriverManager.getDriver(DriverManager.java:264)
at
org.apache.commons.dbcp.BasicDataSource.createConnectionFactory(BasicDataSource.java:1437)
at
org.apache.commons.dbcp.BasicDataSource.createDataSource(BasicDataSource.java:1371)
at
org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
Looking at the DriverManager.java source it seems that this could be a
ClassLoader issue, but I'm unsure as to what the differences are in the
Java environment when executing this code in the rails console versus
the
rails server (which is using the Puma webserver) which might cause this
behavior.
Can anyone enlighten me on this or point me to some docs that describe
the
differences between console and server? Any suggestions for
troubleshooting would be much appreciated as well.
Thanks,
Chris
on 2013-01-03 21:43
on 2013-01-03 22:22
What version of AR-JDBC (activerecord-jdbc-adapter and jdbc-hsqldb) are you using? We've had some "noise" in the recent releases, which may be the culprit.
on 2013-01-03 22:25
Anthony, I'm not doing any ActiveRecord stuff in the JRuby code presently, so I don't have either of those gems installed. The HSQLDB stuff is happening way down in the Java code that I'm loading from the JAR. Do you think adding the AR-JDBC and HSQLDB gems would make a difference when I run under the server process? As I said, the code works perfectly when I invoke it from the console. Cheers, Chris
on 2013-01-03 23:06
Generally you can't rely on DriverManager to find driver classes in a server process. The problem is an issue related to dynamic classloaders and DriverManager, where DriverManager can't find any SQL drivers that aren't present on the JVM's boot classpath. It's best to just directly instantiate the relevant driver class versus using DriverManager to find things. This is how all the major JRuby database libraries do things as well - some first attempt to use DriverManager and fall back on direct instantiation and some just skip DriverManager entirely. If you really want to use DriverManager, you'll have to ensure that the HSQLDB driver is on the JVM's classpath when it boots. Ben
on 2013-01-03 23:20
Ben, I think you're spot on with this analysis. There is some code that dynamically loads a "legacy" version of the HSQLDB driver as part of a data-migration process. I don't think that driver is on the boot classpath and is only loaded if needed to do the migration. So is there a difference between the JVM's boot classpath between running "rails console" and running "rails server"? I would love to test this theory somehow. I very much appreciate your help! Chris
on 2013-01-03 23:47
Ben, One other thought. I saw this SO post: http://stackoverflow.com/questions/11548035/jruby-... I thought I'd try the same, but looking into it I found, I think, that the HSQLDB driver is actually called org.hsqldb.jdbcDriver And with the driver name starting in lowercase I couldn't use java_import to try to add it to the classpath. This isn't an inner class name, so is there a workaround to get JRuby to gracefully handle jdbcDriver? Chris
on 2013-01-04 00:30
I was able to actually get the driver loaded by using the technique in the Stack Overflow post listed below. The trick was using the Java for_name call since JRuby wasn't happy with the lowercase jdbcDriver name that HSQLDB uses. The code executes properly in both rails server and console now. Thanks for your help! Chris
on 2013-01-04 00:52
Great - glad you it working. I don't really know the details of Puma to know why this specific trick works, but if you were to deploy this application to a Java-based server such as Tomcat, Trinidad, or TorqueBox you'd still hit a classloading issue with DriverManager and need to instantiate the drivers directly or add them to the JVM's boot classpath. Ben
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.