Maven PaxExam OSGI容器和ServiceLookupException

Maven PaxExam OSGI容器和ServiceLookupException,maven,junit,osgi,pax-exam,Maven,Junit,Osgi,Pax Exam,我构建了一个非常简单的包,它没有依赖项,也不导入任何包。它唯一的内容是一个计算器服务接口和相应的实现类,其中只包含一个简单的add(inta,intb)方法 我为这个包创建了两个PaxExam测试容器,一个使用Karaf容器,另一个使用OSGI容器。Karaf容器测试可以正常工作,但OSGI测试容器不能 澄清一下。。。如果我将CalculatorService注入到OSGI测试容器中,并在JUnit测试用例中直接实例化CalculatorServiceImpl类,那么它就可以正常工作。因此,OS

我构建了一个非常简单的包,它没有依赖项,也不导入任何包。它唯一的内容是一个计算器服务接口和相应的实现类,其中只包含一个简单的add(inta,intb)方法

我为这个包创建了两个PaxExam测试容器,一个使用Karaf容器,另一个使用OSGI容器。Karaf容器测试可以正常工作,但OSGI测试容器不能

澄清一下。。。如果我将CalculatorService注入到OSGI测试容器中,并在JUnit测试用例中直接实例化CalculatorServiceImpl类,那么它就可以正常工作。因此,OSGI测试容器可以看到我的简单包中的类

一些问题:

  • 我的pom.xml文件中是否缺少一些东西来实现这一点
  • 我是否应该向OsgiTestClient.config()方法添加更多捆绑包
  • 关于什么是保持非常简单的例子的其他想法

下面是我尝试将CalculatorService注入PaxExam OSGI测试容器时得到的堆栈跟踪

org.ops4j.pax.swissbox.tracker.ServiceLookupException: gave up waiting for service info.xyz.common.Calculator
    at org.ops4j.pax.swissbox.tracker.ServiceLookup.getService(ServiceLookup.java:199)
    at org.ops4j.pax.swissbox.tracker.ServiceLookup.getService(ServiceLookup.java:136)
    at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectField(ServiceInjector.java:89)
    at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectDeclaredFields(ServiceInjector.java:69)
    at org.ops4j.pax.exam.inject.internal.ServiceInjector.injectFields(ServiceInjector.java:61)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.createTest(ContainerTestRunner.java:61)
    at org.junit.runners.BlockJUnit4ClassRunner$1.runReflectiveCall(BlockJUnit4ClassRunner.java:266)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:263)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:68)
    at org.ops4j.pax.exam.invoker.junit.internal.ContainerTestRunner.runChild(ContainerTestRunner.java:37)
    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 org.ops4j.pax.exam.nat.internal.NativeTestContainer.call(NativeTestContainer.java:112)
    at org.ops4j.pax.exam.spi.reactors.AllConfinedStagedReactor.invoke(AllConfinedStagedReactor.java:84)
    at org.ops4j.pax.exam.junit.impl.ProbeRunner$2.evaluate(ProbeRunner.java:267)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    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.ops4j.pax.exam.junit.impl.ProbeRunner.run(ProbeRunner.java:98)
    at org.ops4j.pax.exam.junit.PaxExam.run(PaxExam.java:93)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
