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

Comments

Projects
None yet
3 participants
@carlosmrce
//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

This comment has been minimized.

Show comment
Hide comment
@kares

kares Nov 10, 2015

Member

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.

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

This comment has been minimized.

Show comment
Hide comment
@carlosmrce

carlosmrce Nov 10, 2015

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.

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

This comment has been minimized.

Show comment
Hide comment
@kimptoc

kimptoc 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.

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

This comment has been minimized.

Show comment
Hide comment
@carlosmrce

carlosmrce Nov 11, 2015

@kimptoc i get the same error!

@kimptoc i get the same error!

@kimptoc

This comment has been minimized.

Show comment
Hide comment
@kimptoc

kimptoc 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

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

This comment has been minimized.

Show comment
Hide comment
@kares

kares Nov 17, 2015

Member

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
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

This comment has been minimized.

Show comment
Hide comment

kimptoc commented Nov 17, 2015

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

@carlosmrce

This comment has been minimized.

Show comment
Hide comment
@carlosmrce

carlosmrce Nov 17, 2015

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

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

@carlosmrce carlosmrce closed this Nov 17, 2015

@kares kares reopened this Nov 17, 2015

@kares

This comment has been minimized.

Show comment
Hide comment
@kares

kares Nov 17, 2015

Member

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

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 from Passing a ruby class as a generic to Passing a ruby class as a java.lang.Class into Java land Nov 17, 2015

@carlosmrce

This comment has been minimized.

Show comment
Hide comment
@carlosmrce

carlosmrce Nov 17, 2015

@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 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

[ji] when a Ruby Class is being coerced to a Java class - auto-reify …
…(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

@kares kares closed this in #3779 Apr 12, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment