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: &quot;Glyphicons Halflings&quot;; 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: &quot;Glyphicons Halflings&quot;; 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:&quot;JetBrains Mono&quot;,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:&quot;JetBrains Mono&quot;,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:&quot;JetBrains Mono&quot;,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:&quot;JetBrains Mono&quot;,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:&quot;JetBrains Mono&quot;,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--