Question

I'm trying to interface with java classes in a server to use them with ruby, and I need to provide callback classes. Unfortunately, JRuby seems to be trying to coerce a type to itself, and I don't understand why it's doing this and failing trying to do so.

I have the following method in ruby

def registerEvent(id, type, priority = :normal, ignoreCancelled = false, &handler)
  fullClassName = "org.bukkit.event." + type.join(".")
  fullType = java.lang.Class.forName fullClassName

  eventHandler = net.connorcpu.plugscript.EventHandler.new

  eventHandler.setHandlerId id
  eventHandler.setPriority matchToEnum(priority.to_s, org.bukkit.event.EventPriority)
  eventHandler.setEventType fullType
  eventHandler.setIgnoreCancelled ignoreCancelled

  handlerWrapper = EventExecutorWrapper.new(self, handler)
  eventHandler.setExecutor handlerWrapper

  puts eventHandler.java_class.to_s

  $context.registerEvent eventHandler # line 44 from the stacktrace
  return eventHandler
end

Being used like this

registerEvent(
  "edit the quit message because reasons",
  [:player, :PlayerQuitEvent]
) {|event|
  puts 'test message'
}

And when I try to use it, I'm getting the following stacktrace

[21:34:05 WARN]: TypeError: failed to coerce net.connorcpu.plugscript.EventHandler to net.connorcpu.plugscript.EventHandler
  registerEvent at <script>:44
         (root) at <script>:1
            run at SourceFile:617
[21:34:05 ERROR]: [PlugScript] [PlugScript] An exception occurred initializing the script file .\plugins\dev.rb
javax.script.ScriptException: org.jruby.embed.EvalFailedException: (TypeError) failed to coerce net.connorcpu.plugscript.EventHandler to net.connorcpu.plugscript.EventHandler
        at org.jruby.embed.jsr223.JRubyEngine.wrapException(JRubyEngine.java:104) ~[jruby.jar:?]
        at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:121) ~[jruby.jar:?]
        at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:146) ~[jruby.jar:?]
        at net.connorcpu.plugscript.ScriptedPlugin.reloadScript(ScriptedPlugin.java:46) [PlugScript.jar:?]
        at net.connorcpu.plugscript.PlugScript.loadRubyEngines(PlugScript.java:149) [PlugScript.jar:?]
        at net.connorcpu.plugscript.PlugScript.onEnable(PlugScript.java:47) [PlugScript.jar:?]
        at org.bukkit.plugin.java.JavaPlugin.setEnabled(JavaPlugin.java:218) [spigot.jar:git-Spigot-1207]
        at org.bukkit.plugin.java.JavaPluginLoader.enablePlugin(JavaPluginLoader.java:457) [spigot.jar:git-Spigot-1207]
        at org.bukkit.plugin.SimplePluginManager.enablePlugin(SimplePluginManager.java:385) [spigot.jar:git-Spigot-1207]
        at org.bukkit.craftbukkit.v1_7_R1.CraftServer.loadPlugin(CraftServer.java:302) [spigot.jar:git-Spigot-1207]
        at org.bukkit.craftbukkit.v1_7_R1.CraftServer.enablePlugins(CraftServer.java:284) [spigot.jar:git-Spigot-1207]
        at net.minecraft.server.v1_7_R1.MinecraftServer.m(MinecraftServer.java:348) [spigot.jar:git-Spigot-1207]
        at net.minecraft.server.v1_7_R1.MinecraftServer.g(MinecraftServer.java:325) [spigot.jar:git-Spigot-1207]
        at net.minecraft.server.v1_7_R1.MinecraftServer.a(MinecraftServer.java:281) [spigot.jar:git-Spigot-1207]
        at net.minecraft.server.v1_7_R1.DedicatedServer.init(DedicatedServer.java:184) [spigot.jar:git-Spigot-1207]
        at net.minecraft.server.v1_7_R1.MinecraftServer.run(MinecraftServer.java:430) [spigot.jar:git-Spigot-1207]
        at net.minecraft.server.v1_7_R1.ThreadServerApplication.run(SourceFile:617) [spigot.jar:git-Spigot-1207]
Caused by: org.jruby.embed.EvalFailedException: (TypeError) failed to coerce net.connorcpu.plugscript.EventHandler to net.connorcpu.plugscript.EventHandler
        at org.jruby.embed.internal.EmbedEvalUnitImpl.run(EmbedEvalUnitImpl.java:133) ~[jruby.jar:?]
        at org.jruby.embed.jsr223.JRubyEngine.eval(JRubyEngine.java:118) ~[jruby.jar:?]
        ... 15 more
Caused by: org.jruby.exceptions.RaiseException: (TypeError) failed to coerce net.connorcpu.plugscript.EventHandler to net.connorcpu.plugscript.EventHandler
        at RUBY.registerEvent(<script>:44) ~[?:?]
        at RUBY.(root)(<script>:1) ~[?:?]
        ... 1 more

Thank you for any help on this, I've been stumped on this for a while.

Was it helpful?

Solution

It turns out, this was an issue relating to classloaders. The same class was being used from two unique classloaders in each place of the code. The solution was to initialize the JRuby scripting engine with the same classloader as the code creating the scripting environment.

engine = new ScriptingContainer(LocalContextScope.SINGLETHREAD, LocalVariableBehavior.PERSISTENT);
engine.setCompileMode(RubyInstanceConfig.CompileMode.JIT);
engine.setCompatVersion(rubyCompat());
engine.setClassLoader(PlugScript.class.getClassLoader());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top