Build Your Own Tooling
Sometimes you might want to utilise (J)Ruby-based tools with your own plugins, but you do not want to directory expose everything that might be available in other plugins in this suite. You can use the core functionality that exists within the resolver plugin to build your own tooling.
A task to prepare GEMs
The easiest way to implement your own GEM resolver is to extend AbstractGemPrepareTask.
@CompileStatic
class MyPrepareTask extends AbstractGemPrepareTask {
@Inject
MyPrepareTask(WorkerExecutor we) {
super(we)
}
}
You also need to apply the resolver plugin and then instantiate your task within your plugin.
String name = 'myGems' (1)
project.pluginManager.apply(JRubyResolverPlugin)
project.extensions.getByType(GemConfigurations).register(name, MyPrepareTask)
| 1 | Set a name for the configuration that will hold the GEMs (and associated JARs). |
Resolving the JRuby JAR
It is necessary to set a provider for the jruby-complete JAR which will needed to run the preparation task.
The easiest is to use an existing instance of JRubyExtension or to attach such an extension to your task.
The following example shows you how to create such an extension, which does not link to any globl extension.
class MyPrepareTask extends AbstractGemPrepareTask {
@Inject
MyPrepareTask(WorkerExecutor we) {
super(we)
this.jruby = extensions.create(JRubyExtension.NAME, JRubyExtension, this, 'jrubyx') (1)
setJrubyJarsProvider(project.provider { -> (2)
jruby.jrubyConfiguration.files (3)
})
}
private final JRubyExtension jruby
}
| 1 | Create an extension that attaches to the current task and pass the owner task (this) to bind the two together.
Also, give the associated configuration a special name.
(This example uses jrubyx).
This is recommended so that it does not clash with any other condigurations that were created by JRubyExtension instances from other plugins. |
| 2 | Set up a provider to resolve the JAR location when needed.
This provider is only called by AbstractJRubyPrepare when executing the task actions. |
| 3 | GemUtils.findJRubyJar is a utility that resolves the location. |
A task to execute multiple scripts
Starting up JRuby can be expensive.
If you have a case where you need to execute multiple scripts using the same classpath and GEM environment you can do so by creating a task that extends AbstractMultiScriptJRubyExecTask.
You can then use the addScriptWithArgs and addSystemScriptWithArgs methods to add scripts to be executed.
Lower-level access to running multiple scripts
If AbstractMultiScriptJRubyExecTask does not quite meet your needs you can get access to the worker runner itself.
You need to instantiate an instance of MultiScriptWorkerInitiator.
This is either done via project.objects.newInstance(MultiScriptWorkerInitiator) or if you need even finer control over where the worker comes from use the constructor that takes an instance of a WorkerExecutor and a ConfigurationSafeOperations.
After configuring the instance of MultiScriptWorkerInitiator, you can run execution via various runOnWorker methods.
You need to load the exatc script command-lines as part of configuration.
If you need to run any system scripts or scripts installed from GEMs, you need to pass -S as the first parameter of the command-line list.
In addition, you need to still have some implementation of AbstractGemPrepareTask to create the appropriate GEM layout.
The current implementation is not optimal.
It creates an instance of org.jruby.Main per script line.
This could lead to both performance and out-of-memory issues.
THe workaround at present is to set the forkEvery parameter.
If anyone has the time to write a better JRuby implementation, please feel free to submit a PR.
|