Как выполнить скрипты Groovy в изолированном загрузчике классов?

Я пытаюсь запустить скрипты groovy в изолированном загрузчике классов, чтобы они не выполнялись в контексте зависимостей вызывающего класса.

    Path log4j = Paths.get("..../lib/log4j-1.2.17.jar");
    Path groovy = Paths.get("..../lib/groovy-all-2.1.3.jar");
    RootLoader rootLoader = new RootLoader(new URL[] { log4j.toUri().toURL(), groovy.toUri().toURL() }, null);
    GroovyScriptEngine engine = new GroovyScriptEngine(".../src/main/resources", rootLoader);
    engine.run("Standalone.groovy", "");
Standalone.groovy:
import org.apache.log4j.BasicConfigurator
import org.apache.log4j.Logger

Logger logger = Logger.getLogger(getClass())
BasicConfigurator.configure()
logger.info("hello world")
pom.xmlвыдержка:
    <dependency>
        <groupId>org.codehaus.groovy</groupId>
        <artifactId>groovy-all</artifactId>
        <version>2.1.3</version>
    </dependency>

Любое изменение в вышеупомянутом, которое я пробовал, всегда приводит к

Exception in thread "main" groovy.lang.GroovyRuntimeException: Failed to create Script instance for class: class Standalone. Reason: java.lang.ClassCastException: Standalone cannot be cast to groovy.lang.GroovyObject
    at org.codehaus.groovy.runtime.InvokerHelper.createScript(InvokerHelper.java:443)
    at groovy.util.GroovyScriptEngine.createScript(GroovyScriptEngine.java:564)
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:551)
    at groovy.util.GroovyScriptEngine.run(GroovyScriptEngine.java:537)

Я отследил это до groovy.util.GroovyScriptEngine#loadScriptByName где скрипт разбирается в Class<T>где T - имя самого скрипта.

Моя теория заключается в том, что это вызвано двоичной несовместимостью между Groovy Runtime, выполняемой в вызывающем классе, и Groovy Runtime, выполняемой в автономном загрузчике классов, из-за того, что Groovy создает синтетические классы из сценариев посредством отражения.

Любые идеи о том, как это может быть достигнуто?

1 ответ

Решение

Попытаться создать GroovyScriptEngine не напрямую, а через rootLoader.loadClass() и позвонить engine.run через отражение.

Другие вопросы по тегам