必须通过使用bundle显式导入Spring OSGI服务引用接口?

时间:2012-01-24 21:14:19

标签: java spring osgi spring-dm bnd

我熟悉Spring OSGI和Blueprint,但遇到了“类路径”困难(就像许多新手一样)。

我有两个OSGI包 - 一个定义各种bean(使用Blueprint,而不是它应该重要)并将它们作为服务导出;和另一个引用服务bean的bundle(使用Spring OSGI)并将它们插入到一些Apache Camel路由中。

服务提供者包的蓝图看起来像这样:

<service id="camelTsvDataFormat" 
    interface="org.apache.camel.spi.DataFormat"> 
    <bean class="org.apache.camel.component.flatpack.FlatpackDataFormat"/> 
</service> 

service-consumer bundle的Spring上下文如下所示:

<osgi:reference id="tsvDataFormat" 
    interface="org.apache.camel.spi.DataFormat" /> 

<camel:camelContext> 
    <route> 
        <from uri="vm:in"> 
        <setBody> 
            <constant>SELECT * FROM myTable</constant> 
        </setBody> 
        <to uri="jdbc:myDataSource" /> 
        <marshal ref="tsvDataFormat" /> 
        <to uri="file:/path/to/my/files/?fileName=out.tsv" /> 
    </route> 
</camel:camelContext> 

...但是在部署时,Spring“无法找到类[org.apache.camel.spi.DataFormat]”。我可以将接口添加到我的Bnd指令的Import-Package部分,但是必须在不同的位置手动列出两次类似乎是多余的。

另一种选择是在我自己的项目中扩展接口,以便Bnd自动接收它,但这几乎同样麻烦。

我想我希望Spring能够通过接口名称查找服务,而无需实际解析接口类。这个天真吗?或者有没有办法让Bnd自动导入我的appContext服务引用中的接口?如果Bnd可以做到这一点(例如使用插件),是否有一种标准方法可以将Bnd插件与Maven的Apache Felix捆绑插件一起使用?

2 个答案:

答案 0 :(得分:3)

正如Holly建议的那样,bnd通常会从包中调用它的任何字节码中找到这个包。如果它们位于正确的位置,它还应该反省Spring-DM XML文件。但是我不知道它是否以相同的方式支持Blueprint XML文件,因为它们不在同一个bundle位置。因此,可能需要升级您的bnd版本或使用支持Blueprint的插件。

然而,我怀疑这一切。如果没有对接口的字节码引用,那么您似乎甚至没有使用服务引用?在这种情况下,为什么不删除它呢?

答案 1 :(得分:1)

正如@Neil Bartlett所说,Bnd应该在捆绑包中的标准位置(META-INF/springOSGI-INF/blueprint)内省Spring和Blueprint文件。我在POM中手动覆盖了META-INF/spring/*.xmlOSGI-INF/blueprint/*.xml这些内容。我认为这很好,因为我的OSGI平台中的Spring和Blueprint扩展程序接受了标题并引导了相应的容器。然而,Bnd似乎期望没有globs的更简单的标题(参见SpringXMLType.java)。我并不是故意指责,因为它是一个了不起的工具,但是这个让我措手不及。

无论如何,由于我的Spring和Blueprint标记已经在标准位置,我只是从我的POM中删除了冗余的Bnd指令,所有Spring-DM服务引用接口都被自动拾取并Import-Package进入我的包裹:

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.3.6</version>
    <extensions>true</extensions>
    <configuration>
        <instructions>
            <Bundle-Version>${project.version}.${buildNumber}</Bundle-Version>
            <Bundle-Activator>com.example.BundleActivator</Bundle-Activator>
            <!-- 
                <Spring-Context>META-INF/spring/*.xml</Spring-Context> 
                <Bundle-Blueprint>OSGI-INF/blueprint*.xml</Bundle-Blueprint> 
            -->
        </instructions>
    </configuration>
</plugin>