Проблема Felix OSGI встраиваемых приложений

Я использовал Felix в качестве встроенного приложения, как описано в разделе Как запустить и использовать Apache Felix из кода?, Я хочу динамически загружать jar-файлы из моего хост-приложения через OSGi и вызывать методы классов реализации.

Итак, у меня есть следующие три проекта Maven

1) Maven проект, который имеет интерфейс. И пакет этого интерфейса экспортируется. ---> ProjA.

2) Проект реализации -> ProjB, другой проект maven, который импортирует ProjA как зависимость maven и реализует интерфейс с конкретным классом. Также в этом проекте я делаю импорт-пакет OSGi для пакета интерфейса ProjA. Также здесь я регистрирую свою реализацию на OSGI через активатор.

3) Затем ProjC, который является размещенным приложением. То, что я делаю, есть,

    HostActivator activator = new HostActivator();
    List<Object> list = new LinkedList<Object>();
    list.add(activator);
    map.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list);
    Felix f = new Felix(map);
    f.start();

    Bundle a = f.getBundleContext().installBundle("file:C:/ProjA.jar"); 
    Bundle b = f.getBundleContext().installBundle("file:C:/ProjB.jar"); ); // dirty path ;)
    b.start();

    ServiceReference sr = activator.getContext().getAllServiceReferences(MyInterface.class.getName(), "(" + "osgi-device-name" + "=*)")[0];
    MyInterface dictionary =  (MyInterface) activator.getContext().getService(sr);
    dictionary.doAction();

Все отлично работает, пока не брошен. Там я вижу следующую ошибку,

Exception in thread "main" java.lang.ClassCastException: projB.MyImplementation cannot be cast to projA.MyInterface
    at MyHostApplication.MyMainClass.main(MyMainClass.java:70)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

Может ли кто-нибудь помочь мне в этом, для меня это похоже на ошибку на Феликсе.

2 ответа

Решение

ProjA находится в classpath вашего основного проекта (который открывает встроенный контейнер OSGi), и он также устанавливается во встроенный контейнер OSGi в виде пакета. Когда ProjB разрешен, он подключается к комплекту ProjA, поэтому он реализует интерфейс, исходящий от установленного комплекта ProjA.

Когда вы пытаетесь привести объект результата, вы пытаетесь привести к интерфейсу, который находится в пути к классам основного проекта. Это другой интерфейс, который реализует пакет ProjB, поскольку он реализует интерфейс из пакета projA.

Вы не должны устанавливать ProjA как пакет в контейнер OSGi. Вы должны быть уверены, что пакет ProjB может решить. Для этого вы должны добавить projA как системный пакет во встроенный контейнер OSGi.

Другой способ решить эту проблему - использовать тег экспорта в maven maven-bundle-plugin или в файле манифеста.

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
                <instructions>
                    <Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
                    <Export-Package>come.example.myInterface</Export-Package>
                    <Bundle-Activator>come.example.Activator</Bundle-Activator>
                </instructions>
            </configuration>
        </plugin>
    </plugins>
</build>

и не забыл

map.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "come.example.myInterface; version=0.0.1");
Другие вопросы по тегам