Тесты OSGi больше не работают после обновления Groovy 2.5 до Groovy 3.0

У меня есть тест pax-exam, который выглядит так:

@RunWith(PaxExam.class)
public class XmlPathOSGiITest {

    @Configuration
    public static Option[] configure() {
        return new Option[]
                {
                        /* System Properties */
                        systemProperty(EXAM_FAIL_ON_UNRESOLVED_KEY).value("true"),
                        systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),

                        /* Hamcrest & JUnit bundles */
                        restAssuredJunitBundles(),

                        /* Transitive dependencies needed in the Pax Exam container.
                        Some of these need to be wrapped because they are not available as OSGi bundles */
                        mavenBundle().groupId("org.apache.aries.spifly").artifactId("org.apache.aries.spifly.dynamic.bundle").version("1.2.1"),
                        mavenBundle().groupId("org.hamcrest").artifactId("hamcrest").versionAsInProject(),
                        mavenBundle().groupId("org.apache.commons").artifactId("commons-lang3").versionAsInProject(),
                        mavenBundle().groupId("org.codehaus.groovy").artifactId("groovy-json").versionAsInProject().noStart(),
                        mavenBundle().groupId("org.codehaus.groovy").artifactId("groovy-xml").versionAsInProject().noStart(),
                        mavenBundle().groupId("org.codehaus.groovy").artifactId("groovy").versionAsInProject(),

                        wrappedBundle(mavenBundle().groupId("org.ccil.cowan.tagsoup").artifactId("tagsoup").versionAsInProject()),
                        wrappedBundle(mavenBundle("jakarta.xml.bind", "jakarta.xml.bind-api").versionAsInProject()),
                        wrappedBundle(mavenBundle("javax.activation", "activation").version("1.1.1")),
                        wrappedBundle(mavenBundle("org.apache.httpcomponents", "httpclient").versionAsInProject()),
                        wrappedBundle(mavenBundle("org.apache.httpcomponents", "httpmime").versionAsInProject()),
                        wrappedBundle(mavenBundle("org.apache.httpcomponents", "httpcore").versionAsInProject()),

                        /* Rest Assured dependencies needed in the Pax Exam container to be able to execute the tests below */
                        mavenBundle("io.rest-assured", "json-path").versionAsInProject(),
                        mavenBundle("io.rest-assured", "xml-path").versionAsInProject(),
                        mavenBundle("io.rest-assured", "rest-assured").versionAsInProject(),
                        mavenBundle("io.rest-assured", "rest-assured-common").versionAsInProject()
                };
    }

    @Test
    public void getUUIDParsesAStringResultToUUID() {
        final String UUID_XML = "<some>\n" +
                "  <thing id=\"1\">db24eeeb-7fe5-41d3-8f06-986b793ecc91</thing>\n" +
                "  <thing id=\"2\">d69ded28-d75c-460f-9cbe-1412c60ed4cc</thing>\n" +
                "</some>";

        final UUID uuid = from(UUID_XML).getUUID("some.thing[0]");

        assertThat(uuid, Matchers.equalTo(UUID.fromString("db24eeeb-7fe5-41d3-8f06-986b793ecc91")));
    }
}

Раньше это нормально работало с Groovy 2.5, но после обновления до Groovy 3.0 я получаю следующую ошибку:

java.lang.ClassNotFoundException: org.codehaus.groovy.runtime.ScriptBytecodeAdapter not found by groovy-xml [20]

    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1597)
    at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1982)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at org.apache.felix.framework.BundleWiringImpl.getClassByDelegation(BundleWiringImpl.java:1375)
    at org.apache.felix.framework.BundleWiringImpl.searchImports(BundleWiringImpl.java:1618)
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1548)
    at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1982)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at io.restassured.internal.common.assertion.AssertParameter.notNull(AssertParameter.groovy:25)
    at io.restassured.path.xml.XmlPath.get(XmlPath.java:316)
    at io.restassured.path.xml.XmlPath.getUUID(XmlPath.java:584)
    at io.restassured.test.osgi.XmlPathOSGiITest.getUUIDParsesAStringResultToUUID(XmlPathOSGiITest.java:84)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runLeafWithRetry(ContainerTestRunner.java:97)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChildWithRetry(ContainerTestRunner.java:84)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:75)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:43)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.invokeViaJUnit(JUnitProbeInvoker.java:124)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.findAndInvoke(JUnitProbeInvoker.java:97)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.call(JUnitProbeInvoker.java:73)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:566)
    at org.ops4j.pax.swissbox.framework.RemoteFrameworkImpl.invokeMethodOnService(RemoteFrameworkImpl.java:435)
    at org.ops4j.pax.swissbox.framework.RemoteFrameworkImpl.invokeMethodOnService(RemoteFrameworkImpl.java:408)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:566)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:359)
    at sun.rmi.transport.Transport$1.run(Transport.java:200)
    at sun.rmi.transport.Transport$1.run(Transport.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:196)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:562)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:796)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:677)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:676)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at java.lang.Thread.run(Thread.java:834)

