Forum: JRuby Is it possible to override a method in a Java class

Posted by James Britt (Guest)
on 2013-01-26 19:26
(Received via mailing list)
Hey all.

Is it possible, in a JRuby app, to override a method in a Java class?

For example, given a Java class com.foo.Bar that has some method m, I
want to change the behavior of m.

I know I can do this in a subclass, but I want to alter the behavior of
the Java class itself.

Thanks,

James Britt

--

Neurogami - Avant-garage Research & Development

http://www.neurogami.com

james@neurogami.com
Posted by Dave Liebreich (Guest)
on 2013-01-26 20:00
(Received via mailing list)
Yes, I did this:

com.myco.MyClass.class_eval do
  alias :real_myMethod :myMethod
  def myMethod *args
    # do stuff
    real_myMethod *args
    # do other stuff
  end
end

and it seemed to work. jruby 1.7.0 jdk7u11

-Dave

aside:
I used this approach to display the ruby call stack when a java 
exception was thrown inside the method. The code I wrote looks like:

def myMethod *args
  begin
    real_myMethod *args
  rescue Exception
    puts 'exception caught in method execution - dumping ruby call 
stack'
    caller.each do |st|
      puts st
    end
    raise
  end
end

Please let me know if you have any comments or suggestions for 
improvement
Posted by Lei Gao (gaolei)
on 2013-01-26 20:10
(Received via mailing list)
This might not work, as real_myMethod will not only invoke by Ruby code, 
it also can be invoked inside Java code too.

Lei Gao



From: Dave Liebreich <dave.liebreich@gmail.com>
To: user@jruby.codehaus.org
Sent: Saturday, January 26, 2013 10:59 AM
Subject: Re: [jruby-user] Is it possible to override a method in a Java 
class


Yes, I did this:

com.myco.MyClass.class_eval do
 alias :real_myMethod :myMethod
 def myMethod *args
  # do stuff
  real_myMethod *args
  # do other stuff
 end
end

and it seemed to work. jruby 1.7.0 jdk7u11

-Dave

aside:
I used this approach to display the ruby call stack when a java 
exception was thrown inside the method. The code I wrote looks like:

def myMethod *args
 begin
  real_myMethod *args
 rescue Exception
  puts 'exception caught in method execution - dumping ruby call stack'
  caller.each do |st|
   puts st
  end
  raise
 end
end

Please let me know if you have any comments or suggestions for 
improvement
On Saturday, January 26, 2013 at 10:24 AM, James Britt wrote:
Hey all.
Posted by Keith B. (keith_b)
on 2013-01-26 23:37
(Received via mailing list)
Dave -

I'm surprised that the modifications you made worked. I suspect that 
JRuby added a wrapper class around the Java class, and modified that 
wrapper.
I'm pretty sure that class modifications of a Java class in Ruby code 
would be seen only on the Ruby side.

Given that it did work, though, I suspect that the Java class accessed 
in Java code would ignore the modifications.

It should be pretty easy to put together a test, but I don't have time 
at the moment.

- Keith

---
Keith R. Bennett
http://about.me/keithrbennett
Posted by Keith B. (keith_b)
on 2013-01-26 23:38
(Received via mailing list)
Dave -

I'm surprised that the modifications you made worked. I suspect that 
JRuby added a wrapper class around the Java class, and modified that 
wrapper.
I'm pretty sure that class modifications of a Java class in Ruby code 
would be seen only on the Ruby side.

Given that it did work, though, I suspect that the Java class accessed 
in Java code would ignore the modifications.

It should be pretty easy to put together a test, but I don't have time 
at the moment.

- Keith

---
Keith R. Bennett
http://about.me/keithrbennett
Posted by Dave Liebreich (Guest)
on 2013-01-27 00:24
(Received via mailing list)
Yes, I did not need the modifications to work when the original java 
method was called from java code. I only needed them to be in place when 
the method was called from jruby code. Since the original request 
mentioned "in a JRuby app", I thought my approach might help.

-Dave
Posted by Keith B. (keith_b)
on 2013-01-27 00:51
(Received via mailing list)
Dave -


On Jan 26, 2013, at 6:23 PM, Dave Liebreich <dave.liebreich@gmail.com> 
wrote:

> Yes, I did not need the modifications to work when the original java method was 
called from java code. I only needed them to be in place when the method was 
called from jruby code.

Oh, I see.


> Since the original request mentioned "in a JRuby app", I thought my approach 
might help.

Yes, hopefully it would.  However, "a JRuby app" can make heavy use of 
Java libraries that use callbacks.  For example, my "Game of Life 
Viewer" (article: 
http://www.bbs-software.com/blog/2012/09/05/conway..., 
code: https://github.com/keithrbennett/life_game_viewer) is a JRuby app 
that uses Java Swing for the GUI framework.  Swing makes heavy use of 
callbacks.

So that's an example of a JRuby app in which the 
directly-modify-Java-class approach would not work (I don't think), 
whereas the subclass-Java-class approach would. Pretty cool what you did 
though.

Thanks,
Keith
Posted by Keith B. (keith_b)
on 2013-01-27 00:52
(Received via mailing list)
Dave -


On Jan 26, 2013, at 6:23 PM, Dave Liebreich <dave.liebreich@gmail.com> 
wrote:

> Yes, I did not need the modifications to work when the original java method was 
called from java code. I only needed them to be in place when the method was 
called from jruby code.

Oh, I see.


> Since the original request mentioned "in a JRuby app", I thought my approach 
might help.

Yes, hopefully it would.  However, "a JRuby app" can make heavy use of 
Java libraries that use callbacks.  For example, my "Game of Life 
Viewer" (article: 
http://www.bbs-software.com/blog/2012/09/05/conway..., 
code: https://github.com/keithrbennett/life_game_viewer) is a JRuby app 
that uses Java Swing for the GUI framework.  Swing makes heavy use of 
callbacks.

So that's an example of a JRuby app in which the 
directly-modify-Java-class approach would not work (I don't think), 
whereas the subclass-Java-class approach would. Pretty cool what you did 
though.

Thanks,
Keith
Posted by James Britt (Guest)
on 2013-01-27 06:46
(Received via mailing list)
Keith Bennett wrote:
> that uses Java Swing for the GUI framework.  Swing makes heavy use of
> callbacks.
>
> So that's an example of a JRuby app in which the
> directly-modify-Java-class approach would not work (I don't think),
> whereas the subclass-Java-class approach would. Pretty cool what you did
> though.


Thanks very much for these answers.

I spent more time looking into this, adding yet more proof that the
surest way to solve a problem is to post a question about it because
inevitable (well, maybe) one then figures it out.


Turns out that i was not able to get my code to work at first because I
was not correctly addressing the class of interest. Instead I was
creating a new class; the intended target of this code was unaware.

Once I was able to refer to the correct class I did this:

     class Java::ComLeapmotionLeap::Frame
       alias_method :leap_hands, :hands

       def hands
         hands = leap_hands
         # My own nefarious code here
         # ...
       end

     end

In actual use a Frame object (created by third-party Java code) is
passed to a callback method  (onFrame) that has to be defined in a
Listener  class that handles the callback.  In my JRuby app that class
is sub-classed from a Java class.  The objects (and sub-objects) it gets
passed though can be already modified with whatever enhancements I see
fit.  Which, of course, is very cool.


Thanks again!


James
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.