Calling a overloaded static java method which accepts an interface as a parameter

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

As luck would have it, I was closing down the way too many browser tabs
I
had open, and something in one of them caught my eye which helped me
answer
my own question. If I change the second parameter of java_send to:

[org.apache.commons.configuration.Configuration.java_class] (note the
‘java_class’ message that gets tacked on the end), everything works just
fine!

I don’t really understand how this works – if
org.apache.commons.configuration.Configuration is in fact an
org.jruby.RubyModule (printing out the results of messaging
class.namespits out merely ‘Module’), I would have expected to see a
java_class
message in the RubyModule API doc, but I don’t. I suppose jruby is
mixing
this behavior into Module elsewhere? At any rate, the code is now
working,
and I can sleep soundly.

Sorry for the noise!

Mark