Search code examples
jruby

JRuby: Documentation of mappings/conversions between Java and Ruby types/classes?


I am writing a Java wrapper library around a ruby gem so I am embedding ruby within Java and not the other way around. I seem to be in the vast minority!

If I have a ruby method that returns a Time object then I can very easily convert it into a java.util.Date object on the Java side like this:

public Date getStartTime() {
    IRubyObject result = RuntimeHelpers.invoke(runtime.getCurrentContext(),
        this, "start_time");
    return (Date) result.toJava(Date.class);
}

But I think I got lucky working this out by trial and error and not all like-seeming types can be converted in this way. I have another ruby method that returns a URI object (it could be a URI::HTTP or a URI::HTTPS in fact) but trying the obvious (given the above) conversion to a java.net.URI doesn't work (I also tried it with java.net.URL):

public URI getUri() {
    IRubyObject result = RuntimeHelpers.invoke(runtime.getCurrentContext(),
        this, "uri");
    return (URI) result.toJava(URI.class);
}

This code compiles, but fails at run time:

Exception in thread "main" org.jruby.exceptions.RaiseException: (TypeError) cannot
convert instance of class org.jruby.RubyObject to class java.net.URI

I realise that in ruby a URI is actually a module and URI::HTTPS, etc are the classes, so I'm not entirely surprised that the above didn't work. But there's clearly a bit of internal "magic" being done for the Time/Date example so I was wondering if there were similar conversions provided for other types, which types and where they are documented.

Any pointers much appreciated.


Solution

  • https://github.com/jruby/jruby/wiki/CallingJavaFromJRuby says "Conversion of Types – Ruby to Java – See the JRuby rspec source code dir spec/java_integration for many more examples. [examples, ...]".

    Sure enough, coercion_spec.rb contains a lot of examples/specifications. Here's the case you already use:

    describe "Time\"to_java" do
      describe "when passed java.util.Date" do
        it "coerces to java.util.Date" do
          t = Time.now
          d = t.to_java(java.util.Date)
          d.class.should == java.util.Date
        end
      end
    
      # [...]
    end
    

    I believe this is the best documentation currently available.