2012-06-28 2 views
0

Я довольно новичок с OSGi и борюсь с включением в комплект моего пакета Maven.ClassCastException с использованием пакетов OSGi в проекте Maven

Я создал набор API и комплект реализации, используя плагин mave-bundle-plugin. В моем основном проекте (проект Maven) я попытался получить сервис внедренного пакета из ServiceTracker с помощью Felix Framework. Когда я, наконец, попытаюсь передать полученную услугу в правильный тип, я получаю исключение ClassCastException. Проект

API Maven:

public interface ParserTestService { 
    String validForStage(); 
} 

API POM:

проект
<artifactId>ParserTest</artifactId> 
<version>0.0.2-SNAPSHOT</version> 
<packaging>bundle</packaging> 

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.apache.felix</groupId> 
      <artifactId>maven-bundle-plugin</artifactId> 
      <extensions>true</extensions> 
      <configuration> 
       <instructions> 
        <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName> 
        <Bundle-Vendor>Apache-Felix</Bundle-Vendor> 
        <Bundle-Version>0.0.1</Bundle-Version> 
        <Export-Service>de.ParserTestService</Export-Service>  
       </instructions> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 

<dependencies> 
    <dependency> 
     <groupId>org.apache.felix</groupId> 
     <artifactId>org.apache.felix.framework</artifactId> 
     <version>2.0.4</version> 
    </dependency> 
</dependencies> 

Impl Maven:

public class ParserImplService implements ParserTestService { 
    public String validForStage() { 
     return "S"; 
    } 
} 

Impl POM:

<artifactId>ParserTestVersion1</artifactId> 
<version>0.0.2-SNAPSHOT</version> 
<packaging>bundle</packaging> 

<build> 
    <plugins> 
     <plugin> 
      <groupId>org.apache.felix</groupId> 
      <artifactId>maven-bundle-plugin</artifactId> 
      <extensions>true</extensions> 
      <configuration> 
       <instructions> 
        <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName> 
        <Bundle-Vendor>Apache-Felix</Bundle-Vendor> 
        <Bundle-Version>0.0.1</Bundle-Version> 
        <Bundle-Activator>de.Activator</Bundle-Activator> 
        <Export-Package>de</Export-Package> 
        <Export-Service>de.ParserImplService</Export-Service> 
        <Import-Package>org.osgi.framework</Import-Package> 
       </instructions> 
      </configuration> 
     </plugin> 
    </plugins> 
</build> 

<dependencies> 
    <dependency> 
     <groupId>org.apache.felix</groupId> 
     <artifactId>org.apache.felix.framework</artifactId> 
     <version>2.0.4</version> 
     <type>bundle</type> 
    </dependency> 
    <dependency> 
     <groupId>de</groupId> 
     <artifactId>ParserTest</artifactId> 
     <version>0.0.2-SNAPSHOT</version> 
     <type>bundle</type> 
    </dependency> 
</dependencies> 

Maven создал два JAR-файлы со следующим манифестом файлами:

Manifest-Version: 1.0 
Bnd-LastModified: 1340890655296 
Build-Jdk: 1.6.0_24 
Built-By: br_s1 
Bundle-ManifestVersion: 2 
Bundle-Name: Parser Test Interface 
Bundle-SymbolicName: de.ParserTest 
Bundle-Vendor: Apache-Felix 
Bundle-Version: 0.0.1 
Created-By: Apache Maven Bundle Plugin 
Export-Package: de;version="0.0.1" 
Export-Service: de.ParserTestService 
Tool: Bnd-1.50.0 

Manifest-Version: 1.0 
Bnd-LastModified: 1340890661890 
Build-Jdk: 1.6.0_24 
Built-By: br_s1 
Bundle-Activator: de.Activator 
Bundle-ManifestVersion: 2 
Bundle-Name: Parser Test 
Bundle-SymbolicName: de.ParserTestVersion1 
Bundle-Vendor: Apache-Felix 
Bundle-Version: 0.0.1 
Created-By: Apache Maven Bundle Plugin 
Export-Package: de;version="0.0.1" 
Export-Service: de.ParserImplService 
Import-Package: org.osgi.framework;version="[1.5,2)" 
Tool: Bnd-1.50.0 

В моем проекте Major Maven, я установка и начал рамки Феликса. В подпапке «bundles» я скопировал jar-файлы, созданные в процессе развертывания Maven выше. В установочном-рутину, я попытался установить эти пакеты и запустить их:

public class HostActivator implements BundleActivator { 
... 
    public BundleContext getContext() 
    { 
     return m_context; 
    } 
... 
} 

public class HostApplication 
{ 
    private HostActivator m_activator = null; 
    private Felix m_felix = null; 
    private ServiceTracker m_tracker = null; 

    public HostApplication() 
    { 
     Map<String, Object> configMap = new HashMap<String, Object>(); 
     configMap.put(Constants.FRAMEWORK_SYSTEMPACKAGES_EXTRA, "de.test; version=1.0.0"); 
     m_activator = new HostActivator(); 
     List<BundleActivator> list = new ArrayList<BundleActivator>(); 
     list.add(m_activator); 
     configMap.put(FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP, list); 

     m_felix = new Felix(configMap); 
     m_felix.start(); 

     m_tracker = new ServiceTracker(m_activator.getContext(), ParserTestService.class.getName(), null); 
     m_tracker.open(); 
    } 

