Can't execute method of Java object from Ruby


#1

jruby 9.0.4.0 (2.2.2) 2015-11-12 b9fb7aa Java HotSpot™ 64-Bit Server
VM 24.79-b02 on 1.7.0_79-b15 +jit [Windows 7-amd64]

I have the following Java class:

==================================================
class JC {
private Integer vi;
public JC(int i) { vi = new Integer(i); }
public void square() { vi = vi*vi; }
public Integer get_int() { return vi; }
}

I create (in the Java part of my code) an object of this class, and pass
it to a Ruby method. On the Ruby side, I find that I can’t invoke the
method ‘square’, even though the object seems to be of the right type:

==================================================
include Java

class RCconn

def initialize
@doer = RC.new
end

def dispatch(jc)
puts “Received object of type #{jc.class}”
jc.square
# @doer.do_your_duty(jc)
jc
end

end

Inside dispatch, I get:

Received object of type Java::Default::JC
NoMethodError: undefined method `square’ for
#Java::Default::JC:0xa124e5
dispatch at …

What did I do wrong?


#2

Ronald,

Put the public modifier before your java class:

public class JC {
private Integer vi;
public JC(int i) { vi = new Integer(i); }
public void square() { vi = vi*vi; }
public Integer get_int() { return vi; }
}

Move it to its own file and try again. The method, as you have it, is
not accessible to Ruby.

Cris


#3

Cris S. wrote in post #1179417:

Ronald,

Put the public modifier before your java class

Waaaaa! This works!!!

Could you explain, please, why this is necessary? I had JC defined in
its own file before, and I could executed all its methods (they are
public, after all) from my Java application. Why, then, can’t Ruby see
it? Does this have to do with package visibility? But I didn’t use any
package declaration.

Ronald


#4

Since you are all setup with this example…

Answer for me a question.

JRuby has the java_package method. If you set your Ruby class to the
same package can you access your method w/o the public modifier?

Cris


#5

The other java files were in the same package, so they can see the
package level methods.

The private, protected, public (and java has no modifier – package
access (or friendly)) are a bit different then Ruby. I came from the
java side first and I often get confused on the Ruby side :-).

Cris


#6

Cris S. wrote in post #1179422:

JRuby has the java_package method. If you set your Ruby class to the
same package can you access your method w/o the public modifier?

It didn’t work, but I’m not sure, whether I did it in a right way. Since
the Java class JC is in the global namespace, I added to my Ruby file
after the include Java:

java_package ''

But maybe this is not the correct way to specify the global namespace. I
searched several places for an explanation of how java_package works,
but they don’t explain handling the global namespace.


#7

I’m still fighting with how to do packages properly in Java (I’ve opened
a thread on this at
http://www.javaprogrammingforums.com/whats-wrong-my-code/46314-can-not-access-name-same-package-but-different-file-beginners-question.html)

  • maybe, if you have time, you could have a look. It seems to be more
    difficult than expected, and as soon as I have a solution for this, I
    will try out java_package.

Ronald


#8

I am not sure either how one would handle an unnamed package. I suspect
you might have to package your code.

Cris


#9

Ronald,

Are you aware that in java package structures mandate that your file be
in an appropriate directory or compilation fails?

If you have package ‘phee.phi.pho’ Then class ‘Phum’ must be in the
directory phee/phi/pho. It must be in a file named Phum.java if it is
has the public modifier before the keyword class.

Cris


#10

Cris S. wrote in post #1179475:

Are you aware that in java package structures mandate that your file be
in an appropriate directory or compilation fails?

I thought this is just a convention. It is strange: The compiler could
see that the package name does not match the filename, but it did not
complain (“file in a wrongly named directory” or something like this)
when I compiled it.

I will try to modify my example and let you know the findings.

Ronald


#11

Cris S. wrote in post #1179475:

If you have package ‘phee.phi.pho’ Then class ‘Phum’ must be in the
directory phee/phi/pho. It must be in a file named Phum.java if it is
has the public modifier before the keyword class.

I have now restructured file structure and code accordingly, but running
the program now doesn’t find the main class.

I have attached all files to this message (jr7.zip), in case you would
like to hava a look. On Windows, I would run it by executing jr7.bat.

I have also isolated the error, since it is not related to java_import,
and posted the problem here:

http://www.javaprogrammingforums.com/whats-wrong-my-code/46321-main-program-not-found.html


#12

OK, fixed it now. There were several small changes necessary, which were
not obvious - at least not to me. You find the updated test case in the
attachment.

As for the java_package on the Ruby side: This did not work as expected.
I get the error message

NameError: cannot load Java class DoIt

I then changed back

java_import ‘DoIt’ do …

to

java_import ‘foo.DoIt’ do …

(although I think this should not be necessary, because we have a
java_package ‘foo’ before that), but same effect.