2014-05-19 82 views
16

更新2:因为我的博客是有点死的联系得到了降低,所以你可以在这里查看的文章:管理OSGi的依赖地狱

https://www.dropbox.com/s/xvobgzqnl43kcda/Managing_OSGi_Transitive_Dependencies__Part_1____CitizenRandom.pdf?dl=0

https://www.dropbox.com/s/0bdooux4yhrf8lf/Managing%20OSGi%20Transitive%20Dependencies%20%28...pdf?dl=0

https://www.dropbox.com/s/km3mxqah6oy23iq/Why%20using%20Require-Bundle%20is%20a%20bad%20pract...pdf?dl=0

https://www.dropbox.com/s/mtenchtjopcrmr8/How%20many%20ways%20can%20we%20import%20bundles%20in%20OSGi_%20_%20CitizenRandom.pdf?dl=0

https://www.dropbox.com/s/sldxynx3fl8vn61/Managing%20OSGi%20Transitive%20Dependencies%20%282...pdf?dl=0

我有一个Maven项目,用我的pom.xml配置以下列方式非常有名的菲利克斯的Maven插件捆绑:

<packaging>bundle</packaging> 

(...) 

<plugin> 
      <groupId>org.apache.felix</groupId> 
      <artifactId>maven-bundle-plugin</artifactId> 
      <extensions>true</extensions> 
      <configuration> 
       <instructions> 
        <Bundle-SymbolicName>${project.artifactId};singleton:=true</Bundle-SymbolicName> 
        <Bundle-Version>${project.version}</Bundle-Version> 
        <Export-Package>jlifx.*</Export-Package> 
        <!-- <Embed-Dependency>*</Embed-Dependency> --> 
       </instructions> 
      </configuration> 
     </plugin> 

然后,我有一些一阶/包括水平依赖于我的POM以及:

<dependencies> 
    <dependency> 
     <groupId>junit</groupId> 
     <artifactId>junit</artifactId> 
     <version>4.11</version> 
     <scope>test</scope> 
    </dependency> 
    <dependency> 
     <groupId>org.apache.commons</groupId> 
     <artifactId>commons-lang3</artifactId> 
     <version>3.1</version> 
    </dependency> 
    <dependency> 
     <groupId>commons-io</groupId> 
     <artifactId>commons-io</artifactId> 
     <version>2.4</version> 
    </dependency> 
    <dependency> 
     <groupId>commons-logging</groupId> 
     <artifactId>commons-logging</artifactId> 
     <version>1.1</version> 
    </dependency> 
    <dependency> 
     <groupId>io.netty</groupId> 
     <artifactId>netty-all</artifactId> 
     <version>5.0.0.Alpha1</version> 
    </dependency> 
</dependencies> 

现在我的问题开始......如果我做MVN安装我将得到我的包以及其很好的MANIFEST.MF和所有的包,但我不会得到其他依赖包,这意味着如果我抓住我的包文件并将其放在OSGi框架实例上,我将获得类似“无法解决1.0:缺少需求[1.0] osgi.wiring.package; (&(osgi.wiring.package =等等......”

所以我发现我创建第1级依赖捆绑一个办法就是像这样在我的POM创建一个配置文件:

<profiles> 
    <!-- http://www.lucamasini.net/Home/osgi-with-felix/creating-osgi-bundles-of-your-maven-dependencies --> 
    <!-- -Pcreate-osgi-bundles-from-dependencies bundle:wrap --> 
    <profile> 
     <id>create-osgi-bundles-from-dependencies</id> 
     <build> 
      <directory>${basedir}/bundles</directory> 
      <plugins> 
       <plugin> 
        <groupId>org.apache.felix</groupId> 
        <artifactId>maven-bundle-plugin</artifactId> 
        <version>2.0.1</version> 
        <extensions>true</extensions> 
        <executions> 
         <execution> 
          <id>wrap-my-dependency</id> 
          <goals> 
           <goal>wrap</goal> 
          </goals> 
          <configuration> 
           <wrapImportPackage>;</wrapImportPackage> 
          </configuration> 
         </execution> 
        </executions> 
       </plugin> 
      </plugins> 
     </build> 
    </profile> 
</profiles> 

这样当我执行mvn -Pcreate-osgi-bundles-from-dependencies bundle:wrap我会得到捆绑,构造良好并且工作正常但是,这里就是真正的交易,这些捆绑还依赖于他们需要将他们的依赖包裹在一起,根据很多网页,很久以前我们有了mvn org.apache .felix:maven-bundle-plugin:bundleall目标是为我们做到这一点,但我试过了,它是buggy并且返回异常,并且它被标记为不推荐使用,根据Stuart的说法,它将在maven 2.4.1中被移除并且稍后(参考:https://issues.apache.org/jira/browse/FELIX-4145)。

所以,我唯一的解决办法,现在是,手动,检查我的第一级依赖每个清单和去谷歌包含所需的软件包的罐子,将它们添加到我的pom.xml作为Maven依赖,然后运行mvn -Pcreate-osgi-bundles-from-dependencies bundle:wrap将它们打包为捆绑包。

这就是被称为依赖地狱......

有什么办法来自动解决第n水平依赖于一个maven束的OSGi项目的这项任务?即让Maven研究我的第一级依赖关系的清单文件,阅读导入包,查看提供此类包的jar的中央回购站,下载它们并将它们打包为捆绑包?

注意:请提供有关如何实现此目的的详细说明,请不要链接到此工具或可以解决此问题的工具。这些工具的主要问题是缺少示例和文档。例如bundleall已被弃用,但似乎没有工具可以取代它,至少在maven bundle插件的官方文档中,到目前为止已弃用... 我确定我可能已经穿过工具能够做到这一点,但缺乏文件禁止新手用户知道...

谢谢!





编辑-1:

谢谢您的回答至今:) 我觉得我没有解释以最适当的方式我的情况我只是通过纯文本来完成这些工作,我感到有些困难。或者,也许我不明白你的答案。我在OSGi中颇为“全新”,我唯一的知识来自书籍(OSGi in Action等)和Google。

想象一下,我的包导入包A和包B.但包A导入包C,而包B也导入C.但是现在C进口包装D,E,F和G.另一方面,包装D进口一吨其他包装,E,F和G也是如此。

我的电脑中只有我自己的包装以及提供程序包A和B的软件包,因为它们是我的第一级依赖项。不过,我没有其他必需的捆绑包,即使它们作为jar安装在我的JDK安装文件夹中,我也没有将它们作为捆绑包捆绑,甚至我也不知道我可以从哪里获得jar来包装它们(其实我知道,但让我想象我不)。

我期望构建工具做的是运行类似以下的算法:

1)转到我的包MANIFEST.MF和读取进口包装领域。枚举所有必需的包和它们的响应。版本。

2)在互联网上的某个地方搜索我需要的图书馆的罐子或包。

3)下载每一个和检查,如果他们只是普通的罐子或有一个有效的OSGi清单文件(即它们是捆绑)

3.1)如果他们是捆绑,复制他们到我的包/文件夹。

3.2)其他包装罐子到使用任何工具来做到这一点和包复制到我的包/文件夹束。

4)现在,对于每个下载/创建的新捆绑包,重复步骤1),2),3)和4)。

我想作为最终结果是什么:一种,而我有直接或间接的依赖,这样我就可以将它们安装在我的OSGi框架实例上的飞,如费利克斯或每个库包春分。

我不想要什么:

1)必须手动做到这一点,因为如果我尝试解决依赖我可花了几个小时或几天收集和包装瓶的每个依赖性。

2)将所有依赖嵌入到ubber/mega包中。根据我读过的几本书,这是一个糟糕的做法,单独维护每个依赖项很困难,而且还会破坏模块化。

注:我的问题是不是包装罐成捆的特定任务,而是递归地做这件事,以每捆的进口,即使他们需要从在线存储库下载,如Maven的中央。

有没有办法自动做到这一点,或者我失去了一些关于OSGi的东西?这么大,我永远不需要这样做,我要求?

EDIT 2:

一些,如果不是全部,进口软件包的相关性,可以在运行时解决。想象一下,OSGi框架试图启动一个捆绑包,而不是显示“无法解析8.0:缺少需求[8.0] osgi.wiring.package;”的错误消息它会在网上搜索该软件包,下载并在运行中进行安装。生活会容易得多。

+1

如果我正确理解你的话,你想要在内部构建包含很多依赖关系的包?你可能知道osgi错了吗?如果您想将完整的应用程序打包到档案中,您可以创建一个EBA,并使用useTransitiveDependencies = true来包含所有3.方库。 –

+0

嗨,不,我不想将它们全部打包在一个存档中(archive = .jar文件是否正确?)。我只想让maven为我的项目的每个传递依赖关系生成一个包归档。理想情况下,他会阅读我的软件包的导入包字段,列出软件包名称和版本,转到maven的中央存储库,从那里获取所需的库,将不包含的包包装到捆绑包中,然后将它们粘贴到我的项目文件夹中。然后对每个传递依赖关系都做同样的事情。 – PedroD

+0

我想你是在误解一个包是什么。 bundle是一个包含所有特定类的容器,其他包(包括版本或版本范围)和导出语句的导入语句。你可以将你所有的三方库如commons-lang,commons-io等应用到你的应用程序并导入必要的语句。即使3. party libs有你需要在你的bundle中覆盖的静态字段,你也没问题,因为在OSGi中,每个bundle都有它自己的类加载器。 –

回答

3

使用maven-bundle-plugin中的条件包以递归方式将JAR包中的所有必需包内联并激活标记true。

+0

你能否请你发布你的解决方案@PedroD,我感兴趣:) – reyman64

5

如果你想包装不是捆绑的罐子,而只是需要这些罐子作为OSGi框架中的库,你可以用BND工具包装它。看到链接How to create/generate OSGi bundles from existing third-party jars?

但我可以看到你使用非常常见的libaries,已经被转换为osgi包。您可以在SpringSource Enterprise Bundle Repository中找到许多转换为捆绑的库。

但是,如果您找不到任何未转换为良好OSGi包的库,则可以使用PAX-URL中的WRAP协议在OSGi框架中安装这些依赖关系。要使用这些协议取决于您正在使用的OSGi框架,但在默认情况下安装在apache karaf中。例如,为了从行家库安装库:

[email protected]> osgi:install -s 'wrap:mvn:commons-lang/commons-lang/2.4$Bundle-SymbolicName=commons-lang&Bundle-Version=2.4' 

此指令从安装Maven仓库公地琅库到OSGi框架和将其包装成OSGi包与所述首标中出现的行。

对于像你在第二次编辑中所说的自动安装依赖关系,有几种解决方案,但是有一点工作。有两种主要的解决方案可以自动配置到OSGi框架,即“Felix OBR存储库”和“Felix Provisioning”捆绑软件和Equinox p2存储库。他们都有控制台命令来自动安装捆绑和功能。问题是,我实际上找不到一个好的公共捆绑软件包。您需要使用所有捆绑包构建您自己的存储库,而不是您需要的。

如果您使用maven-bundle-plugin,当您将工件安装到本地maven资源库中时,插件会更新文件“repository”。XML”位于你的资料库,以反映的根本要求和你捆绑的能力这个文件是一个OBR库文件

+0

阅读此:http://stackoverflow.com/questions/how-to-ask –

+0

嗨,感谢您的帮助! 是的,我知道有几种工具可以帮助我将jar文件打包成捆。我的问题比这个更大。我编辑了我的开篇文章(请参阅下面的文章),试图解释我的问题。 再次感谢! – PedroD

3

我想作为最终结果:A每个库包,而我 有直接或间接的依赖,这样我就可以 安装他们即时在我的OSGi框架实例,如费利克斯或秋分。

好吧,如果我正确地理解你的问题,你想要的东西一样maven-dependency-plugin?

 <plugin> 
      <groupId>org.apache.maven.plugins</groupId> 
      <artifactId>maven-dependency-plugin</artifactId> 
      <executions> 
       <execution> 
        <id>copy-dependencies</id> 
        <phase>package</phase> 
        <goals> 
         <goal>copy-dependencies</goal> 
        </goals> 
        <configuration> 
         <outputDirectory>${project.build.directory}/thridparty-libs</outputDirectory> 
         <overWriteIfNewer>true</overWriteIfNewer> 
         <includeScope>runtime</includeScope> 
         <excludeGroupIds>${project.groupId}</excludeGroupIds> 
         <excludeArtifactIds>...</excludeArtifactIds> 
        </configuration> 
       </execution> 
      </executions> 
     </plugin> 

如果您遇到问题,您有很多没有osgi-Manifest的依赖关系,您应该检查它们是否可用于springsource企业软件包存储库http://ebr.springsource.com/repository/和apache-servicemix软件包http://search.maven.org/#search|ga|1|g%3A%22org.apache.servicemix.bundles%22(如我的评论中所述)

+0

这很接近,但仍不会使大部分工作自动化。 我认为有一种方法可以配置OBR存储库来完成这项工作,我会在这里发布任何来自我方的更新,以便与任何感兴趣的人分享我可以找到的解决方案。 谢谢! – PedroD

0

尝试p2-maven-plugin它完全符合您从1到4所描述的内容。它实际上使用tycho来构建p2存储库,但您也可以使用它来收集和捆绑您的依赖关系和传递依赖关系。 我不写这里的例子,因为在上面的链接每一个想法都很好地记录在一个简单的理解方式的例子。

希望这有助于

0

此功能包括:文件夹中的罐子您的罐子依赖关系:OSGI-INF/lib目录/

在的build.gradle:

**

dependencies { 
    ...dependencies 
} 
def bundleClassPath() { 
    def list = [] 
    configurations.compile.each { 
     list += 'OSGI-INF/lib/' + it.name 
    } 
    return list.join(',') 
} 
def includeResource() { 
    def list = [] 
    configurations.compile.each { 
    list += 'OSGI-INF/lib/' + it.name + "=" + it.path 
    } 
    return list.join(',') 
} 
bundle { 
    instructions << [ 
    'Bundle-ClassPath' : bundleClassPath(), 
    '-includeresource' : includeResource() 
    ] 
} 

**