読者です 読者をやめる 読者になる 読者になる

taketoncheir.log

Like the Decatoncheir by Poseidon Industrial, This blog is Yet Another Storage for My Long Term Memories.

Maven - OSGiにおける依存関係の解決方法

Eclipse-pluginを作っているわけですが、依存関係の泥沼にはまりました。
最終的に解決に成功したので、ここに記しておきます。


まず、OSGiにおける依存の記述について。
OSGiの概要はここらへん見てもらえれば atmarkit


OSGiではBundle間の依存をMANIFEST.MFに記述します。
MANIFEST.MFのImport-PackageとExport-Package属性でスコープの管理をするわけです。
なので、まず必要なクラス群をBundleにする必要があります。
(tychoでいうeclipse-plugin)


この様子を図に示しました。
図ではSlf4j, junit, Seleniumに依存しつつ、Seleniumなどのthird-party libraryをBundle Bでラップし、Bundle AではBundle Bから提供されたAPIを用いてEclipse-pluginを記述するといった構成にしています。


f:id:tk_shg:20120520144329p:plain


まず、third-party librariesをどうしましょう。
当初自分は勘違いをし、各Bundle内に必要なjarを物理的に持たなくてはならないと思っていました。
でもそれは違います。
もしそうであれば、例えばSlf4jが全てのBundleで依存されていたとすると、全てのBundleにコピーしなければならなくなります。
答えは、Bundle化し、Exportで参照を提供する、です。
図では、Bundle Cに全てのthird party libraryを集め、Bundle CのMANIFEST.MFでExportを書いています。
(jarにするのにfelixのmaven-bundle-pluginを使いました)


Bundle CのexportをBundle A, Bで使うには、pom.xmlのdependencyにBundle Bを追加し、MANIFEST.MFにおいて

Import-Package: org.junit;version="4.10.0"

と書いてやります。
あるいは、Require-Bundle: my.bundle.CのようにBundle-SimbolicNameを書いても構いません。
こちらだとpackageを逐一追加する手間が省けます。


これら一連のプロジェクトは、maven-tychoを用いてビルドをしました。
ただし、Bundle A, B, Cを一度にビルドすることは出来ません。まず、Cのみビルドし、
Bundle A, Bを続けてビルドする必要があります(親pomのdependencyにBundle Cを追加します)。
また、もうひとつのハマりポイントとして、tychoは依存関係解決の方法としてMANIFEST.MFを優先するモードと、
pom.xmlを優先するモードの二つを持っています(参考)。
これらを混在させてはいけません(たぶん)。


今回はpomを読ませるモードで実行しました。
以下を該当プロジェクトのpom.xmlに設定します(親pomにセットしてもいいです)。
featureやrepositoryプロジェクトに対してもこれをセットする必要があります。

      <plugin>
        <groupId>org.eclipse.tycho</groupId>
        <artifactId>target-platform-configuration</artifactId>
        <version>${tycho-version}</version>
        <configuration>
          <pomDependencies>consider</pomDependencies>
        </configuration>
      </plugin>

たぶんこれでうまくいくはず。
この流れさえつかめば、ビルドしてcan't resolveと出たらpomのdependencyとMANIFESTのimportを記述して、、という形でいつかは解決できるはずです。
ちなみに、ImportしたパッケージをそのままExportするとエラーが出るような気がします(未確認)。


以上のゴールにたどり着くのに参考にしたのが、m2eプロジェクトでした。
github m2e-core


m2e-maven-runtimeにthird-partyを集めて、pomDependenciesを親pomでconsiderにセットし、かつ各MANIFEST.MFのImport/Exportで依存を記述しています。
特にtychoを使っている場合は参考になると思います。


以上です。今回もかなり疲れました(^_^;)
f:id:tk_shg:20120520144329p:plain