-
Notifications
You must be signed in to change notification settings - Fork 914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unable to load a StatementInterceptor #5471
Comments
Where and how do you define/load your custom class/jar? The reason I ask is that I think it's a problem of "what is loaded when". Thing is, the JDBC driver jar is only loaded the first time a connection is established. Now if you do something with your custom class before that, it cannot be loaded since it can't find the MySQL JDBC stuff. And then when the MySQL stuff is available, your class is not... You can force these to be available by simply doing require 'jdbc/mysql'
::Jdbc::MySQL.load_driver(:require) before you load your custom class. Another thing: for Rails 5.1.x you should use activerecord-jdbc-adapter 51.x (currently 51.2) instead of 50.x |
In our first initializer, we In require 'java'
require 'jdbc/mysql'
Jdbc::MySQL.load_driver(:require)
java_import "com.mysql.jdbc.StatementInterceptorV2"
java_import "com.mysql.jdbc.ResultSetInternalMethods"
java_import "com.mysql.jdbc.Statement"
java_import "com.mysql.jdbc.Connection"
java_import "java.util.Properties"
java_import "java.sql.SQLException"
java_package "com.example.mysql"
class MyStatementInterceptor
java_implements com.mysql.jdbc.StatementInterceptorV2
java_signature 'void init( Connection connection, Properties properties )'
def init _, _
nil
end
java_signature 'void destroy()'
def destroy
end
java_signature 'boolean executeTopLevelOnly()'
def executeTopLevelOnly
true
end
java_signature 'ResultSetInternalMethods preProcess( String sql, Statement interceptedStatement, Connection connection ) throws SQLException'
def preProcess _, _, _
nil
end
java_signature 'ResultSetInternalMethods postProcess( String sql, Statement interceptedStatement, ResultSetInternalMethods originalResultSet,
Connection connection, int warningCount, boolean noIndexUsed, boolean noGoodIndexUsed, SQLException statementException ) throws SQLException'
def postProcess _, _, _, _, _, _, _, _
nil
end
become_java!
end I can confirm that MyStatementInterceptor is defined before the first attempt to establish a database connection. I've tried both As for why we're on 50.0, we were impacted by a variation of the issue described in jruby/activerecord-jdbc-adapter#897 and have put off that upgrade until we upgrade to rails 5.2. |
I can reproduce the problem in a fresh rails 5.2 app with the latest
|
Wow - I owe you a beer. I'm going to close this issue as you've been able to rework the example to successfully load. If you have the time, @dr-itz, I'd love you're opinion on whether you consider any of the following bugs that deserve their own independent issues filed:
|
@JasonLunn I agree there's room for improvement, especially 3. and 5. btw. here's how I debugged this since I basically had no idea about the whole thing (my first wrong assumption was based on AR-JDBC being involved, then I got curios):
anyway, it was kinda fun 😸 |
@enebo - any preference on whether the feature requests / documentation enhancements above are filed together vs separately? |
@JasonLunn file each separately (and possibly just update the wiki for 2 if you understand point of the parameter). |
I'll open issues for the topics mentioned above that aren't covered by the wiki update later today. |
Thanks again, @dr-itz - I've opened issues and updated the wiki based on your work. Please let me know if you spot any omissions or misstatements. |
Prelude
MySQL Connect Java supports an interceptor pattern for specifying classes to use to preprocess SQL commands or postprocess results. Its easy to configure from rails by appending something like:
to the db properties in
database.yml
. The above example uses a class provided inside the MySQL jar and works without issue.Specifying a StatementInterceptor class defined in JRuby fails with the error message:
I'm assuming that I'm running into a classloader issue, but since (I think?) the MySQL Connector J is being loaded by JRuby via the
jdbc-mysql
gem, I thought the classloader used by the MySQL jar would be able to see any JRuby defined classes. I've tried defining the class with and without an explicit package without a change in results.I've already been able to confirm (via
jrubyc
) that the class I defined properlyimplements
com.mysql.jdbc.StatementInterceptorV2
and provides valid methods with appropriate type signatures.Is this a bug, am I doing it wrong, or is this a limitation of JRuby?
Environment
rails
5.1.6jdbc-mysql
5.1.46activerecord-jdbc-adapter
50.0activerecord-jdbcmysql-adapter
50.0Expected Behavior
I expected Java code loaded by a Ruby gem to be able to invoke
Class.forName
and successfully load a Java class that was defined by JRuby.Actual Behavior
The text was updated successfully, but these errors were encountered: