Re: using @GrabConfig(systemClassLoader=true) in a ScriptEngine
Per Nyfelt <[email protected]> Fri, 11 Jul 2025 20:54:11 +0200
| Newsgroups | gmane.comp.lang.groovy.user |
|---|---|
| Organization | Alipsa HB |
| Message-ID | <[email protected]> |
This is a multi-part message in MIME format.
--------------ESMNgCE06hHTDhet0hGBrVA0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 8bit
Thank you for the suggestions! I tried setting the system classloader with
-Djava.system.class.loader=org.codehaus.groovy.tools.RootLoader
and also tried
-Djava.system.class.loader=groovy.lang.GroovyClassloader
That indeed fixes the issue with "no suitable classloader available for
Grab" but unfortunately neither of them fixes the problem.
The issue is now that ant (called via AntBuilder) is unable to find the
h2 jdbc driver. It looks like RootLoader is a child first classloader so
it "should" have worked but I guess that ant's own classloader is not
playing well that setup.
The code is here in case anyone want to try it out:
https://github.com/perNyfelt/groovy-issues/tree/main/antbuilder
The error i am getting is as follows:
[0.003s][warning][cds] Archived non-system classes are disabled because
the java.system.class.loader property is specified (value =
"org.codehaus.groovy.tools.RootLoader"). To use archived non-system
classes, this property must not be set
Exception in thread "main" : Class Not Found: JDBC driver org.h2.Driver
could not be loaded
at
org.apache.tools.ant.taskdefs.JDBCTask.getDriver(JDBCTask.java:434)
at
org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:365)
at
org.apache.tools.ant.taskdefs.SQLExec.getConnection(SQLExec.java:953)
at org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:649)
at
org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:299)
at
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at
org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:99)
at groovy.ant.AntBuilder.performTask(AntBuilder.java:347)
at groovy.ant.AntBuilder.nodeCompleted(AntBuilder.java:286)
at
groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:161)
at groovy.ant.AntBuilder.doInvokeMethod(AntBuilder.java:219)
at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:75)
at
org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:651)
at
org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:628)
at
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeOnDelegationObjects(ClosureMetaClass.java:392)
at
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:331)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)
at
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)
at sqltask$_run_closure1.doCall(sqltask.groovy:9)
at
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328)
at
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:280)
at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)
at groovy.lang.Closure.call(Closure.java:433)
at groovy.lang.Closure.call(Closure.java:422)
at
org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:368)
at
org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:313)
at org.codehaus.groovy.runtime.dgm$914.doMethodInvoke(Unknown
Source)
at
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)
at sqltask.run(sqltask.groovy:7)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:460)
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:504)
at SqlTask.main(SqlTask.java:10)
I guess my best option is to mimic what the groovy command does exactly
and try to get that to work from java...
regards,
Per
*Jochen Theodorou* - Wednesday, July 9, 2025 5:46:19 PM GMT+2
If you run the program using the groovy command or a shell then there is
a GroovyClassLoader involved can be used instead of the systemloader.
Basically since Java9 Java does not use a url class loader as system
loader anymore. Which means we cannot support systemClassLoader=true in
case there is no rescuing GroovyClassLoader
you could try using -Djava.system.class.loader=... to set a class loader
using the fully qualified name. It should be a URLClassloader or child
of it and I guess the class needs to be on the classpath as well The
alternative is using a small program to load the classpath and start the
program. In Groovy we are using RootLoader for this. Or you use
GroovyStarter bye Jochen
On 7/8/25 12:51, Per Nyfelt wrote:
> Hi,
>
> I am trying to figure out a way to
> use @GrabConfig(systemClassLoader=true) in a ScritpEngine (or
> GroovyShell, does not matter.
>
> The following script works without any problem using the groovy
> command (.e.g `groovy sqltaskExample.groovy`):
>
> @GrabConfig(systemClassLoader=true)
> @Grab('com.h2database:h2:2.3.232')
> import groovy.ant.AntBuilder
>
> println"Groovy ClassLoader: ${this.class.classLoader}" def project =new AntBuilder()
> project.with { sql(
> driver:"org.h2.Driver",
> url:"jdbc:h2:mem:AZ",
> userid:"sa",
> password:"",
> // direct printed output into a text file: output:"query.out",
> print:"yes",// enable printing of result sets showheaders:"false",// suppress column names showtrailers:"false" // suppress "N rows returned" line ){ transaction(""" CREATE TABLE some_table ( id INT, name VARCHAR(200) ); """)
> transaction(""" INSERT INTO some_table (id, name) VALUES (1, 'hello'); """)
> transaction(""" SELECT name FROM some_table WHERE id = 1; """)
> } // now the file query.out contains exactly "hello" loadfile(property:"row1col1",srcFile:"query.out")
> echo(message:'row1col1 = ${row1col1}')
> delete(file:"query.out")
> }
>
> Calling that from java however does not work:, e.g.
> public class ShellWithGrabSupport {
> public static void main(String[] args)throws Exception {
> GroovyScriptEngine gse =new GroovyScriptEngine(".");
> gse.run("sqltaskExample.groovy",new Binding());
> }
> }
> Results in "No Suitable classloader found for Grab"
> I have tried stuff like this:
> System.setProperty("groovy.grape.enable","true");
> System.setProperty("groovy.grape.report.downloads","true");
> GroovyClassLoader gcl =new GroovyClassLoader(ClassLoader.getSystemClassLoader());
>
> CompilerConfiguration config =new CompilerConfiguration();
> config.setRecompileGroovySource(true);
>
> GroovyShell shell =new GroovyShell(gcl, config);
> Script s = shell.parse(new File("sqltaskExample.groovy"));
> s.run();
>
> and
> System.setProperty("groovy.grape.report.downloads","true");
> System.setProperty("groovy.grape.enable","true");
> // Ensure system classloader is used Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
>
> // This mimics what the `groovy` CLI does GroovyMain.main(new String[]{"sqltaskExample.groovy"});
>
> All with the same result.
>
> I use the following to bootstrap java:
> gl="$GROOVY_HOME/lib" v="4.0.27" cp="$gl/groovy-$v.jar:$gl/groovy-ant-$v.jar:$gl/groovy-ant-$v.jar:$gl/ant-1.10.15.jar:\ $gl/ant-launcher-1.10.15.jar:$gl/ivy-2.5.3.jar" java -cp"$cp" ShellWithGrabSupport.java
>
> So since ant is loaded by the system classloader, I must
> use @GrabConfig(systemClassLoader=true) in the groovy script for the
> jdbc driver, otherwise the sql ant task will not be able to find it.
>
> This minimum, reproducible example is here:
> https://github.com/perNyfelt/groovy-issues/tree/main/grabconfig
>
> The details of the error are as follows:
> Exception in thread "main"
> org.codehaus.groovy.control.MultipleCompilationErrorsException:
> startup failed:
> General error during conversion: No suitable ClassLoader found for grab
>
> java.lang.RuntimeException: No suitable ClassLoader found for grab
> at groovy.grape.GrapeIvy.chooseClassLoader(GrapeIvy.groovy:179)
> at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:273)
> at groovy.grape.Grape$1.run(Grape.java:172)
> at groovy.grape.Grape$1.run(Grape.java:158)
> at
> java.base/java.security.AccessController.doPrivileged(AccessController.java:319)
> at groovy.grape.Grape.grab(Grape.java:158)
> at
> groovy.grape.GrabAnnotationTransformation.visit(GrabAnnotationTransformation.java:380)
> at
> org.codehaus.groovy.transform.ASTTransformationVisitor.lambda$addPhaseOperationsForGlobalTransforms$5(ASTTransformationVisitor.java:374)
> at
> org.codehaus.groovy.control.CompilationUnit$ISourceUnitOperation.doPhaseOperation(CompilationUnit.java:906)
> at
> org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:701)
> at
> org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:675)
> at
> groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:365)
> at
> groovy.lang.GroovyClassLoader.lambda$parseClass$2(GroovyClassLoader.java:314)
> at
> org.codehaus.groovy.runtime.memoize.StampedCommonCache.compute(StampedCommonCache.java:163)
> at
> org.codehaus.groovy.runtime.memoize.StampedCommonCache.getAndPut(StampedCommonCache.java:154)
> at
> groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:314)
> at
> groovy.util.GroovyScriptEngine$ScriptClassLoader.doParseClass(GroovyScriptEngine.java:231)
> at
> groovy.util.GroovyScriptEngine$ScriptClassLoader.parseClass(GroovyScriptEngine.java:218)
> at
> groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:298)
> at
> groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:263)
> at
> groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:534)
> at
> groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:584)
> at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:571)
> at ShellWithGrabSupport.main(ShellWithGrabSupport.java:7)
> at
> ...
> Does anyone know a way?
>
>
>
--------------ESMNgCE06hHTDhet0hGBrVA0
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: 8bit
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p>Thank you for the suggestions! I tried setting the system
classloader with</p>
<pre
style="font-family:'JetBrains Mono',monospace;font-size:10.5pt;">-Djava.system.class.loader=org.codehaus.groovy.tools.RootLoader
and also tried
</pre>
<div style="background-color:#1e1f22;color:#bcbec4">
<pre
style="font-family:'JetBrains Mono',monospace;font-size:10.5pt;">-Djava.system.class.loader=groovy.lang.GroovyClassloader
</pre>
</div>
<p></p>
<p>That indeed fixes the issue with "no suitable classloader
available for Grab" but unfortunately neither of them fixes the
problem.</p>
<p>The issue is now that ant (called via AntBuilder) is unable to
find the h2 jdbc driver. It looks like RootLoader is a child first
classloader so it "should" have worked but I guess that ant's own
classloader is not playing well that setup.</p>
<p>The code is here in case anyone want to try it out:
<a class="moz-txt-link-freetext" href="https://github.com/perNyfelt/groovy-issues/tree/main/antbuilder">https://github.com/perNyfelt/groovy-issues/tree/main/antbuilder</a><br>
</p>
<p>The error i am getting is as follows:</p>
<p>[0.003s][warning][cds] Archived non-system classes are disabled
because the java.system.class.loader property is specified (value
= "org.codehaus.groovy.tools.RootLoader"). To use archived
non-system classes, this property must not be set<br>
Exception in thread "main" : Class Not Found: JDBC driver
org.h2.Driver could not be loaded<br>
at
org.apache.tools.ant.taskdefs.JDBCTask.getDriver(JDBCTask.java:434)<br>
at
org.apache.tools.ant.taskdefs.JDBCTask.getConnection(JDBCTask.java:365)<br>
at
org.apache.tools.ant.taskdefs.SQLExec.getConnection(SQLExec.java:953)<br>
at
org.apache.tools.ant.taskdefs.SQLExec.execute(SQLExec.java:649)<br>
at
org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:299)<br>
at
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)<br>
at
java.base/java.lang.reflect.Method.invoke(Method.java:580)<br>
at
org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:99)<br>
at groovy.ant.AntBuilder.performTask(AntBuilder.java:347)<br>
at
groovy.ant.AntBuilder.nodeCompleted(AntBuilder.java:286)<br>
at
groovy.util.BuilderSupport.doInvokeMethod(BuilderSupport.java:161)<br>
at
groovy.ant.AntBuilder.doInvokeMethod(AntBuilder.java:219)<br>
at
groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:75)<br>
at
org.codehaus.groovy.runtime.InvokerHelper.invokePogoMethod(InvokerHelper.java:651)<br>
at
org.codehaus.groovy.runtime.InvokerHelper.invokeMethod(InvokerHelper.java:628)<br>
at
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeOnDelegationObjects(ClosureMetaClass.java:392)<br>
at
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:331)<br>
at
groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)<br>
at
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)<br>
at sqltask$_run_closure1.doCall(sqltask.groovy:9)<br>
at
java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)<br>
at
java.base/java.lang.reflect.Method.invoke(Method.java:580)<br>
at
org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:343)<br>
at
groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:328)<br>
at
org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:280)<br>
at
groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1007)<br>
at groovy.lang.Closure.call(Closure.java:433)<br>
at groovy.lang.Closure.call(Closure.java:422)<br>
at
org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:368)<br>
at
org.codehaus.groovy.runtime.DefaultGroovyMethods.with(DefaultGroovyMethods.java:313)<br>
at
org.codehaus.groovy.runtime.dgm$914.doMethodInvoke(Unknown Source)<br>
at
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(IndyInterface.java:321)<br>
at sqltask.run(sqltask.groovy:7)<br>
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:460)<br>
at groovy.lang.GroovyShell.evaluate(GroovyShell.java:504)<br>
at SqlTask.main(SqlTask.java:10)<br>
<br>
</p>
<p>I guess my best option is to mimic what the groovy command does
exactly and try to get that to work from java...</p>
<p>regards,</p>
<p>Per<br>
</p>
<div class="chatty_author"
style="box-sizing: border-box; line-height: 36px; font-family: sans-serif; float: left; width: 1383px; color: rgb(255, 255, 255); margin-bottom: -16px; font-size: 12.5px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(51, 122, 183); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><div
class="chatty_author_name"
style="box-sizing: border-box; padding-left: 50px;"><b
style="box-sizing: border-box; font-weight: bold;">Jochen Theodorou</b> - Wednesday, July 9, 2025 5:46:19 PM GMT+2</div></div>
<pre class="chatty_body"
style="box-sizing: border-box; overflow: visible; font-family: Hack; font-size: 1.25rem; display: inline-block; padding: 5px 40px 5px 5px; margin: 10px 10px 25px 20px; line-height: 1.42857; word-break: keep-all; overflow-wrap: normal; color: rgb(34, 34, 51); background: rgb(255, 255, 255); border: none; border-radius: 6px; min-width: 300px; position: relative; white-space: pre-wrap; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><div
class="email_quote_parent" style="box-sizing: border-box;"><button
title="Toggle quote"
style="box-sizing: border-box; color: inherit; font: inherit; margin: 0px; overflow: visible; text-transform: none; appearance: button; cursor: pointer;"><span
class="glyphicon glyphicon-comment"
style="box-sizing: border-box; position: relative; top: 1px; display: inline-block; font-family: "Glyphicons Halflings"; font-style: normal; font-weight: normal; line-height: 1; -webkit-font-smoothing: antialiased;"></span></button>
</div>If you run the program using the groovy command or a shell then there is
a GroovyClassLoader involved can be used instead of the systemloader.
Basically since Java9 Java does not use a url class loader as system
loader anymore. Which means we cannot support systemClassLoader=true in
case there is no rescuing GroovyClassLoader
<div class="email_quote_parent" style="box-sizing: border-box;"><button
title="Toggle quote"
style="box-sizing: border-box; color: inherit; font: inherit; margin: 0px; overflow: visible; text-transform: none; appearance: button; cursor: pointer;"><span
class="glyphicon glyphicon-comment"
style="box-sizing: border-box; position: relative; top: 1px; display: inline-block; font-family: "Glyphicons Halflings"; font-style: normal; font-weight: normal; line-height: 1; -webkit-font-smoothing: antialiased;"></span></button>
</div><span style="box-sizing: border-box;">you could try using -Djava.system.class.loader=... to set a class loader
using the fully qualified name. It should be a URLClassloader or child
of it and I guess the class needs to be on the classpath as well
The alternative is using a small program to load the classpath and start
the program. In Groovy we are using RootLoader for this. Or you use
GroovyStarter
bye Jochen</span></pre>
<p></p>
<p><br>
</p>
<div class="moz-cite-prefix">On 7/8/25 12:51, Per Nyfelt wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CAOAt0KSf2Vs8E4amQUapwhBnCMtfuqZoY5An1WtJxutFFZWwOw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr">Hi,
<div><br>
</div>
<div>I am trying to figure out a way to
use @GrabConfig(systemClassLoader=true) in a ScritpEngine (or
GroovyShell, does not matter.</div>
<div><br>
</div>
<div>The following script works without any problem using the
groovy command (.e.g `groovy sqltaskExample.groovy`):<br>
<br>
<div
style="background-color:rgb(30,31,34);color:rgb(188,190,196)">
<pre
style="font-family:"JetBrains Mono",monospace"><span
style="color:rgb(179,174,96)">@GrabConfig</span>(systemClassLoader=<span
style="color:rgb(207,142,109)">true</span>)
<span style="color:rgb(179,174,96)">@Grab</span>(<span
style="color:rgb(106,171,115)">'com.h2database:h2:2.3.232'</span>)
<span style="color:rgb(207,142,109)">import </span>groovy.ant.AntBuilder
println <span style="color:rgb(106,171,115)">"Groovy ClassLoader: </span>$<span
style="font-weight:bold">{</span><span
style="color:rgb(207,142,109)">this</span>.<span
style="color:rgb(199,125,187)">class</span>.<span
style="color:rgb(199,125,187)">classLoader</span><span
style="font-weight:bold">}</span><span
style="color:rgb(106,171,115)">"
</span><span style="color:rgb(207,142,109)">def </span>project = <span
style="color:rgb(207,142,109)">new </span>AntBuilder()
project.<span style="color:rgb(117,122,133)">with </span><span
style="font-weight:bold">{
</span><span style="font-weight:bold"> </span><span
style="color:rgb(117,122,133)">sql</span>(
<span style="color:rgb(106,171,115)">driver</span>: <span
style="color:rgb(106,171,115)">"org.h2.Driver"</span>,
<span style="color:rgb(106,171,115)">url</span>: <span
style="color:rgb(106,171,115)">"jdbc:h2:mem:AZ"</span>,
<span style="color:rgb(106,171,115)">userid</span>: <span
style="color:rgb(106,171,115)">"sa"</span>,
<span style="color:rgb(106,171,115)">password</span>: <span
style="color:rgb(106,171,115)">""</span>,
<span style="color:rgb(122,126,133)">// direct printed output into a text file:
</span><span style="color:rgb(122,126,133)"> </span><span
style="color:rgb(106,171,115)">output</span>: <span
style="color:rgb(106,171,115)">"query.out"</span>,
<span style="color:rgb(106,171,115)">print</span>: <span
style="color:rgb(106,171,115)">"yes"</span>, <span
style="color:rgb(122,126,133)">// enable printing of result sets
</span><span style="color:rgb(122,126,133)"> </span><span
style="color:rgb(106,171,115)">showheaders</span>:<span
style="color:rgb(106,171,115)">"false"</span>, <span
style="color:rgb(122,126,133)">// suppress column names
</span><span style="color:rgb(122,126,133)"> </span><span
style="color:rgb(106,171,115)">showtrailers</span>:<span
style="color:rgb(106,171,115)">"false" </span><span
style="color:rgb(122,126,133)">// suppress "N rows returned" line
</span><span style="color:rgb(122,126,133)"> </span>) <span
style="font-weight:bold">{
</span><span style="font-weight:bold"> </span><span
style="color:rgb(117,122,133)">transaction</span>(<span
style="color:rgb(106,171,115)">"""
</span><span style="color:rgb(106,171,115)"> CREATE TABLE some_table (
</span><span style="color:rgb(106,171,115)"> id INT,
</span><span style="color:rgb(106,171,115)"> name VARCHAR(200)
</span><span style="color:rgb(106,171,115)"> );
</span><span style="color:rgb(106,171,115)"> """</span>)
<span style="color:rgb(117,122,133)">transaction</span>(<span
style="color:rgb(106,171,115)">"""
</span><span style="color:rgb(106,171,115)"> INSERT INTO some_table (id, name)
</span><span style="color:rgb(106,171,115)"> VALUES (1, 'hello');
</span><span style="color:rgb(106,171,115)"> """</span>)
<span style="color:rgb(117,122,133)">transaction</span>(<span
style="color:rgb(106,171,115)">"""
</span><span style="color:rgb(106,171,115)"> SELECT name
</span><span style="color:rgb(106,171,115)"> FROM some_table
</span><span style="color:rgb(106,171,115)"> WHERE id = 1;
</span><span style="color:rgb(106,171,115)"> """</span>)
<span style="font-weight:bold">}
</span><span style="font-weight:bold"> </span><span
style="color:rgb(122,126,133)">// now the file query.out contains exactly "hello"
</span><span style="color:rgb(122,126,133)"> </span><span
style="color:rgb(117,122,133)">loadfile</span>(<span
style="color:rgb(106,171,115)">property</span>: <span
style="color:rgb(106,171,115)">"row1col1"</span>, <span
style="color:rgb(106,171,115)">srcFile</span>: <span
style="color:rgb(106,171,115)">"query.out"</span>)
<span style="color:rgb(117,122,133)">echo</span>(<span
style="color:rgb(106,171,115)">message</span>: <span
style="color:rgb(106,171,115)">'row1col1 = ${row1col1}'</span>)
<span style="color:rgb(117,122,133)">delete</span>(<span
style="color:rgb(106,171,115)">file</span>: <span
style="color:rgb(106,171,115)">"query.out"</span>)
<span style="font-weight:bold">}</span></pre>
</div>
</div>
<div><br>
</div>
<div>Calling that from java however does not work:, e.g.<br>
<div
style="background-color:rgb(30,31,34);color:rgb(188,190,196)">
<pre
style="font-family:"JetBrains Mono",monospace"><span
style="color:rgb(207,142,109)">public class </span>ShellWithGrabSupport {
<span style="color:rgb(207,142,109)">public static void </span><span
style="color:rgb(86,168,245)">main</span>(String[] args) <span
style="color:rgb(207,142,109)">throws </span>Exception {
GroovyScriptEngine gse = <span style="color:rgb(207,142,109)">new </span>GroovyScriptEngine(<span
style="color:rgb(106,171,115)">"."</span>);
gse.run(<span style="color:rgb(106,171,115)">"sqltaskExample.groovy"</span>, <span
style="color:rgb(207,142,109)">new </span>Binding());
}
}</pre>
</div>
Results in "No Suitable classloader found for Grab"</div>
<div>I have tried stuff like this:<br>
<div
style="background-color:rgb(30,31,34);color:rgb(188,190,196)">
<pre
style="font-family:"JetBrains Mono",monospace">System.<span
style="font-style:italic">setProperty</span>(<span
style="color:rgb(106,171,115)">"groovy.grape.enable"</span>, <span
style="color:rgb(106,171,115)">"true"</span>);
System.<span style="font-style:italic">setProperty</span>(<span
style="color:rgb(106,171,115)">"groovy.grape.report.downloads"</span>, <span
style="color:rgb(106,171,115)">"true"</span>);
GroovyClassLoader gcl = <span style="color:rgb(207,142,109)">new </span>GroovyClassLoader(ClassLoader.<span
style="font-style:italic">getSystemClassLoader</span>());
CompilerConfiguration config = <span style="color:rgb(207,142,109)">new </span>CompilerConfiguration();
config.setRecompileGroovySource(<span style="color:rgb(207,142,109)">true</span>);
GroovyShell shell = <span style="color:rgb(207,142,109)">new </span>GroovyShell(gcl, config);
Script s = shell.parse(<span style="color:rgb(207,142,109)">new </span>File(<span
style="color:rgb(106,171,115)">"sqltaskExample.groovy"</span>));
s.run();</pre>
</div>
</div>
<div><br>
</div>
<div>and</div>
<div>
<div
style="background-color:rgb(30,31,34);color:rgb(188,190,196)">
<pre
style="font-family:"JetBrains Mono",monospace">System.<span
style="font-style:italic">setProperty</span>(<span
style="color:rgb(106,171,115)">"groovy.grape.report.downloads"</span>, <span
style="color:rgb(106,171,115)">"true"</span>);
System.<span style="font-style:italic">setProperty</span>(<span
style="color:rgb(106,171,115)">"groovy.grape.enable"</span>, <span
style="color:rgb(106,171,115)">"true"</span>);
<span style="color:rgb(122,126,133)">// Ensure system classloader is used
</span>Thread.<span style="font-style:italic">currentThread</span>().setContextClassLoader(ClassLoader.<span
style="font-style:italic">getSystemClassLoader</span>());
<span style="color:rgb(122,126,133)">// This mimics what the `groovy` CLI does
</span>GroovyMain.<span style="font-style:italic">main</span>(<span
style="color:rgb(207,142,109)">new </span>String[]{<span
style="color:rgb(106,171,115)">"sqltaskExample.groovy"</span>});</pre>
</div>
</div>
<div><br>
</div>
<div>All with the same result. </div>
<br class="gmail-Apple-interchange-newline">
I use the following to bootstrap java:
<div>
<div
style="background-color:rgb(30,31,34);color:rgb(188,190,196)">
<pre
style="font-family:"JetBrains Mono",monospace">gl=<span
style="color:rgb(106,171,115)">"</span>$GROOVY_HOME<span
style="color:rgb(106,171,115)">/lib"
</span>v=<span style="color:rgb(106,171,115)">"4.0.27"
</span>cp=<span style="color:rgb(106,171,115)">"</span>$gl<span
style="color:rgb(106,171,115)">/groovy-</span>$v<span
style="color:rgb(106,171,115)">.jar:</span>$gl<span
style="color:rgb(106,171,115)">/groovy-ant-</span>$v<span
style="color:rgb(106,171,115)">.jar:</span>$gl<span
style="color:rgb(106,171,115)">/groovy-ant-</span>$v<span
style="color:rgb(106,171,115)">.jar:</span>$gl<span
style="color:rgb(106,171,115)">/ant-1.10.15.jar:\
</span>$gl<span style="color:rgb(106,171,115)">/ant-launcher-1.10.15.jar:</span>$gl<span
style="color:rgb(106,171,115)">/ivy-2.5.3.jar"
</span><span style="color:rgb(197,118,51)">java </span>-cp <span
style="color:rgb(106,171,115)">"</span>$cp<span
style="color:rgb(106,171,115)">" </span>ShellWithGrabSupport.java</pre>
</div>
</div>
<div><br>
</div>
<div>So since ant is loaded by the system classloader, I must
use @GrabConfig(systemClassLoader=true) in the groovy script
for the jdbc driver, otherwise the sql ant task will not be
able to find it.</div>
<div><br>
</div>
<div>This minimum, reproducible example is here: <a
href="https://github.com/perNyfelt/groovy-issues/tree/main/grabconfig"
moz-do-not-send="true" class="moz-txt-link-freetext">https://github.com/perNyfelt/groovy-issues/tree/main/grabconfig</a></div>
<div><br>
</div>
<div>The details of the error are as follows:<br>
Exception in thread "main"
org.codehaus.groovy.control.MultipleCompilationErrorsException:
startup failed:<br>
General error during conversion: No suitable ClassLoader found
for grab<br>
<br>
java.lang.RuntimeException: No suitable ClassLoader found for
grab<br>
at
groovy.grape.GrapeIvy.chooseClassLoader(GrapeIvy.groovy:179)<br>
at groovy.grape.GrapeIvy.grab(GrapeIvy.groovy:273)<br>
at groovy.grape.Grape$1.run(Grape.java:172)<br>
at groovy.grape.Grape$1.run(Grape.java:158)<br>
at
java.base/java.security.AccessController.doPrivileged(AccessController.java:319)<br>
at groovy.grape.Grape.grab(Grape.java:158)<br>
at
groovy.grape.GrabAnnotationTransformation.visit(GrabAnnotationTransformation.java:380)<br>
at
org.codehaus.groovy.transform.ASTTransformationVisitor.lambda$addPhaseOperationsForGlobalTransforms$5(ASTTransformationVisitor.java:374)<br>
at
org.codehaus.groovy.control.CompilationUnit$ISourceUnitOperation.doPhaseOperation(CompilationUnit.java:906)<br>
at
org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:701)<br>
at
org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:675)<br>
at
groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:365)<br>
at
groovy.lang.GroovyClassLoader.lambda$parseClass$2(GroovyClassLoader.java:314)<br>
at
org.codehaus.groovy.runtime.memoize.StampedCommonCache.compute(StampedCommonCache.java:163)<br>
at
org.codehaus.groovy.runtime.memoize.StampedCommonCache.getAndPut(StampedCommonCache.java:154)<br>
at
groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:314)<br>
at
groovy.util.GroovyScriptEngine$ScriptClassLoader.doParseClass(GroovyScriptEngine.java:231)<br>
at
groovy.util.GroovyScriptEngine$ScriptClassLoader.parseClass(GroovyScriptEngine.java:218)<br>
at
groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:298)<br>
at
groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:263)<br>
at
groovy.util.GroovyScriptEngine.loadScriptByName(GroovyScriptEngine.java:534)<br>
at
groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:584)<br>
at
groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:571)<br>
at
ShellWithGrabSupport.main(ShellWithGrabSupport.java:7)<br>
at </div>
<div>...</div>
<div>Does anyone know a way?<br>
<br>
<br>
</div>
<div><br>
</div>
</div>
</blockquote>
</body>
</html>
--------------ESMNgCE06hHTDhet0hGBrVA0--