LoginSignup
11
1

More than 3 years have passed since last update.

Apache Karafの依存ライブラリバンドルの自作方法

Last updated at Posted at 2020-12-20

株式会社 日立製作所 謝洋

1. はじめに

Apache Karaf(以降、Karaf)では、Mavenレポジトリから依存ライブラリバンドルをインストール時に、直接インストールできないという問題があります。本記事ではmaven-bundle-pluginを利用して、依存ライブラリバンドルを自作する方法をご紹介します。

2. Karafとは

Karafは、Apache Camel(以降、Camel)を用いて開発したアプリを実行するプラットフォームです。Karafにインストールしたjarやwar(Karafでバンドルと呼ばれる)は、互いにパッケージを共有できます。そのため、Camelアプリはビルド時に依存ライブラリを追加せずとも、Karafにインストールした依存ライブラリからパッケージを利用できます。本書では、Karafにインストールした依存ライブラリを依存ライブラリバンドルと呼びます。

3. Mavenレポジトリを用いたライブラリバンドルのインストール

Karafでは、簡単にMavenレポジトリから依存ライブラリバンドルをインストールできます。インストールが成功すると、新しいバンドルが生成されて、IDが振られます。下記は、PostgreSQL JDBC Driverのインストールに成功した例です。

karaf@root()> install -s mvn:org.postgresql/postgresql/42.2.5
Bundle ID: 343

一方で、失敗する場合もあります。下記は、暗号化プロトコルを実装したJasypt (Java Simplified Encryption)のインストールに失敗した例です。

karaf@root()> install -s mvn:org.jasypt/jasypt/1.9.2
Bundle IDs:
Error executing command: Error installing bundles:
        Unable to install bundle mvn:org.jasypt/jasypt/1.9.2: org.osgi.framework.BundleException: OSGi R3 bundle not supported

これは、Mavenリポジトリからダウンロードしたjarに同梱されているManifestファイル(META-INF/MANIFEST.MF)に必要なバンドルヘッダがないためです。以降、バンドルヘッダおよびその設定方法を説明し、動作を確認します。また、バンドルヘッダ設定時の懸念点について解説します。

4. バンドルヘッダの説明

ここではバンドルヘッダを説明します。下記はManifestファイルの例です。この例には7つのバンドルヘッダを記載しています。

MANIFEST.MF
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Sample bundle
Bundle-SymbolicName: com.sample
Bundle-Version: 1.0.0
Embed-Dependency: sample
Import-Package: com.sample.import
Export-Package: com.sample.export

下記はそれぞれのヘッダの説明です。
※ 各バンドルヘッダの詳細説明については、OSGiのマニュアルをご参照ください。

# ヘッダ名 説明 必須
1 Manifest-Version マニフェストファイルのバージョン。Karafを利用する場合に、値を1.0に設定。
2 Bundle-ManifestVersion Manifestファイル構文のバージョン。Karafを利用する場合に、値を2に設定。
3 Bundle-Name Karafでのバンドルの表示名。
4 Bundle-SymbolicName バンドルを一意に識別する名前。
5 Bundle-Version バンドルのバージョン。この設定値は、バンドルがエクスポートするパッケージに自動的に付与される。
6 Embed-Dependency バンドルのnested jarを設定。
7 Import-Package バンドルが外部からインポートするJavaパッケージとバージョンを設定。
8 Export-Package バンドルが外部にエクスポートするJavaパッケージとバージョンを設定。

5. バンドルヘッダの設定方法

