Forum: JRuby Can't execute method of Java object from Ruby

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-20 13:30
jruby 9.0.4.0 (2.2.2) 2015-11-12 b9fb7aa Java HotSpot(TM) 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?
3b8ad006781b1a3ab36dc76e2a05ce9c?d=identicon&s=25 Cris Shupp (cshupp)
on 2015-11-20 15:49
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
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-20 16:20
Cris Shupp 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
3b8ad006781b1a3ab36dc76e2a05ce9c?d=identicon&s=25 Cris Shupp (cshupp)
on 2015-11-20 18:18
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
3b8ad006781b1a3ab36dc76e2a05ce9c?d=identicon&s=25 Cris Shupp (cshupp)
on 2015-11-20 18:21
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
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-23 11:40
Cris Shupp 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.
3b8ad006781b1a3ab36dc76e2a05ce9c?d=identicon&s=25 Cris Shupp (cshupp)
on 2015-11-23 15:23
I am not sure either how one would handle an unnamed package.  I suspect
you might have to package your code.

Cris
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-23 17:16
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-m...)
- 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
3b8ad006781b1a3ab36dc76e2a05ce9c?d=identicon&s=25 Cris Shupp (cshupp)
on 2015-11-23 17:53
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
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-23 18:17
Cris Shupp 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
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-24 10:26
Attachment: jr7.zip (2 KB)
Cris Shupp 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-m...
0fa73332c8e4a3b06ea439fd3f034322?d=identicon&s=25 Ronald Fischer (rovf)
on 2015-11-24 12:41
Attachment: jr7.zip (2 KB)
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.
This topic is locked and can not be replied to.