JRuby: How does one keep Java objects as Java objects so they can be used in method calls?

S

Steve Drach

I'm trying to use JDOM and JRuby (yes I know about RexML). In the following
program, I get an error when I pass f to sb.build because f is a RubyFile and
not a Java File object. The error I get is:

no method 'build' with argument types matching [org.jruby.RubyFile] (NameError)

What is the correct way to deal with this, I believe, common issue?

Thanks,
Steve

------
require 'java'

class Foo
include_package 'java.io'
include_package 'org.jdom'
include_package 'org.jdom.input'

attr_reader :d

def initialize
sb = SAXBuilder.new
f = File.new "/home/drach/schema/modeler/build.xml"
@d = sb.build f
end
end

foo=Foo.new
 
T

Thomas E Enebo

I'm trying to use JDOM and JRuby (yes I know about RexML). In the following
program, I get an error when I pass f to sb.build because f is a RubyFile and
not a Java File object. The error I get is:

no method 'build' with argument types matching [org.jruby.RubyFile]
(NameError)

What is the correct way to deal with this, I believe, common issue?

Well one way is to create a 'java_alias' ala:

java_alias :JFile, :File

then use 'JFile.new "/etc/blah"'

I actually think that your original code should have worked, but
it doesn't. In ruby:

module One
class File
def initialize(a, b)
end
end
end

Class Two
include One

def foo
p File.new("/etc/motd", "r")
end
end

Will see One::File instead of File. At the surface I would think
that include_package should work similiarly. I will likely change this
behavior before next release unless someone can explain why doing so
would be a bad idea.

-Tom
 
S

Steve Drach

Well one way is to create a 'java_alias' ala:
java_alias :JFile, :File

then use 'JFile.new "/etc/blah"'

Ok, I think I understand. It's because the constant File was already
defined to be the org.jruby.RubyFile class. Is that correct? And
java_alias just deals with Java constants? Is that why alias wouldn't
work, since it would have aliased the RubyFile to JFile? It's all
a little subtle for me.

In any case, it seems to work, and both File and SAXBuilder are
the correctly scoped type (symbol?) now. However it now fails
mysteriously, not telling me which method is missing:

jruby-0.7.0/bin/jruby.sh test.rb
Foo::SAXBuilder
Foo::JFile
Exception in thread "main" java.lang.NoSuchMethodError
at org.jruby.javasupport.JavaSupport.createRaiseException(JavaSupport.java:83)

The new code is:

require 'java'

class Foo
include_package 'java.io'
include_package 'org.jdom'
include_package 'org.jdom.input'

java_alias :JFile, :File

attr_reader :d

def initialize
sb = SAXBuilder.new
p sb.class
f = JFile.new "/home/drach/schema/modeler/build.xml"
p f.class
@d = sb.build f
end
end

foo = Foo.new
 
T

Thomas E Enebo

Ok, I think I understand. It's because the constant File was already
defined to be the org.jruby.RubyFile class. Is that correct? And
java_alias just deals with Java constants? Is that why alias wouldn't
work, since it would have aliased the RubyFile to JFile? It's all
a little subtle for me.

yep. I was not the designer of the java integration so I can only
make an educated guess, but I think a decision was made to lazily
load classes from an imported package when they are actually used.
It implements this via const_missing. Obviously, for File, const_missing
is never fired, so I think they made java_alias as a way around this
problem. I sent some more thoughts on this to jruby-dev last night.
Any continued conversation about this should probably continue there.
In any case, it seems to work, and both File and SAXBuilder are
the correctly scoped type (symbol?) now. However it now fails
mysteriously, not telling me which method is missing:

In the current CVS tree I think this problem is fixed (along
with many others). I tried running your script (using another
xml file) and I did not get your error (no news is good news? :)).

A problem was corrected where it was not properly finding the
correct overloaded method in a java class. SaxBuiler.build has
a about thousand versions, so I am guessing it has tripped over that
bug.

-Tom

PS- Could you send any other jruby questions to jruby-user or
jruby-dev (hosted by sourceforge)? It will make jruby not look
so dead :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top