-
-
Notifications
You must be signed in to change notification settings - Fork 942
Closed
Milestone
Description
The Vert.x 3 Ruby lang integration uses java_class.declared_method for dispatching the Ruby Vert.x API to the Java Vert.x API.
The JavaMethod object does not wrap the returned objects instance of JavaObject, so such objects are not usable from JRuby as they are and must be rewrapped with their corresponding JRuby wrappers.
The current implementation extends the returned JavaMethod object to avoid such issues:
public class ConvertingJavaMethod extends JavaMethod {
private final Class boxedReturnType;
private final JavaUtil.JavaConverter returnConverter;
public ConvertingJavaMethod(Ruby runtime, Method method) {
super(runtime, method);
method.setAccessible(true);
if (method.getReturnType().isPrimitive() && method.getReturnType() != void.class) {
this.boxedReturnType = CodegenUtils.getBoxType(method.getReturnType());
} else {
this.boxedReturnType = method.getReturnType();
}
returnConverter = JavaUtil.getJavaConverter(method.getReturnType());
}
@Override
public IRubyObject invoke(IRubyObject[] args) {
IRubyObject ret = super.invoke(args);
if (ret instanceof JavaObject) {
ret = convertReturn(((JavaObject) ret).getValue());
}
return ret;
}
private IRubyObject convertReturn(Object result) {
if (result != null && result.getClass() != boxedReturnType) {
// actual type does not exactly match method return type, re-get converter
// FIXME: when the only autoconversions are primitives, this won't be needed
return JavaUtil.convertJavaToUsableRubyObject(getRuntime(), result);
}
return JavaUtil.convertJavaToUsableRubyObjectWithConverter(getRuntime(), result, returnConverter);
}
}
Such code is used in such way:
(Java::IoVertxLangJruby::Helper.fixJavaMethod(@j_del.java_class.declared_method(:runOnContext,Java::IoVertxCore::Handler.java_class))).invoke(@j_del,Proc.new { yield })
(the helper transforms the JavaMethod returned by declared_method to ConvertingJavaMethod)
The current code needs to use method.setAccessible(true) otherwise some Vert.x methods cannot be invoked leading to a runtime error like:
org.jruby.exceptions.RaiseException: (TypeError) illegal access on 'complete': Class org.jruby.javasupport.JavaMethod can not access a member of class io.vertx.core.impl.FutureImpl with modifiers "public"
at org.jruby.javasupport.JavaMethod.invoke(org/jruby/javasupport/JavaMethod.java:257)
at RUBY.complete(/Users/julien/java/vertx-lang-ruby/target/classes/vertx/future.rb:72)
Reactions are currently unavailable