Final Update:
Bottom line: for the current implementation of JRuby implementing this does not seem possible. A near-future release is supposed to improve on the Java/Ruby integration. In this case what is needed:
- A Java class that is the superclass of all JRuby classes. Similar to the
PyInstance
class (a Java class) in the Jython implementation.
- A Java class that corresponds to a class defined in JRuby such that when instantiated via
newInstance()
in Java also creates a corresponding JRuby instance. Similar to the JythonPropertyHandler
class I defined in Jython, corresponding to the JRubyPropertyHandler
class I attempted to define in JRuby, below.
End Update
Sometimes I drink to forget, and sometimes I just forget. Several years ago I blogged about using JXPath to query Jython objects. Sometime since then I forgot all about JXPath. I remember it now being fairly simple, and working with all kinds of structures. (And so JXPath should be a fairly simple way to use XPath to query JSON objects in Java, BTW.)
I started playing with JRuby recently to see how it's doing. When I came across the Jython code I just mentioned, I thought I'd try the equivalent in Jruby. Here's what I have so far, but I have two question marks preventing it from running. I sent them to the JRuby users list, but if anyone reading this has an answer or a hint, I'd appreciate that.
class JRubyPropertyHandler
include org.apache.commons.jxpath.DynamicPropertyHandler
def getPropertyNames(robject)
return robject.instance_variables.to_java
end
def getProperty(robject, property)
if robject.instance_variables.include?(property)
robject.instance_variable_get(property)
else
nil
end
end
def setProperty(robject, property, value)
robject.instance_variable_set(property, value)
end
def JRubyPropertyHandler.register()
introspector = org.apache.commons.jxpath.JXPathIntrospector
introspector.registerDynamicClass(???, ???)
end
end
It's that call to
registerDynamicClass
(
javadoc) that has me stumped. The first argument is a class of all the instances that should be handled by
JRubyPropertyHandler
.
The second argument ideally should just be JRubyPropertyHandler
. i.e. not an instance of the handler, but the handler class itself.
I tried calling...
introspector = org.apache.commons.jxpath.JXPathIntrospector
introspector.registerDynamicClass(Object, JRubyPropertyHandler)
But these two arguments are each instances of
org.jruby.RubyClass
, not
java.lang.Class
as needed.
In Jython the two arguments to register a handler are PyInstance
, the Java class that is the superclass of all Jython instances, and the handler class itself. The code for my working Jython implementation is on my original blog post.
Update: from the jruby user's mail list, Nick Sieger drops a good hint, and I have more questions until I can get back to a jirb prompt...
> Perhaps this snippet helps?
>
> $ bin/jruby -S irb
> irb(main):001:0> class Foo
> irb(main):002:1> include java.lang.Runnable
> irb(main):003:1> end
> => Foo
> irb(main):004:0> Foo.new.java_class
> => $Proxy7
Thanks. Maybe. I'll look into it when I can get back to my jirb prompt.
That will work for the second argument *if* it implies that when the
jxpath java code creates a new instance of $Proxy7 then what actually
happens is a new jruby instance of Foo is created.
But what does this say about all jruby objects?
i.e. in jruby, they are all instances of the class Object, but if I do
the following...
o = Object.new
j = o.java_class
...then can I assume that all jruby objects are (in java-land)
instances of a java class that inherits from "j"?
Or is the java_class $ProxyN class more of an on-demand, dynamically
generated, bridge to the other world?