Classloaders in JRuby

Hi everyone,

I am on a project integrating a JRuby on Rails web frontend into a
large existing java codebase. Due to some other requirements, there
are some interfaces that I can’t put on the standard JRuby classpath,
I have to load them using a custom class loader like this:

def load_interface
protocol = “file”
host = “localhost”
filepath = Rails.root.parent + “build/classes”
url = URL.new protocol, host, filepath.to_s.to_java_string
urlcl = URLClassLoader.new([url].to_java java.net.URL)
interfac_ename = "com.company1.Interface1
interface_class = java.lang.Class.forName(interface_name, true,
urlcl)
return interface_class
end

So, this method returns a Java class. Now, I need to get a JRuby
Module m from this Java interface so that I can do call
some_jruby_object.extend(m) because I need to provide an
implementation. I’ve tried calling “JavaUtilities.get_interface_module
interface_class”, but I get an error then:

ArgumentError: expected JavaClass, got interface com.company1.Interface1

I am not sure how to convert the interface that I loaded into an
instance of the JavaClass object. I noticed that there is a
JavaClass.get method, but in addition to the actual class parameter it
also takes a Runtime parameter, and I am not sure where to find that
object. Also, I am not sure whether I am at all going down the right
direction here, and maybe I am missing something obvious that doesn’t
require calling “get_interface_module”.

Thank you!

Hi,

You can access the runtime as “JRuby.runtime” after requiring the
“jruby” library. Although, I tried calling JavaClass.get with a raw
interface class and it also gave me an error (TypeError: cannot
convert instance of class org.jruby.java.proxies.ConcreteJavaProxy to
class java.lang.Class).

In your case, there might be a bug or some unexpected behavior, since
Java class objects should be wrapped by the time they get to Ruby, but
apparently yours isn’t? Have you tried using the resulting
“interface_class” object with Object#extends?

/Nick

I’ve also noticed, with 1.6.4, if I do wicked stuff involving
someClassLoader.loadClass(…), I get back a bare Java class, and not a
JavaClass.

-Bob

On Mon, Oct 24, 2011 at 10:30 AM, Nick S. [email protected]
wrote:

apparently yours isn’t? Have you tried using the resulting
“interface_class” object with Object#extends?

Hi Nick,

Thank you. I did find the runtime method, and managed to get that
part working, but I have encountered a number of related problems
afterwards that I can’t quite figure out. Specifically yes - I’ve
tried using extends, but Java-level objects (specifically a Proxy of
that interface) refuse to recognize the Ruby-level extended object as
an instance of that interface. I am going to try to write up a few
isolated testcases for what I encountered as soon as I get some time.

Aha, so maybe it’s a regression? Or maybe it never worked that way

/Nick