Внедрение контейнера Pax Exam + Karaf Custom Service встречает ClassNotFoundException

Недавно я написал интеграционный тест, работающий в контейнере Karaf, который использует Pax Exam, вот мой код:

package com.mercury.mof.integration.tests;

import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.provision;
import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
import static org.ops4j.pax.tinybundles.core.TinyBundles.bundle;

import java.util.HashSet;
import java.util.Set;

import javax.inject.Inject;

import org.apache.karaf.features.Feature;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.OptionUtils;
import org.ops4j.pax.exam.ProbeBuilder;
import org.ops4j.pax.exam.TestProbeBuilder;
import org.ops4j.pax.exam.junit.PaxExam;
import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
import org.ops4j.pax.exam.spi.reactors.PerMethod;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;

import com.mercury.mof.dataplatform.api.impl.DefaultMofDataPlatformModule;
import com.mercury.mof.foundation.framework.api.modular.IFramework;
import com.mercury.mof.foundation.framework.api.modular.IModule;

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
public class FeaturesTest extends KarafTestSupport {

    @ProbeBuilder
    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
        probe.setHeader(
            Constants.DYNAMICIMPORT_PACKAGE,
                "*,org.apache.felix.service.*;status=provisional");
    return probe;
}


//This is my custom service ,and when running tests Pax Exam always report     ClassNotFoundException. 
    @Inject
    IFramework framework;

@Override
@Configuration
public Option[] config() {
    Option[] option = super.config();

    // KarafFeatureDependencyGenerator generator = new
    // KarafFeatureDependencyGenerator();
    // System.out.println(maven().groupId(
    // "org.apache.karaf.assemblies.features")
    // .artifactId("standard").type("xml")
    // .classifier("features")
    // .versionAsInProject().getURL());
    //
    //
    // try{
    // System.out.println(
    // generator.analysisFeature(System.getenv("m2_repo"), maven().groupId(
    // "org.apache.karaf.assemblies.features")
    // .artifactId("enterprise").type("xml")
    // .classifier("features")
    // .versionAsInProject().getURL()));
    // }catch(Exception e){
    // e.printStackTrace();
    // }

    Option[] combined = OptionUtils
            .combine(
                    option,

                    features(
                            maven().groupId(
                                    "org.apache.karaf.assemblies.features")
                                    .artifactId("standard").type("xml")
                                    .classifier("features")
                                    .versionAsInProject(), "http",
                            "http-whiteboard"),
                    features(
                            maven().groupId(
                                    "org.apache.karaf.assemblies.features")
                                    .artifactId("enterprise").type("xml")
                                    .classifier("features")
                                    .versionAsInProject(), "transaction",
                            "jpa", "jndi"),

                    mavenBundle("org.osgi", "org.osgi.compendium", "4.2.0"),
                    mavenBundle("org.osgi", "org.osgi.core", "4.2.0"),
                    mavenBundle("org.osgi", "org.osgi.enterprise", "4.2.0"),
                    mavenBundle("com.mercury", "mof-foundation-commons",
                            "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-framework-impl", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-cache-api", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof", "mof-data-platform-api",
                            "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-data-platform-impl", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-framework-api", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-security-api", "1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-cache-api,1.0.0.alpha"),
                    mavenBundle("com.mercury.mof",
                            "mof-foundation-rbac-api", "1.0.0.alpha"),

                    provision(bundle()
                            .set("Import-Package",
                                    "org.osgi.service.blueprint;version=\"[1.0.0,2.0.0)\",com.mercury.mof.foundation.framework.api.modular;version=\"[1.0,2)\",com.mercury.mof.dataplatform.api;version=\"[1.0,2)\",com.mercury.mof.foundation.commons.inf.lifecycle;version=\"[1.0,2)\",com.mercury.mof.foundation.framework.api.impl.modular;version=\"[1.0,2)\"")


                            .set("Export-Package",
                                    "com.mercury.mof.dataplatform.api.impl;uses:=\"com.mercury .mof.foundation.framework.api.impl.modular,com.mercury.mof.foundation.c ommons.inf.lifecycle\";version=\"1.0.0.alpha\"")
                            .set("DynamicImport-Package", "*")
                            .set(Constants.BUNDLE_MANIFESTVERSION, "2")
                            .set(Constants.BUNDLE_SYMBOLICNAME,
                                    "com.mercury.mof.mof-data-platform-impl-integration-test")
                            .set(Constants.BUNDLE_VERSION, "1.0.0.alpha")
                            .add(IFramework.class)
                            .add("OSGI-INF/blueprint/blueprint.xml",
                                    getClass()
                                            .getResource(
                                                    "/OSGI-INF/blueprint/blueprint.xml"))

                            .build())

            );

    return combined;
}

@Test
public void testTransactionFeature() throws Exception {
    Assert.assertNotNull(this.featuresService);
    assertFeatureInstalled("http");
    assertFeatureInstalled("jpa");
    assertFeatureInstalled("jndi");
    assertFeatureInstalled("transaction");


    Assert.assertNotNull(this.blueprintContainer);

    Assert.assertNotNull(this.blueprintContainer.getComponentInstance("mofFrameworkServiceImpl"));
    // Assert.assertNotNull(module);

}

protected Set<Feature> getFeatures(String features) throws Exception {
    String[] featureArray = features.split("\\s");
    Set<Feature> featureSet = new HashSet<Feature>();
    for (String s : featureArray) {

        if (s == null || (s = s.trim()).isEmpty()) {
            continue;
        }
        Feature feature = this.featuresService.getFeature(s);
        if (feature == null) {
            throw new IllegalArgumentException("The feature which named:"
                    + s + " can not be found.");
        }
        featureSet.add(feature);
    }
    return featureSet;
}

}

Но я обнаружил, что он не может пройти тест, потому что мой пользовательский класс обслуживания (фреймворк IFramework) не может быть найден тестовым пакетом, и он сообщает:

java.lang.ClassNotFoundException:     com.mercury.mof.foundation.framework.api.modular.IFramework not found by PAXEXAM-PROBE-45604164-c35f-448b-9627-af8adb7e16f7 [110]
    at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1460)
    at org.apache.felix.framework.BundleWiringImpl.access$400(BundleWiringImpl.java:72)
    at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1843)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:356)
    at java.lang.Class.getDeclaredFields0(Native Method)
    at java.lang.Class.privateGetDeclaredFields(Class.java:2317)
    at java.lang.Class.getDeclaredFields(Class.java:1762)
    at org.junit.runners.model.TestClass.<init>(TestClass.java:49)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:75)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:57)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.<init>(ContainerTestRunner.java:53)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunnerBuilder.runnerForClass(ContainerTestRunnerBuilder.java:50)
    at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunnerClassRequest.getRunner(ContainerTestRunnerClassRequest.java:61)
    at org.junit.internal.requests.FilterRequest.getRunner(FilterRequest.java:31)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:138)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.invokeViaJUnit(JUnitProbeInvoker.java:123)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.findAndInvoke(JUnitProbeInvoker.java:96)
    at org.ops4j.pax.exam.invoker.junit.internal.JUnitProbeInvoker.call(JUnitProbeInvoker.java:72)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at org.ops4j.pax.exam.rbc.internal.RemoteBundleContextImpl.remoteCall(RemoteBundleContextImpl.java:80)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:322)
    at sun.rmi.transport.Transport$1.run(Transport.java:177)
    at sun.rmi.transport.Transport$1.run(Transport.java:174)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.rmi.transport.Transport.serviceCall(Transport.java:173)
    at sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:553)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:808)
    at sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:667)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:722)

Я не знаю, в чем проблема. На самом деле я добавляю некоторые стандартные службы osgi в свой базовый тест, и это работает как шарм, почему это приводит к проблемам, когда я использую свой собственный сервис? может ли кто-нибудь дать мне подсказку? Большое спасибо


person user1099102    schedule 30.11.2013    source источник


Ответы (1)


Лучший способ убедиться, что ваш тест может видеть класс IFramework, — убедиться, что пакет, предоставляющий класс, установлен в вашем контейнере. Использование mavenBundle внутри аннотированного метода @Configuration — хороший способ.

На что нужно обратить внимание: i) Пакет, содержащий IFramework, экспортирует класс. ii) Если вы используете координацию maven, убедитесь, что артефакт установлен (см. [1]). iii) Убедитесь, что зависимости пакета, экспортирующего IFramework, удовлетворены.

Итак, комментарии, относящиеся к вашему коду: i) вам не нужно устанавливать ядро ​​osgi, компендиум и предприятие (они предоставляются karaf). ii) Нет необходимости использовать предоставление для добавления классов и ресурсов (я вижу, что классы устанавливаются как пакеты и тестовые ресурсы в любом случае).

[1]: если ваш интеграционный тест является частью того же модуля maven с классами, которые вы используете в тестах, вы должны знать, что тесты запускаются до того, как артефакт будет установлен в вашем репозитории, поэтому использование координат maven может привести к к вопросам. Если это так, рассмотрите возможность разделения тестов или не используйте координаты maven.

person iocanel    schedule 02.12.2013
comment
Привет, iocanel, большое спасибо за повтор. Я протестировал зависимость от maven, войдя в каталог распаковки экзамена pax, удалив все пакеты, связанные с pax, и запустив karaf в командной строке, и я уверен, что зависимость верна, потому что другой пакет будет использовать класс IFramework и вызывать службы, и служба запускается как обычно. Итак, я предполагаю, что последней причиной, которую вы укажете, будет кандидат, но я действительно не знаю, есть ли способ исправить начальный порядок моего тестового пакета. - person user1099102; 02.12.2013
comment
И у меня есть еще одна проблема: тестирование экзамена pax всегда будет пытаться загрузить пакеты функций из сети, когда я запускаю тест, если есть способ остановить это и заставить его найти рекомендуемые пакеты, используя мой локальный репозиторий maven? Так благодарен. - person user1099102; 02.12.2013