包含计算器服务的简单捆绑包的pom.xml如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.xyz</groupId>
    <artifactId>xyz-businessLogic</artifactId>
    <version>0.0.1</version>
    <packaging>bundle</packaging>

    <dependencies>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
            </plugin>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
                        <Bundle-Version>${project.version}</Bundle-Version>
                        <Import-Package>
                        </Import-Package>
                        <Export-Package>
                            info.xyz.common,
                            info.xyz.common.impl
                        </Export-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>info.xyz</groupId>
    <artifactId>xyz-test-osgi</artifactId>
    <version>0.0.1</version>

    <parent>
        <groupId>info.xyz</groupId>
        <artifactId>xyz</artifactId>
        <version>0.0.1</version>
        <relativePath>../xyz</relativePath>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-container-native</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-junit4</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-link-mvn</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.url</groupId>
            <artifactId>pax-url-aether</artifactId>
            <version>${pax.url.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.ops4j.pax.exam</groupId>
            <artifactId>pax-exam-inject</artifactId>
            <version>${pax.exam.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.felix</groupId>
            <artifactId>org.apache.felix.framework</artifactId>
            <version>5.4.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>${ch.qos.logback.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>${ch.qos.logback.version}</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>${javax.inject.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>

        <!-- Testing target -->
        <dependency>
            <groupId>info.xyz</groupId>
            <artifactId>xyz-businessLogic</artifactId>
            <version>0.0.1</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Needed if you use versionAsInProject() -->
            <plugin>
                <groupId>org.apache.servicemix.tooling</groupId>
                <artifactId>depends-maven-plugin</artifactId>
                <version>1.3.1</version>
                <executions>
                    <execution>
                        <id>generate-depends-file</id>
                        <goals>
                            <goal>generate-depends-file</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>
package info.xyz.test.osgi;

import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import info.xyz.common.Calculator;

import javax.inject.Inject;

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

@RunWith(PaxExam.class)
@ExamReactorStrategy(PerMethod.class)
public class OsgiTestClient
{
    @Inject
    protected Calculator _calculator;

    @ProbeBuilder
    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe)
    {
        System.out.println("TestProbeBuilder gets called");
        probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*");
        probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.common");
        probe.setHeader(Constants.IMPORT_PACKAGE, "info.xyz.common.impl");
        return probe;
    }

    @Configuration
    public Option[] config()
    {
        return new Option[] {
                junitBundles(),
                mavenBundle().groupId("info.xyz").artifactId("xyz-businessLogic").versionAsInProject(),
        };
    }

    @Test
    public void testAdd()
    {
        info.xyz.common.impl.CalculatorImpl calculator = new info.xyz.common.impl.CalculatorImpl();
        int result = calculator.add(1, 2);
        System.out.println("--- testing: ");
    }
}
最后一条注释,如果我注释掉注入CalculatorService的代码,代码运行良好(因为我正在手动实例化CalculatorImpl类)。因此,我的测试容器对计算器接口和实现具有编译时和运行时可见性。但这项服务的注入不起作用


最后提醒一下,当我构建PaxExam-Karaf测试容器时,计算器服务的注入是成功的,测试用例运行良好。错误出现在运行本文中描述的PaxExam OSGI容器时。

是的,那么默认情况下,blueprint堆栈/库没有安装在本机容器中(但它们在Karaf中)

您需要将此DEP添加到您的测试pom中:

    <dependency>
        <groupId>org.apache.aries</groupId>
        <artifactId>org.apache.aries.util</artifactId>
        <version>1.1.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.proxy</groupId>
        <artifactId>org.apache.aries.proxy.api</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.proxy</groupId>
        <artifactId>org.apache.aries.proxy.impl</artifactId>
        <version>1.0.4</version>
    </dependency>


    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.api</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.core</artifactId>
        <version>1.4.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.core.compatibility</artifactId>
        <version>1.0.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.cm</artifactId>
        <version>1.0.5</version>
    </dependency>

这应该是个好办法

您能否提供有关如何在计算器示例中注册/发布服务的更多信息?我的意思是,您是使用声明性服务还是Blueprint,还是使用OSGi方法(ServiceTracker、registerServices…)呢。。。我已将blueprint.xml添加到原始帖子中。这很有效。。。谢谢你的时间,非常感谢。
    <dependency>
        <groupId>org.apache.aries</groupId>
        <artifactId>org.apache.aries.util</artifactId>
        <version>1.1.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.proxy</groupId>
        <artifactId>org.apache.aries.proxy.api</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.proxy</groupId>
        <artifactId>org.apache.aries.proxy.impl</artifactId>
        <version>1.0.4</version>
    </dependency>


    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.api</artifactId>
        <version>1.0.1</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.core</artifactId>
        <version>1.4.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.core.compatibility</artifactId>
        <version>1.0.0</version>
    </dependency>

    <dependency>
        <groupId>org.apache.aries.blueprint</groupId>
        <artifactId>org.apache.aries.blueprint.cm</artifactId>
        <version>1.0.5</version>
    </dependency>
mavenBundle().groupId("org.apache.aries").artifactId("org.apache.aries.util").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.api").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.proxy").artifactId("org.apache.aries.proxy.impl").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.api").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.cm").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core").versionAsInProject(),
                    mavenBundle().groupId("org.apache.aries.blueprint").artifactId("org.apache.aries.blueprint.core.compatibility").versionAsInProject().noStart(),