ここではバンドルヘッダの設定方法を説明します。本記事では、maven-bundle-pluginを利用してバンドルヘッダを設定します。以降、設定の手順を説明します。

  1. 空のCamelプロジェクトを新規で作成して、src/mainの下のファイルをすべて削除します。
  2. pom.xmlの依存関係を確認します。本記事では例としてjasypt 1.9.2の依存ライブラリバンドルを作成するので、下記の通りjasypt 1.9.2の依存関係を設定します。

    pom.xml
    <dependency>
      <groupId>org.jasypt</groupId>
      <artifactId>jasypt</artifactId>
      <version>1.9.2</version>
    </dependency>
    
  3. maven-bundle-pluginの設定を確認します。instructions要素の下に、Bundle-Name、Bundle-SymbolicName、Embed-Dependecy、Import-PackageおよびExport-Packageを設定します。 Manifest-VersionおよびBundle-ManifestVersionには自動的にデフォルト値が設定されるので、ここは設定不要です。

    pom.xml
      <plugin>
        <groupId>org.apache.felix</groupId>
        <artifactId>maven-bundle-plugin</artifactId>
        <version>${version.maven-bundle-plugin}</version>
        <extensions>true</extensions>
        <configuration>
          <instructions>
            <Bundle-Name>Jasypt 1.9.2</Bundle-Name>
            <Bundle-SymbolicName>com.sample.jasypt</Bundle-SymbolicName>
            <Bundle-Version>1.9.2</Bundle-Version>
            <Embed-Dependency>jasypt;scope=compile</Embed-Dependency>
            <Import-Package>com.ibm.icu.text;resolution:=optional,
               javax.crypto,
               javax.crypto,
               javax.servlet;resolution:=optional,
               javax.servlet.http;resolution:=optional
            </Import-Package>
            <Export-Package>org.jasypt.commons,
                org.jasypt.contrib.org.apache.commons.codec_1_3,
                org.jasypt.contrib.org.apache.commons.codec_1_3.binary;uses:=org.jasypt.contrib.org.apache.commons.codec_1_3,
                org.jasypt.digest;uses:="org.jasypt.digest.config,org.jasypt.salt",
                org.jasypt.digest.config;uses:="org.jasypt.salt",
                org.jasypt.encryption,
                org.jasypt.encryption.pbe;uses:="org.jasypt.encryption,org.jasypt.encryption.pbe.config,org.jasypt.exceptions,org.jasypt.salt",
                org.jasypt.encryption.pbe.config;uses:="org.jasypt.salt",
                org.jasypt.exceptions,
                org.jasypt.intf.cli,
                org.jasypt.intf.service,
                org.jasypt.normalization,
                org.jasypt.properties;uses:="org.jasypt.encryption,org.jasypt.util.text",
                org.jasypt.registry,
                org.jasypt.salt,
                org.jasypt.util.binary,
                org.jasypt.util.digest,
                org.jasypt.util.numeric,
                org.jasypt.util.password;uses:="org.jasypt.digest.config",
                org.jasypt.util.password.rfc2307;uses:="org.jasypt.util.password",
                org.jasypt.util.text,
                org.jasypt.web.pbeconfig;uses:="javax.servlet,javax.servlet.http,org.jasypt.encryption.pbe.config"
            </Export-Package>
          </instructions>
        </configuration>
      </plugin>
    

Import-PackageとExport-Packageに設定するパッケージは、カンマで区切ります。また、各パッケージにオプション設定を追加できます。オプション設定はセミコロンで区切ります。下記は各オプション設定の説明です。
※ 本記事で記載しているもの以外にもオプション設定はありますが、本記事では割愛します。興味がある方は、OSGiのマニュアルをご参照ください。

# 名前 種類 設定可能値 説明
1 resolution Import-Package mandatory, optional 依存関係が解決できない場合の操作を設定。デフォルト値のmandatoryでは、該当パッケージを解決できない場合に、バンドルを起動しない。optionalでは、該当パッケージを解決できなくても起動する。
2 version Import-Package 記法は以下の表に記載 インポートするパッケージのバージョン範囲を設定。
3 use Export-Package パッケージ名 該当パッケージの依存パッケージが同じバンドルに存在する場合、この項目で依存パッケージを設定。この設定をしないと、バンドルは外からパッケージを探す。
4 version Export-Package ピリオドで区切る3桁のバージョン 該当パッケージのバージョンを設定。設定しない場合、パッケージのバージョンがBundle-Versionの設定値となる。
  • Import-Packageのversionの記法例
# 記法例 説明
1 [1.2.3, 4.5.6) 1.2.3 <= x < 4.5.6
2 [1.2.3, 4.5.6] 1.2.3 <= x <= 4.5.6
3 (1.2.3, 4.5.6) 1.2.3 < x < 4.5.6
4 (1.2.3, 4.5.6] 1.2.3 < x <= 4.5.6
5 1.2.3 1.2.3 <= x