Я проверил mvn dependency:tree, чтобы убедиться, что в пути к классам нет остатков Groovy 2.5.x.

Что могло быть причиной этого и как это исправить? Обратите внимание, что вы можете найти проект на github здесь.


person Johan    schedule 14.02.2020    source источник
comment
Из трассировки стека на данный момент это выглядит так: io.restassured.internal.common.assertion.AssertParameter.notNull (AssertParameter.groovy: 25) Класс ScriptBytecodeAdapter будет загружен, но у него нет такого вызова. Это внутренняя ошибка groovy?   -  person Christian Schneider    schedule 14.02.2020
comment
ScriptBytecodeAdapter - это один из внутренних классов среды выполнения Groovy, используемый в качестве интерфейса между средой выполнения Groovy и сгенерированным байт-кодом. Таким образом выполняются все стандартные непрямые вызовы методов. Отличный артефакт содержит этот класс. Что касается того, почему он не загружается, я не могу сказать. Возможно, подготовьте минимальный проект и спросите его в списке пользователей Apache Groovy.   -  person blackdrag    schedule 14.02.2020
comment
Это полная трассировка стека? Иногда класс не может быть загружен, потому что он использует зависимость, отсутствующую во время выполнения.   -  person GianMaria Romanato    schedule 14.02.2020
comment
Да, это полная трассировка стека.   -  person Johan    schedule 14.02.2020
comment
ClassNotFoundException в OSGi может быть из-за неправильных метаданных (класс находится в пути к классам, но конкретный пакет не может найти его из-за изоляции модуля). Думаю, я воспроизвел очень похожую проблему в простом проекте (без ожидания, без теста PaxExam, с использованием Bndtools): github.com/jmini/bnd-experiments/tree/master/groovy-v3-xml-test Тот же тест с Groovy 2.5.9 подходит : github.com/jmini/bnd-experiments/tree / master / groovy-v2-xml-test   -  person Jmini    schedule 16.02.2020
comment
Я открыл issues.apache.org/jira/browse/GROOVY-9402   -  person Jmini    schedule 16.02.2020
comment
@Johan, есть ли у вас способ протестировать с 3.0.2-SNAPSHOT, чтобы убедиться, что исправление GROOVY-9402 работает на вас?   -  person Jmini    schedule 20.02.2020
comment
@Jmini Я пробовал это с 3.0.2-SNAPSHOT сейчас, и он работает !! Большое спасибо!   -  person Johan    schedule 21.02.2020


Ответы (2)


Обсуждение здесь подняло проблему GROOVY-9402, которая исправлена ​​в версии 3.0.2 Groovy. .

Резюме:

Метаданные OSGi не соответствуют Groovy 3.0.0 и 3.0.1.

На ранней стадии разработки Groovy 3.0 команда хотела избавиться от разделенных пакетов между различными модулями (модульная система JPMS) и соответствующим образом обновила метаданные OSGi.

Позже они решили добавить несколько устаревших классов в расположение старого пакета, чтобы указать, что классы были перемещены (это означает, что Groovy 3.0 имеет проблемы с разделением пакетов, а поддержка JPMS будет добавлена ​​с 4.0). Во время этой операции метаданные OSGi не были исправлены. Это решено с помощью Groovy 3.0.2

person Jmini    schedule 24.02.2020

Я думаю, это может быть вызвано отличной загрузкой внутреннего класса. Скорее всего, Groovy использует загрузчик классов пользовательского пакета для загрузки своего собственного класса ScriptBytecodeAdapter. Для этого он должен использовать собственный загрузчик классов. Кстати. Самый простой способ получить такие загрузчики классов - получить загрузчик классов известного класса.

В OSGi загрузчик класса всегда является загрузчиком класса пакета, в котором находится класс.

person Christian Schneider    schedule 16.02.2020
comment
В моем примере github.com/jmini/bnd-experiments / tree / master / groovy-v3-xml-test класс ScriptBytecodeAdapter не задействован: NoClassDefFoundError: groovy/xml/XmlParser. Может ли это быть из-за неработающих метаданных? Я открыл эту проблему для изучения: issues.apache.org/jira/browse/GROOVY- 9402 - person Jmini; 16.02.2020
comment
Я думаю, вы имеете в виду, что groovy должен экспортировать дополнительный пакет. Думаю, здесь дело обстоит не так. Это помогло бы только в том случае, если бы пользовательский пакет действительно ссылался на пакет. Если класс, который не найден, является внутренним, то обычно используется неправильный загрузчик классов. Тем не менее есть смысл сообщить об ошибке. - person Christian Schneider; 16.02.2020