Проблема 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");