    public void installBundlesFromDir() { 

     File dir = new File("bundles"); 
     for (File f : dir.listFiles()) { 
      try { 
       Bundle b = m_felix.getBundleContext().installBundle("file:"+f.getAbsolutePath()); 
       b.start(); 

       ServiceReference sr = m_felix.getBundleContext().getServiceReference(ParserTestService.class.getName()); 

       ParserTestService service = (ParserTestService) m_felix.getBundleContext().getService(sr); 

      } catch (BundleException e) { 
       System.err.println("could not load bundle "+f.getAbsolutePath()); 
      } 
     }   

    } 
} 

Соответствующий POM:

<artifactId>parserUse</artifactId> 
<version>0.0.1-SNAPSHOT</version> 

<dependencies> 
    <dependency> 
     <groupId>org.apache.felix</groupId> 
     <artifactId>org.apache.felix.framework</artifactId> 
     <version>2.0.4</version> 
    </dependency>    
    <dependency> 
     <groupId>de</groupId> 
     <artifactId>ParserTestVersion1</artifactId> 
     <version>0.0.2-SNAPSHOT</version> 
    </dependency> 
    <dependency> 
     <groupId>de</groupId> 
     <artifactId>ParserTest</artifactId> 
     <version>0.0.2-SNAPSHOT</version> 
    </dependency> 
</dependencies> 

Когда я пытаюсь вызвать установить процедуру, однако, я получаю ClassCastException:

java.lang.ClassCastException: de.ParserImplService cannot be cast to de.ParserTestService 

Я уже проверил загрузчики классов

ParserTestService.class.getClassLoader() 

и

(m_felix.getBundleContext().getService(sr)).getClass().getClassLoader() 

и они отличаются друг от друга.

Я всегда думал, что OSGi позаботится о загрузке класса для меня.

Кто-нибудь знает, что я делаю неправильно? Любая помощь приветствуется!

Спасибо заранее, Себастьян

ответ

1

я, наконец, нашел способ решить эту проблему, но только избегая Феликс и использование Equinox вместо этого.

1.) API экспортирует только пакет <Export-Package>de</Export-Package>

2.) Имплеп не экспортирует ничего. Он определяет только активатор и его импорт

<Bundle-Activator>de.Activator</Bundle-Activator> 
<Import-Package>org.osgi.framework;de</Import-Package> 

3.) Я заменил всю HostApplication с помощью Equinox:

public class HostApplication { 
    private BundleContext bundleContext; 

    public HostApplication(String profileName) { 
     BundleContext bc = null; 
     Properties frameworkProperties = readCustomProfile(profileName); 

     frameworkProperties.put("osgi.clean", "true"); 
     frameworkProperties.put("osgi.console", "true"); 

     Map<String, String> frameworkPropertiesMap = new HashMap<String, String>(); 
     for (Object o : frameworkProperties.keySet()) { 
      frameworkPropertiesMap.put((String) o, 
        (String) frameworkProperties.getProperty((String) o)); 
     } 

     EclipseStarter.setInitialProperties(frameworkPropertiesMap); 
     bc = EclipseStarter.startup(new String[] { "-console", "-dev", "bin" }, null); 
    } 

    public boolean containsIegm(String stage, byte[] msg) { 

     try { 
      ServiceReference serviceReference = bundleContext.getServiceReference(ParserTest.class.getName()); 
      return ((ParserImplService) bundleContext.getService(serviceReference)).containsIegm(msg); 

     } catch (Exception ex) { 
      ex.printStackTrace(); 
     } 

     return false; 
    } 

    public void installBundlesFromDir() { 

     File dir = new File("bundles"); 
     int i = 0; 
     for (File f : dir.listFiles()) { 
      try { 
       Bundle b = bundleContext.installBundle("file:"+ f.getAbsolutePath()); 
       b.start(); 
      } catch (BundleException e) { 
       System.err.println("could not load bundle " + f.getAbsolutePath()); 
      } 
     } 

    } 
} 

я пытался точно так же с Феликсом, используя BundleContext из m_felix (см вопрос) и полностью удалил HostActivator (я знаю, что он не нужен в моем приложении). Однако я не мог заставить его работать.

В любом случае, с Equinox одинаково легко встраивается инфраструктура OSGi в приложениях, отличных от OGSi/non-bundle.

Спасибо всем за помощь! Sebastian

+3

Чтобы уточнить, нет абсолютно никаких оснований для того, чтобы Felix и Equinox отличались здесь. Я подозреваю, что существует более простой способ FAR для достижения того, что вы пытались сделать, если бы вы только отступали от деталей и описывали свои цели в более общих терминах. –

1

Обе связки экспортирующие "де". Это означает, что будет два пространства имен, называемых «de».
Расслоение Bundle-Символический: de.ParserTestVersion1 должны импорт «де» и получить его от другого пучка

+1

Кроме того, при создании «ServiceTracker» используется неверный «BundleContext» ... похоже, что использовался контекст публикации (хотя установка очень сбивает с толку). В результате обычные проверки совместимости искажаются. Кроме того, если внешний пакет имеет видимость классов реализации внутри внутреннего пакета (например, HostActivator), то зачем даже беспокоиться о сервисе? Почему не просто прямое инстанцирование? –

+0

@David: Я обновил экспорт и импорт пакетов и по-прежнему получаю ClassCastException. Я полагаю, это не было причиной моей проблемы. – user1488793

+0

@Neil: Я не совсем понимаю ваш ответ. Поскольку я новичок в OSGi и начинаю думать, что ошибался, возможно, я должен уточнить, что я хочу сделать: Мое приложение-хост должно уметь делать две вещи. 1.) Он должен иметь возможность устанавливать и запускать службы из каталога. 2.) Он должен иметь возможность ссылаться на эти службы. – user1488793