Hi All,
I’m trying to call com.thinkaurelius.titan.core.TitanFactory.open with a
single parameter. The open method has two single parameter signatures,
one
which accepts a String, and one which accepts an interface
(org.apache.commons.configuration.Configuration). I want to call the
latter, so I’m attempting to do this using java_send:
args =
[java.lang.Class.for_name(“org.apache.commons.configuration.Configuration”)]
graph = com.thinkaurelius.titan.core.TitanFactory.java_send(:open, args,
@config)
I’m using java.lang.Class.for_name to populate the array used in the
second
parameter, because if I don’t (for example, if I instead do
args = [org.apache.commons.configuration.Configuration]
), I get “TypeError: cannot convert instance of class
org.jruby.RubyModule
to class java.lang.Class”. StackOverflow tells me “This is because java
interfaces become Ruby Modules by default and the second argument to
:java_method expects an array of Class objects” (
java - JRuby calls the wrong method - Stack Overflow).
But here’s what happens with Class.for_name:
LoadError: load error: /Users/mccraw/Documents/RubySolstice/app/titan –
java.lang.ClassNotFoundException:
org/apache/commons/configuration/Configuration
The JRuby wiki FAQ (FAQs · jruby/jruby Wiki · GitHub) tells me:
"When JRuby runs at the command line, it loads into the bootstrap class
loader. This class loader lives above CLASSPATH, so libraries you add to
CLASSPATH are not normally visible. Because Class.forName uses the class
loader of the nearest non-system class that called it, it ends up seeing
JRuby as the caller and looking for classes only in CLASSPATH.
The workaround for this is simple: Uuse JRuby’s import or include_class
methods to load the class, or just reference it directly as in
Java::my.package.MyClass or org.postgresql.Driver"
This jives with something else I’ve noticed, which is that if I jar up
all
my ruby code into a jar whose manifest has the apache commons
configuration
jar in its classpath, the code works great. Oddly though, even if I
launch
jruby with -I/path/to/dir/containing/commons-configuration.jar, I still
get
the ClassNotFoundException. Note that in the class containing this
code,
I’m requiring the jar explicitly:
Dir[“#{Main.root}/titan-0.2.0/lib/*.jar”].each
{ |jar| require jar }
So one way, the class loader can’t seem to see it, and the other way,
JRuby
seems to convert it to a module. I have googled my brains out and am
fresh
out of crazy variants to try. Surely people are calling methods that
accept interfaces as parameters. Is there some standard way to handle
this
that I’ve missed?
Thanks so much!
Mark