Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Passing a ruby class as a java.lang.Class into Java land #3454

Closed
carlosmrce opened this issue Nov 10, 2015 · 10 comments · Fixed by #3779
Closed

Passing a ruby class as a java.lang.Class into Java land #3454

carlosmrce opened this issue Nov 10, 2015 · 10 comments · Fixed by #3779

Comments

@carlosmrce
Copy link

//Job.java
package br.eti.mribeiro;

public interface Job {
    void teste();
}


//Teste.java
package br.eti.mribeiro;

public class Teste {
    public void executaJob(Class<? extends Job> classe){
        try {
            Job job = classe.newInstance();
            job.teste();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

#jruby_teste.rb
require File.join(File.dirname(File.expand_path(__FILE__)), 'teste_jruby.jar')

java_import 'br.eti.mribeiro.Job'
java_import 'br.eti.mribeiro.Teste'

class TesteJob
  include Job
  def teste
    puts "123456"
  end
end
Teste.new.executaJob(TesteJob.class)

I guess the code above is pretty self explaining, i hava a Ruby class that implements a Java interface, and i want to pass that class back to another Java class. However, when a execute the ruby code i get the following error:

java.lang.InstantiationException: org.jruby.RubyClass
        at java.lang.Class.newInstance(Class.java:359)
        at br.eti.mribeiro.Teste.executaJob(Teste.java:6)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at org.jruby.javasupport.JavaMethod.invokeDirectWithExceptionHandling(JavaMethod.java:452)
        at org.jruby.javasupport.JavaMethod.invokeDirect(JavaMethod.java:313)
        at org.jruby.java.invokers.InstanceMethodInvoker.call(InstanceMethodInvoker.java:45)
        at org.jruby.runtime.callsite.CachingCallSite.cacheAndCall(CachingCallSite.java:313)
        at org.jruby.runtime.callsite.CachingCallSite.call(CachingCallSite.java:163)
        at teste.invokeOther18:executaJob(teste.rb)
        at teste.RUBY$script(teste.rb:14)
        at java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:599)
        at org.jruby.ir.Compiler$1.load(Compiler.java:111)
        at org.jruby.Ruby.runScript(Ruby.java:822)
        at org.jruby.Ruby.runScript(Ruby.java:814)
        at org.jruby.Ruby.runNormally(Ruby.java:752)
        at org.jruby.Ruby.runFromMain(Ruby.java:574)
        at org.jruby.Main.doRunFromMain(Main.java:409)
        at org.jruby.Main.internalRun(Main.java:304)
        at org.jruby.Main.run(Main.java:231)
        at org.jruby.Main.main(Main.java:200)

Shouldn't this work?

ps: teste_jruby.jar is a jar file i exported with the java code.

Thanks,
Carlos.

@kares
Copy link
Member

kares commented Nov 10, 2015

unfortunately, java support currently does not go that far - you can not instantiate a Ruby defined class on Java's side as class.newInstance() ... probably possible to implement to some extent although tricky.

@carlosmrce
Copy link
Author

Ouch!!! This will force me to write a bunch of messy java-ruby bridges. The lack of this feature basically males impossible to use a bunch of java libraries from ruby. Looking forward to this being implemented.

@kimptoc
Copy link

kimptoc commented Nov 11, 2015

You could write your Teste class in Ruby and then your code would work like this:

Teste.new.executaJob(TesteJob) # don't specify .class

But I guess it depends what else you are doing as to whether that is valid.

@carlosmrce
Copy link
Author

@kimptoc i get the same error!

@kimptoc
Copy link

kimptoc commented Nov 11, 2015

@carlosmrce hmm - worked for me :) . The Ruby Teste class I used was something like this:

class Teste 
    def executaJob(classe)
        begin
            job = classe.new
            job.teste
        rescue Exception => e
           puts e.message
        end
    end
end

@kares
Copy link
Member

kares commented Nov 17, 2015

also, should be able to "over-come" the limitation by forcing a Java-class to be generated for the Ruby one:

class TesteJob
  include Job
  def teste
    puts "123456"
  end
end
teste_jclass = TesteJob.become_java!
Teste.new.executaJob( teste_jclass )
# teste_jclass.newInstance works fine

@kimptoc
Copy link

kimptoc commented Nov 17, 2015

become_java! - interesting, thanks for that. https://github.com/jruby/jruby/wiki/GeneratingJavaClasses

@carlosmrce
Copy link
Author

Thanks a lot for the tip @kares !!! Solved the problem for me!

@kares kares reopened this Nov 17, 2015
@kares
Copy link
Member

kares commented Nov 17, 2015

still would be useful to get this working out-of-the box (without an explicit become_java!)

@kares kares changed the title Passing a ruby class as a generic Passing a ruby class as a java.lang.Class into Java land Nov 17, 2015
@carlosmrce
Copy link
Author

@kares I got another error

C:>jruby teste.rb
rubyobj.TesteJob
br/eti/mribeiro/Teste.java:8:in executaJob': java.lang.AbstractMethodError: rubyobj.TesteJob.teste()V from java/lang/reflect/Method.java:497:ininvoke'
from teste.rb:15:in <top>' from java/lang/invoke/MethodHandle.java:625:ininvokeWithArguments'

It breaks on the line 'job.teste();'

kares added a commit that referenced this issue Apr 6, 2016
…(closing #3454)

... much less confusing than for user classes to see the nearest reified class in the inheritance hierarchy (without explicitly doing `become_java!`)
@kares kares added this to the JRuby 9.1.0.0 milestone Apr 6, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants