Error: could not coerce to class java.lang.Object

Should this program work?


import org.jruby.embed.ScriptingContainer;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.javasupport.JavaEmbedUtils.EvalUnit;
import org.jruby.runtime.builtin.IRubyObject;

public class jruby_test {
public static void main(String[] args) {
System.setProperty(“jruby.home”, “<>”);
ScriptingContainer container = new ScriptingContainer();
EvalUnit unit = container.parse(“require ‘complex’; return
Complex.new(3,4)”);
IRubyObject ret = unit.run();
Object o = JavaEmbedUtils.rubyToJava(ret);
System.out.println(o);
}
}

I get:

:1: could not coerce Complex to class java.lang.Object (TypeError) Exception in thread "main" org.jruby.embed.EvalFailedException: could not coerce Complex to class java.lang.Object at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:116) at jruby_test.main(jruby_test.java:11) Caused by: org.jruby.exceptions.RaiseException: could not coerce Complex to class java.lang.Object at (unknown).new(:1) at (unknown).(unknown)(:1) jruby_test.java:11 is the line IRubyObject ret = unit.run(); I guess I might have to call JavaEmbedUtils from inside the script? It would make my life easier if I could do this from the java side. Adam --------------------------------------------------------------------- To unsubscribe from this list, please visit: http://xircles.codehaus.org/manage_email

On Fri, Aug 6, 2010 at 11:15 PM, Adam M. [email protected]
wrote:

        System.setProperty(“jruby.home”, “<>”);
        ScriptingContainer container = new ScriptingContainer();
        EvalUnit unit = container.parse(“require ‘complex’; return Complex.new(3,4)”);
        IRubyObject ret = unit.run();
        Object o = JavaEmbedUtils.rubyToJava(ret);

Well, what are you hoping to get by calling rubyToJava? Normally
that’s used to coerce a Ruby value into an equivalent Java value, like
a Ruby string into a Java string or a Ruby number into a Java number
of some type. For Complex, there’s no “simple” coercion we can use to
produce a Java-typed value, so we error out.

What you have in the IRubyObject ret value actually is the Complex
object in its Ruby form. You can invoke methods on it, but must either
do so from Ruby code or through method-invocation APIs of
ScriptingContainer and friends. Alternatively, you can create your own
Ruby class that implements a known Java interface, and then you’ll be
able to coerce (via rubyToJava) those object instances into that Java
interface.

Using Java libraries from Ruby is obviously easy, but the integration
of the two worlds can get a bit tricky. Have you looked at all the
excellent embedding/scripting examples from the wiki?

  • Charlie

To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

On Sat, Aug 7, 2010 at 7:49 AM, Charles Oliver N.
[email protected] wrote:

Well, what are you hoping to get by calling rubyToJava? Normally
that’s used to coerce a Ruby value into an equivalent Java value, like
a Ruby string into a Java string or a Ruby number into a Java number
of some type. For Complex, there’s no “simple” coercion we can use to
produce a Java-typed value, so we error out.

I plan on running some conversions logic on the Java side after I get
back a Java object. For a lot of objects with no obvious coercion
(like Complex), I’ll just end up converting them to Strings. I was
just hoping to find a way to not have to always explicitly call .to_s
on a Ruby object before returning to Java.

The problem isn’t the rubyToJava call. If I made it that far then I
think I would be fine, because maybe I would do something like this
(this is pseudo code):
Object o;
try {
o = JavaEmbedUtils.rubyToJava(jrubyReturnVal);
}
catch(CoercionException e) {
o = jrubyReturnVal.sendMethod(“to_s”); // or however this would be
coded
}

But it seems the error occurs simply trying to execute a script which
has a final value that can not be coerced. So for example simply
running this code also fails with the same error:

ScriptingContainer container = new ScriptingContainer();
container.runScriptlet(“require ‘complex’; c = Complex.new(3,4)”);

I am surprised by this script failing. On the “Embedding JRuby” wiki
page it says
“Embed Core offers several shortcuts, such as … returning
Java-friendly objects from Ruby code.”
"You can … work directly with return values. These values are
accessible on the Java side as normal Java objects: you’re not forced
to convert everything to strings or primitive types. "

But I am having trouble figuring out how to actually make that happen
with Complex. I’m not sure if I hit a bug in JRuby 1.5.1 or I’m just
doing something wrong.

What you have in the IRubyObject ret value actually is the Complex
object in its Ruby form. You can invoke methods on it, but must either
do so from Ruby code or through method-invocation APIs of
ScriptingContainer and friends.

That would be fine, except like I said the code fails earlier than
expected and I can’t even seem to get back an IRubyObject value.
Ignore my attempt to call rubyToJava, the real question is: How to I
get
IRubyObject ret = unit.run(); or container.runScriptlet(...)
to not fail in this scenario?

Using Java libraries from Ruby is obviously easy, but the integration
of the two worlds can get a bit tricky. Have you looked at all the
excellent embedding/scripting examples from the wiki?

Yes. The wiki info is extremely helpful, and the part I quoted above
made me think what I am trying to do should be possible. I am actually
playing around with JRuby code I wrote a year ago and these problems
I’m running into seem new, so maybe it’s a regression?


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

On Sat, Aug 7, 2010 at 1:02 PM, Adam M. [email protected]
wrote:

Java-friendly objects from Ruby code."
"You can … work directly with return values. These values are
accessible on the Java side as normal Java objects: you’re not forced
to convert everything to strings or primitive types. "

But I am having trouble figuring out how to actually make that happen
with Complex. I’m not sure if I hit a bug in JRuby 1.5.1 or I’m just
doing something wrong.

Ok, I see what you’re hitting. So here’s the thing: runScriptlet’s
contract is that it will produce a coerced/converted Java object. For
return values that can’t coerce, it will error.

However, in most cases, this works ok. It’s trying to coerce things to
java.lang.Object, I believe, which for custom user code just passes
the IRubyObject/RubyObject out directly. For coercible types, they’ll
return the coerced value.

See this pastie for the behavioral difference:

âž” jruby -rcomplex -rjava -e “Complex.new(1,1).to_java”
-e:1:in `to_java’: could not coerce Complex to class java.lang.Object
(TypeError)
from -e:1

âž” jruby -rcomplex -rjava -e “class Foo; end; Foo.new.to_java”

So the problem then is specific to Complex. Or actually, specific to
subclasses of Numeric:

âž” jruby -rrational -rjava -e “Rational(1, 2).to_java”
-e:1:in `to_java’: could not coerce Rational to class java.lang.Object
(TypeError)
from -e:1

I tracked this to the implementation of toJava in RubyNumeric:

@Override
public Object toJava(Class target) {
    return JavaUtil.getNumericConverter(target).coerce(this, 

target);
}

This is probably fixable; we need to modify this coercion to allow
passing out the actual object when the coercion target is
java.lang.Object or similar.

Can you open a bug for this, please?

  • Charlie

To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email

On Sat, Aug 7, 2010 at 11:55 AM, Charles Oliver N.
[email protected] wrote:

Ok, I see what you’re hitting. So here’s the thing: runScriptlet’s
contract is that it will produce a coerced/converted Java object. For
return values that can’t coerce, it will error.

Ok, got it.
Now I wonder, in the case like this:

EvalUnit unit = container.parse(“require ‘complex’; return
Complex.new(3,4)”);
IRubyObject ret = unit.run();

Would it make sense to provide some way to bypass coercion completely?
Or perhaps hook in some custom coercion logic? That might be too
complicated for typical use cases though. If we fix the problem with
Numeric subclasses, I guess I don’t really care about having those
capabilities.

This is probably fixable; we need to modify this coercion to allow
passing out the actual object when the coercion target is
java.lang.Object or similar.

Can you open a bug for this, please?

Sure!
http://jira.codehaus.org/browse/JRUBY-4998

I might take a stab at patching RubyNumeric.toJava() myself. I’ll add
comments to the bug if I find a clean solution.

Thanks for the help. Much appreciated.

Adam


To unsubscribe from this list, please visit:

http://xircles.codehaus.org/manage_email