I’m working on some code for my book and I’m trying out Swinger, which is a Cucumber library for Swing. I wanted to integrate it into my build (which is Gradle), but was running into issues. The problem is that I was pulling JRuby-Embed from the central Maven repo, which meant that I could only use the JRuby classes by way of Gradle’s fancy classloader stunts. The issue is that JRuby does some of its own classloader stunts, so there were classloader issues. The issue resulted in error messages that looked like this:
Caused by: org.jruby.exceptions.RaiseException: library `enumerator' could not be loaded: java.lang.ClassNotFoundException: org.jruby.libraries.EnumeratorLibrary at (unknown).new(:1) at (unknown).(unknown)(:1)
After tracking through the JRuby source code, I found that RubyInstanceConfig was grabbing the thread context classloader instead of the classloader used to load itself. I don’t know what that classloader was set to, but resetting it solved the issue.
Here’s the resulting Gradle script, which at least runs the gem installs and a Cucumber run:
import org.jruby.Main as JRuby buildscript { repositories { mavenCentral() } dependencies { classpath "org.jruby.embed:jruby-embed:0.1.2" } } task checkGradle << { println "OK" } task gems << { def gemsDir = "./build/gems" if(!new File(gemsDir).exists()) { runJRuby("gem install -i $gemsDir --no-rdoc --no-ri cucumber") } } task runTest(dependsOn:gems) << { def cukeHome = new File('./build/gems/gems').listFiles().find { it.name.startsWith('cucumber-') } runJRuby("$cukeHome/bin/cucumber src/test/features") } def runJRuby(cmdArg) { Thread.currentThread().setContextClassLoader(JRuby.class.classLoader) println "Running JRuby: $cmdArg" JRuby.main("-S $cmdArg".split()) }
Related posts: