3

Recently I wrote a integration test running in Karaf container which using Pax Exam,here is my code:

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;
}

}

But I found that it can not passed the test because my custom service class (IFramework framework) can not be found by the testing bundle and it report:

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)

I dont know where the problem is, Actually I inject some standard osgi services into my base test, and it works like a charm, why it leads to trouble when I using my own service? can anybody give me some hint? So many thanks

Johan
  • 74,508
  • 24
  • 191
  • 319

1 Answers1

1

The best way to make sure that your test can see the IFramework class, is to make sure that the bundle that provides the class is installed in your container. Using mavenBundle inside the @Configuration annotated method is a good way to go.

Things you need to be pay attention to: i) The bundle that contains IFramework exports the class. ii) If you are using maven coordination ensure that the artefact is installed (see [1]). iii) Ensure that the dependencies of the bundle exporting IFramework are satisfied.

So comments related to your code: i) you don't need to install osgi core, compendium & enterprise (they are provided by karaf). ii) There is no need to use the provision thing to add classes and resources (I see the classes being installed as bundles & test resources are going to be available anyway).

[1]: if your integration test is part of the same maven module with the classes you are using in the tests, you need to be aware that the tests are run before the artefact is installed in your repository, so using maven coords can lead to issues. If this is the case, consider splitting your tests, or don't use maven coords.

iocanel
  • 570
  • 2
  • 2
  • Hi, iocanel, thanks very much for your replay. I have tested the maven dependency by get into the pax exam unpack directory and delete all pax related bundles and run karaf in command line, and I'm sure the dependency is correct, because another bundle will using the IFramework class and invoking services, and the service is started as normal. So, I guess that the last reason you give will be the candicate, but I really dont know if there is any way to correct the starting order of my testing bundle. – user1099102 Dec 02 '13 at 11:43
  • 1
    And I have another trouble: the pax exam testing will always try to downloading bundles in features from net when I running test, if there's anyway to stop this and make it find featured bundles using my local maven repository? So thankful. – user1099102 Dec 02 '13 at 11:49