6. 動作確認

ここでは動作を確認します。動作確認の手順は下記です。

  1. pom.xmlを編集した後、Camelプロジェクトをビルドします。
  2. ビルドして生成したjarをKarafのホットデプロイフォルダに置きます。
  3. Karafコンソールに入って、下記のコマンドでバンドルが起動されたことを確認します。

    karaf@root()> list
    START LEVEL 100 , List Threshold: 50
    ID │ State  │ Lvl │ Version                         │ Name
    ────┼────────┼─────┼─────────────────────────────────┼────────────────────────────────────────────
    ...
    347 │ Active │  80 │ 1.9.2                           │ Jasypt 1.9.2
    
  4. 下記のコマンドで、作成したjasypt 1.9.2バンドルがパッケージをエクスポートしていることを確認します。

    karaf@root()> package:exports -b 347
    Package Name                                           │ Version │ ID  │ Bundle Name
    ───────────────────────────────────────────────────────┼─────────┼─────┼──────────────────
    org.jasypt.commons                                     │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.contrib.org.apache.commons.codec_1_3.binary │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.contrib.org.apache.commons.codec_1_3        │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.digest.config                               │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.digest                                      │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.encryption.pbe.config                       │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.encryption.pbe                              │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.encryption                                  │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.exceptions                                  │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.intf.cli                                    │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.intf.service                                │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.normalization                               │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.properties                                  │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.registry                                    │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.salt                                        │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.util.binary                                 │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.util.digest                                 │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.util.numeric                                │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.util.password.rfc2307                       │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.util.password                               │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.util.text                                   │ 1.9.2   │ 347 │ com.sample.jasypt
    org.jasypt.web.pbeconfig                               │ 1.9.2   │ 347 │ com.sample.jasypt
    

7. 懸念点

Karafでは、ユースケースに柔軟に対応するために同じパッケージの複数バージョンを配置できます。例えば、jasypt 1.9.2およびjasypt 1.9.3の依存ライブラリバンドルをkarafにインストールした場合、下記の通り1.9.2および1.9.3の両方のorg.jasypt.commonsパッケージがエクスポートされます。

karaf@root()> package:exports -p org.jasypt.commons
Package Name       │ Version │ ID  │ Bundle Name
───────────────────┼─────────┼─────┼─────────────────────────────────────
org.jasypt.commons │ 1.9.2   │ 347 │ com.sample.jasypt
org.jasypt.commons │ 1.9.3   │ 348 │ com.sample2.jasypt

このとき、Camelアプリでorg.jasypt.commonsをインポートするために、下記の通りImport-Packageのversionを設定したとします。

pom.xml
            <Import-Package>org.jasypt.commons;resolution:=optional;version="[1.9.0,2.0.0)"</Import-Package>

この場合、org.jasypt.commmons 1.9.2および1.9.3の両方がバージョンの範囲に該当するので、どちらもインポートされる可能性があります。また、バンドルの再起動などによって、他のバージョンに切り替わる可能性もあります。例えば、org.jasypt.commons 1.9.2をベースにCamelアプリを開発した場合、org.jasypt.commons 1.9.3にバージョンが切り替わってしまうと、Camelアプリの動作に影響が出る恐れがあります。このような問題を避けるため、Camel アプリのImport-Packageを厳密に設定することをお勧めします。
例えば、org.jasypt.commons 1.9.2のみをインポートしたい場合、下記のように設定をします。

pom.xml
            <Import-Package>org.jasypt.commons;resolution:=optional;version="[1.9.2)"</Import-Package>

version=1.9.2と設定すれば同じ結果を得られるのではとお考えの方もいるかと思いますが、Import-Packageのversionの記法例に示した通り、version=1.9.2と設定すると1.9.2以上のバージョンのパッケージをインポートすることを意味するため、同じ結果を得ることはできません。

8. おわりに

本記事ではmaven-bundle-pluginを活用することで、Karafの依存ライブラリバンドルを自作する方法を説明しました。Mavenレポジトリからダウンロードした依存ライブラリのjarファイルは直接Karafにインストールできない場合が多いので、本記事に記載した方法が役に立てばうれしいです。

11
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
1