2012-06-28 65 views
0

我与OSGi的相当一个新手,并与包括捆绑到我的Maven项目struggeling。ClassCastException异常使用OSGi包Maven项目

我使用MAVE束-插件创建的API包和一个实现捆绑。在我的主要项目(一个Maven项目)中,我尝试使用Felix框架从ServiceTracker获得已实现捆绑包的服务。当我最终尝试将获得的服务转换为正确的类型时,我收到一个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 

在我的专业Maven项目,我安装并启动了菲利克斯框架。在子文件夹“bundles”中,我复制了上面Maven部署过程创建的jar文件。在安装例程,我试图安装这些包,并开始他们:

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

得到它,我终于找到了一种方法来解决这个问题,但只能通过避免菲利克斯和使用春分代替。

1。)API仅导出包<Export-Package>de</Export-Package>

2.)Impl不导出。它只定义了活化剂和其进口

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

3)我换成使用春分整个HostApplication:

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()); 
      } 
     } 

    } 
} 

我想正好与Felix一样使用m_felix的BundleContext的(见问题)并完全删除HostActivator(我知道在我的应用程序中没有必要)。但是,我无法使它工作。

无论如何,使用Equinox,在非OGSi /非捆绑应用程序中嵌入OSGi框架同样很容易。

感谢大家的帮助! Sebastian

+3

澄清,Felix和Equinox绝对没有什么不同。我怀疑,如果你只是退一步细说并用更一般的术语来描述你的目标,那么有一种FAR更简单的方式来实现你想要做的事情。 –

1

这两个捆绑正在出口“德”。这意味着将会有两个名为“de”的名称空间。
束束 - SymbolicName:de.ParserTestVersion1应该进口“德”,并从其他捆

+1

另外,'ServiceTracker'的创建使用错误的'BundleContext' ...它看起来像使用了发布包的上下文(虽然安装非常令人困惑)。结果,正常的兼容性检查被破坏。另外,如果外部bundle具有内部bundle中实现类的可见性(例如HostActivator),那么为什么即使打扰一个服务?为什么不直接实例化? –

+0

@David:我更新了bundle的导入和导入,仍然得到ClassCastException。我想这不是我的问题的原因。 – user1488793

+0

@尼尔:我不完全明白你的答案。由于我是OSGi的新手,并开始认为我走错了路,也许我应该澄清我想做的事情:我的主机应用程序应该能够做两件事。 1.)它应该能够从一个目录安装和启动服务2)它应该能够调用这些服务。 – user1488793