Контейнер PaxExam OSGI и исключение ServiceLookupException

Я создал очень простой пакет, который не имеет зависимостей и не импортирует пакеты. Его единственное содержимое - это интерфейс CalculatorService и соответствующий класс реализации, содержащий простой метод add (int a, int b).

Я создал два тестовых контейнера PaxExam для этого пакета, один из которых использует контейнер Karaf, а другой - контейнер OSGI. Контейнерные тесты Karaf работают нормально, но тестовый контейнер OSGI - нет.

Чтобы немного прояснить ... если я удалю внедрение CalculatorService в тестовый контейнер OSGI и напрямую создаю экземпляр класса CalculatorServiceImpl в моем тестовом примере JUnit, он будет работать нормально. Итак, класс из моего простого пакета виден в тестовом контейнере 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>

Ясно, что у моего простого пакета нет никаких зависимостей, и пакеты, содержащие файлы Calculator и 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 Test имеет следующий вид:

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, описанного в этом посте.


person Randy Leonard    schedule 14.12.2015    source источник
comment
Не могли бы вы предоставить дополнительную информацию о том, как вы регистрируете / публикуете услуги в своем образце Калькулятора? Я имею в виду, используете ли вы декларативные службы или Blueprint или делаете это с помощью методов OSGi (ServiceTracker, registerServices ...)   -  person Jorge Martinez    schedule 15.12.2015
comment
Хороший момент ... Я добавил blueprint.xml в исходный пост.   -  person Randy Leonard    schedule 15.12.2015


Ответы (1)


Да, тогда стек / библиотеки чертежей не устанавливаются по умолчанию в собственном контейнере (но они находятся в Карафе).

Вам нужно добавить эту deps в свой тестовый 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(),

Это должно помочь!

person Jorge Martinez    schedule 15.12.2015
comment
Это сработало ... спасибо за ваше время, очень признателен. - person Randy Leonard; 15.12.2015