2015-12-14 28 views
2

我已經構建了一個非常簡單的包,它具有零依賴性並且不導入任何包。它唯一的內容是一個CalculatorService接口和相應的實現類,它只包含一個簡單的add(int a,int b)方法。PaxExam OSGI容器和ServiceLookupException

我爲這個包創建了兩個PaxExam測試容器,一個使用Karaf容器,另一個使用OSGI容器。卡拉夫容器測試工作正常,但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> 

有零隻依賴於我的簡單捆綁,幷包包含計算器和CalculatorImpl很明顯文件被導出。以下是用於定義這些服務的blueprint.xml文件。

<?xml version="1.0" encoding="UTF-8"?> 
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jpa="http://aries.apache.org/xmlns/jpa/v1.0.0" xmlns:tx="http://aries.apache.org/xmlns/transactions/v1.0.0" 

    xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0 
      http://www.w3.org/2001/XMLSchema-instance http://www.w3.org/2001/XMLSchema-instance 
      http://aries.apache.org/xmlns/jpa/v1.0.0 http://aries.apache.org/xmlns/jpa/v1.0.0 
      http://aries.apache.org/xmlns/transactions/v1.0.0 http://aries.apache.org/xmlns/transactions/v1.0.0"> 

    <bean id="calculatorService" class="info.xyz.common.impl.CalculatorImpl" /> 
    <service ref="calculatorService" interface="info.xyz.common.Calculator" /> 
</blueprint> 

接下來,pom.xml中爲我PaxExam OSGI容器如下:

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

最後,OSGI測試類給出如下:

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測試容器時,Calculator服務的注入成功並且測試用例運行良好。運行本文描述的PaxExam OSGI容器時出錯。

+0

您能否提供更多關於如何在Calculator示例中註冊/發佈服務的信息?我的意思是你使用聲明式服務或藍圖,或者你是用OSGi方法(ServiceTracker,registerServices ...)來做它 –

+0

好點...我已將blueprint.xml添加到原始帖子中。 –

回答

2

是的,那麼藍圖棧/庫默認情況下並不安裝在本地容器中(但它們在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> 

,並添加以下捆綁配置在您的測試:

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(), 

這應該使的伎倆!

+0

這工作......謝謝你的時間,非常感謝。 –