// 
//     Licensed to the Apache Software Foundation (ASF) under one
//     or more contributor license agreements.  See the NOTICE file
//     distributed with this work for additional information
//     regarding copyright ownership.  The ASF licenses this file
//     to you under the Apache License, Version 2.0 (the
//     "License"); you may not use this file except in compliance
//     with the License.  You may obtain a copy of the License at
// 
//       http://www.apache.org/licenses/LICENSE-2.0
// 
//     Unless required by applicable law or agreed to in writing,
//     software distributed under the License is distributed on an
//     "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
//     KIND, either express or implied.  See the License for the
//     specific language governing permissions and limitations
//     under the License.
//

= NetBeans IDEでのCDIを使用したOSGiバンドルのサービスとしての注入
:jbake-type: tutorial
:jbake-tags: tutorials 
:jbake-status: published
:icons: font
:syntax: true
:source-highlighter: pygments
:toc: left
:toc-title:
:description: NetBeans IDEでのCDIを使用したOSGiバンドルのサービスとしての注入 - Apache NetBeans
:keywords: Apache NetBeans, Tutorials, NetBeans IDEでのCDIを使用したOSGiバンドルのサービスとしての注入

このドキュメントでは、NetBeans IDEでのlink:http://www.osgi.org/Main/HomePage[+Open Services Gateway Initiative+] (OSGi)フレームワークの統合サポートによって、OSGiバンドルを作成するプロセスおよびプロジェクトでそのバンドルを使用するプロセスがどのように簡素化されているかについて説明します。このチュートリアルでは、Maven OSGiバンドル原型から2つの単純なOSGiバンドルを作成し、次にそれらのバンドルをGlassFish Server Open Source Edition 3.1にデプロイします。

基本的なOSGiバンドルの作成後、Webクライアント・アプリケーションを作成し、CDIを使用してそれらのバンドルをサービスとして注入します。次に、Webアプリケーションをバンドルとしてサーバーにデプロイします。このチュートリアルでは、次にOSGi管理コンソールを使用してOSGiバンドルを操作する方法について説明します。

エンタープライズ・アプリケーションでOSGiバンドルを使用すると、個別のバンドルを更新する際のモジュール性および柔軟性を高めることができます。GlassFishサーバーがデフォルトでOSGiをサポートすることによって、アプリケーションにバンドルを組み込む作業は非常に簡単になります。

このチュートリアルは、link:http://blog.arungupta.me/[+Arun Gupta氏のブログ+]で見ることができるブログ投稿link:http://blogs.oracle.com/arungupta/entry/totd_154_dynamic_osgi_services[+TOTD#154: Dynamic OSGi services in GlassFish 3.1 - Using CDI and@OSGiService+]およびその他のブログ・エントリに基づいています。OSGiの操作に関するその他の役立つ情報については、このブログを参照してください。

また、次のリソースには、ハイブリッド・アプリケーションでのOSGiとCDIの使用に関する情報が豊富に含まれています。

* link:http://weblogs.java.net/blog/2009/06/14/developing-hybrid-osgi-java-ee-applications-glassfish[+GlassFishでのハイブリッド(OSGi+Java EE)アプリケーションの開発+]
* link:http://blogs.oracle.com/sivakumart/entry/typesafe_injection_of_dynamic_osgi[+ハイブリッドJava EEアプリケーションでの動的なOSGiサービスの型安全のインジェクション+]
* link:http://weblogs.java.net/blog/2009/06/04/osgi-enabled-web-applications-inglassfish[+OSGiを有効にしたGlassFishのWebアプリケーション+]
* link:http://www.youtube.com/watch?v=vaOpJJ-Xm70[+ YouTube動画: GlassFish 3.1およびCDIを使用した動的なOSGiサービスの型安全のインジェクション +]
* link:http://glassfish.java.net/public/GF-OSGi-Features.pdf[+GlassFish Serverを使用したOSGiアプリケーションの開発+][PDF]

*チュートリアルの課題*

* <<Exercise_1,親POMプロジェクトの作成>>
* <<Exercise_2,OSGiバンドル・プロジェクトの作成>>
* <<Exercise_2a,MavenHelloServiceApiインタフェース・バンドルの作成>>
* <<Exercise_2b,MavenHelloServiceImpl実装バンドルの作成>>
* <<Exercise_2c,OSGiバンドルのビルドとデプロイ>>
* <<Exercise_3,Webクライアント・アプリケーションの作成>>
* <<Exercise_3a,POMプロジェクトでの依存性の構成>>
* <<Exercise_3b,MavenHelloWebClient Webアプリケーションの作成>>
* <<Exercise_3c,バンドルとしてのWebアプリケーションのビルド>>
* <<Exercise_3d,Webアプリケーション・バンドルのデプロイ>>
* <<Exercise_4,OSGi管理コンソールのインストールと使用>>
* <<Exercise_5,リファレンスおよび参考情報>>

*このチュートリアルに従うには、次のソフトウェアとリソースが必要です。*

|===
|ソフトウェアまたはリソース |必須バージョン 

|link:http://download.netbeans.org/netbeans/7.1/beta/[+NetBeans IDE+] |7.2、7.3、7.4、8.0、Java EEバージョン 

|link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[+Java Development Kit (JDK)+] |バージョン7または8 

|GlassFish Server Open Source Edition |3.1.xまたは4.x 
|===

*前提条件*

このドキュメントは、次のテクノロジについて基本的な知識またはプログラミング経験を持つ読者を想定して書かれています。

* Javaプログラミング
* NetBeans IDE
* Mavenフレームワーク

このチュートリアルを開始する前に、必要に応じて次のドキュメントをお読みください。

* link:http://wiki.netbeans.org/MavenBestPractices[+NetBeans IDEでのApache Mavenのベスト・プラクティス+]
* link:http://books.sonatype.com/mvnref-book/reference/introduction.html[+Chapter 1. Introducing Apache Maven+] (link:http://books.sonatype.com/mvnref-book/reference/index.html[+Maven: The Complete Reference +])
* link:http://www.osgi.org/javadoc/r4v42/[+OSGiフレームワーク+]

 


== 親POMプロジェクトの作成

この項では、このチュートリアルで作成するOSGiバンドル用の親POMプロジェクトを作成します。プロジェクトのPOM ( ``pom.xml`` )を編集して、子プロジェクトによって依存性として継承される依存性管理要素を追加します。

1. メイン・メニューから「新規プロジェクト」([Ctrl]-[Shift]-[N]、Macの場合は[⌘]-[Shift]-[N])を選択します。
2. 「Maven」カテゴリから「POMプロジェクト」を選択します。

image::images/cdi-newpomproject.png[title="新規プロジェクト・ウィザードのMaven POMプロジェクト原型"]


[start=3]
. 「プロジェクト名」に「*MavenOSGiCDIProject*」と入力します。「終了」をクリックします。

「終了」をクリックすると、IDEがPOMプロジェクトを作成し、そのプロジェクトが「プロジェクト」ウィンドウで開きます。


[start=4]
. 「プロジェクト」ウィンドウで「プロジェクト・ファイル」ノードを展開して「 ``pom.xml`` 」をダブルクリックし、エディタでそのファイルを開きます。

プロジェクトの基本的なPOMは、次のようになっているはずです。


[source,xml]
----

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>MavenOSGiCDIProject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
</project>
        
----

[start=5]
. 親の ``pom.xml`` を変更して、次の要素を追加します。変更を保存します。

[source,xml]
----

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>MavenOSGiCDIProject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    *<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.osgi</groupId>
                <artifactId>org.osgi.core</artifactId>
                <version>4.2.0</version>
                <scope>provided</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>*
</project>
        
----

この課題では、プロジェクトで使用するアーティファクトとアーティファクト・バージョンを明示的に指定しました。依存性管理を使用し、親POMにアーティファクトを指定することで、子プロジェクト内のPOMがより単純化され、プロジェクト内で依存性のバージョンの一貫性を確保できます。

依存性管理の使用の詳細は、link:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html[+依存性メカニズム入門+]を参照してください。


== OSGiバンドル・プロジェクトの作成

新規プロジェクト・ウィザードの「Maven」カテゴリには、OSGiバンドル・プロジェクトを作成するためのOSGiバンドルの原型が用意されています。OSGiバンドル・プロジェクトを作成すると、生成されたPOMは、 ``org.osgi.core``  JARを依存性として宣言し、プロジェクト・ビルド用に ``maven-bundle-plugin`` を指定します。


=== MavenHelloServiceApiインタフェース・バンドルの作成

この課題では、新規プロジェクト・ウィザードを使用して、他のバンドルによって実装される単純なインタフェースを提供するOSGiバンドル・プロジェクトを作成します。バンドルとインタフェースを作成したら、POMを変更して、親POMプロジェクトで指定した ``org.osgi.core`` アーティファクトに対する依存性を更新します。

1. 「ファイル」>「新規プロジェクト」を選択し、新規プロジェクト・ウィザードを開きます。
2. 「Maven」カテゴリから「OSGiバンドル」を選択します。「次」をクリックします。

image::images/cdi-new-osgiproject.png[title="新規プロジェクト・ウィザードのMaven OSGiバンドル原型"]


[start=3]
. 「プロジェクト名」に「*MavenHelloServiceApi*」と入力します。

[start=4]
. 「参照」をクリックし、「場所」として「*MavenOSGiCDIProject*」POMプロジェクトを選択します。「終了」をクリックします。

「終了」をクリックすると、IDEがバンドル・プロジェクトを作成し、そのプロジェクトが「プロジェクト」ウィンドウで開きます。エディタでMavenHelloServiceApiプロジェクトの ``pom.xml`` を開くと、 ``packaging`` 要素に ``bundle`` が指定されていること、およびバンドルのビルド時に ``maven-bundle-plugin`` が使用されることがわかります。


[source,xml]
----

<project>
    <modelVersion>4.0.0</modelVersion>
    <parent>
    <artifactId>MavenOSGiCDIProject</artifactId>
    <groupId>com.mycompany</groupId>
    <version>1.0-SNAPSHOT</version>
    </parent>

    <groupId>com.mycompany</groupId>
    <artifactId>MavenHelloServiceApi</artifactId>
    <version>1.0-SNAPSHOT</version>
    *<packaging>bundle</packaging>*
    <name>MavenHelloServiceApi OSGi Bundle</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>4.3.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                *<artifactId>maven-bundle-plugin</artifactId>*
                <version>2.3.7</version>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        <Bundle-Activator>com.mycompany.mavenhelloserviceimpl.Activator</Bundle-Activator>
                        <Export-Package />
                    </instructions>
                </configuration>
            </plugin>

            ...
        </plugins>
    </build>

    ...
<project>
----

また、Maven OSGiバンドル原型を使用してOSGiバンドル・プロジェクトを作成したときに、IDEによって ``org.osgi.core`` アーティファクトがデフォルトで依存性として追加されたこともわかります。


[start=5]
. 「プロジェクト」ウィンドウでMavenHelloServiceApiプロジェクト・ノードを右クリックし、「プロパティ」を選択します。

[start=6]
. 「プロジェクト・プロパティ」ダイアログ・ボックスで「ソース」カテゴリを選択します。

[start=7]
. 「*ソース/バイナリ形式*」を1.6に設定し、「*エンコーディング*」がUTF-8であることを確認します。「OK」をクリックします。

[start=8]
. 「プロジェクト」ウィンドウで「ソース・パッケージ」ノードを右クリックし、「新規」>「Javaインタフェース」を選択します。

[start=9]
. 「クラス名」に「*Hello*」と入力します。

[start=10]
. 「パッケージ」として「*com.mycompany.mavenhelloserviceapi*」を選択します。「終了」をクリックします。

[start=11]
. インタフェースに次の ``sayHello`` メソッド(太字部分)を追加し、変更内容を保存します。

[source,java]
----

public interface Hello {
    *String sayHello(String name);*
}
----

[start=12]
. 「プロジェクト」ウィンドウでプロジェクトのノードを右クリックし、「ビルド」を選択します。

プロジェクトをビルドした後、「ファイル」ウィンドウを開いてプロジェクト・ノードを展開すると、 ``target`` フォルダに ``MavenHelloServiceApi-1.0-SNAPSHOT.jar`` が作成されていることがわかります。

image::images/cdi-manifest.png[title="「ファイル」ウィンドウにコンパイルされたJARの内容が表示される"]

プロジェクトをビルドすると、 ``maven-bundle-plugin`` が ``MANIFEST.MF`` ファイルの生成を処理します。コンパイルされたJARの ``MANIFEST.MF`` ファイルを開くと、プラグインによって、エクスポート・パッケージを宣言するマニフェスト・ヘッダーが生成されたことがわかります。OSGiでは、公開して他のバンドルで使用できるようにするすべてのバンドルを ``MANIFEST.MF`` の ``Export-Package`` 要素内に列挙する必要があります。


[start=13]
.  ``MANIFEST.MF`` に ``Export-Package`` 要素(次の例で*太字*で示された要素)が含まれていることを確認します。

[source,java]
----

Manifest-Version: 1.0
Bnd-LastModified: 1395049732676
Build-Jdk: 1.7.0_45
Built-By: nb
Bundle-Activator: com.mycompany.mavenhelloserviceapi.Activator
Bundle-ManifestVersion: 2
Bundle-Name: MavenHelloServiceApi OSGi Bundle
Bundle-SymbolicName: com.mycompany.MavenHelloServiceApi
Bundle-Version: 1.0.0.SNAPSHOT
Created-By: Apache Maven Bundle Plugin
*Export-Package: com.mycompany.mavenhelloserviceapi;uses:="org.osgi.frame
 work";version="1.0.0.SNAPSHOT"*
Import-Package: org.osgi.framework;version="[1.6,2)"
Tool: Bnd-1.50.0
----

OSGiコンテナは ``Export-Package`` マニフェスト・ヘッダーを読み取り、バンドル外からアクセスできる、バンドル内のクラスを判断します。この例では、 ``com.mycompany.mavenhelloserviceapi`` パッケージ内のクラスが公開されています。

NOTE:  ``MANIFEST.MF`` に ``Export-Package`` 要素が含まれていない場合、「プロジェクト・プロパティ」ウィンドウでプラグインのデフォルト・プラグイン動作を有効にし、プロジェクトを再ビルドする必要があります。「プロジェクト・プロパティ」ウィンドウで「パッケージをエクスポート」カテゴリを選択し、*デフォルトmaven-bundle-plugin動作*オプションを選択します。「プロジェクト・プロパティ」ウィンドウの「パッケージをエクスポート」パネルを使用して、公開するパッケージを明示的に指定するか、 ``pom.xml`` に直接パッケージを指定します。

   


=== MavenHelloServiceImpl実装バンドルの作成

この課題では、POMプロジェクト内にMavenHelloServiceImplを作成します。

1. 「ファイル」>「新規プロジェクト」を選択し、新規プロジェクト・ウィザードを開きます。
2. 「Maven」カテゴリから「OSGiバンドル」を選択します。「次」をクリックします。
3. 「プロジェクト名」に「*MavenHelloServiceImpl*」と入力します。
4. 「参照」をクリックし、「場所」として「*MavenOSGiCDIProject*」POMプロジェクトを選択します(選択されていない場合)。「終了」をクリックします。
5. 「プロジェクト」ウィンドウでプロジェクトのノードを右クリックし、「プロパティ」を選択します。
6. 「プロジェクト・プロパティ」ダイアログ・ボックスで「ソース」カテゴリを選択します。
7. 「*ソース/バイナリ形式*」を1.6に設定し、「*エンコーディング*」がUTF-8であることを確認します。「OK」をクリックします。
8. 「プロジェクト」ウィンドウで「ソース・パッケージ」ノードを右クリックし、「新規」>「Javaクラス」を選択します。
9. 「クラス名」に「*HelloImpl*」と入力します。
10. 「パッケージ」として「*com.mycompany.mavenhelloserviceimpl*」を選択します。「終了」をクリックします。
11. 次(太字部分)を入力し、変更内容を保存します。

[source,java]
----

public class HelloImpl *implements Hello {
    
    public String sayHello(String name) {
        return "Hello " + name;*
    }
}
----

 ``Hello`` を実装すると、MavenHelloServiceApiプロジェクトを依存性として追加することによって解決する必要があるエラーがIDEに表示されます。


[start=12]
. 「プロジェクト」ウィンドウの*MavenHelloServiceImpl*の「依存性」ノードを右クリックし、「依存性の追加」を選択します。

[start=13]
. 「ライブラリの追加」ダイアログで、「開いているプロジェクト」タブをクリックします。

[start=14]
. 「MavenHelloServiceApi OSGiバンドル」を選択します。「追加」をクリックします。

image::images/cdi-add-dependency.png[title="「ライブラリの追加」ダイアログの「開いているプロジェクト」タブ"]


[start=15]
. エディタで開いている ``HelloImpl.java`` クラス内を右クリックして「インポートを修正」([Alt]-[Shift]-[I]、Macの場合は[⌘]-[Shift]-[I])を選択し、 ``com.mycompany.mavenhelloserviceapi.Hello`` のインポート文を追加します。変更を保存します。

[start=16]
. 「 ``com.mycompany.mavenhelloserviceimpl`` 」パッケージを展開し、「 ``Activator.java`` 」をダブルクリックしてこのファイルをエディタで開きます。

image::images/cdi-activator.png[title="「プロジェクト」ウィンドウのActivatorクラス"]

IDEによってプロジェクト内に ``Activator.java`` バンドル・アクティベータ・クラスが自動的に作成されます。バンドル・アクティベータは、バンドルのライフサイクルを管理するために使用されます。バンドル・アクティベータ・クラスは、バンドルの ``MANIFEST.MF`` で宣言され、バンドルがコンテナによって開始されるときにインスタンス化されます。

OSGiバンドルにはバンドル・アクティベータ・クラスは必要ありませんが、アクティベータ・クラスで ``start()`` メソッドを使用して、たとえば、バンドルが必要とするサービスまたはその他のリソースを初期化できます。この課題では、「出力」ウィンドウにメッセージを出力するクラスに、少量のコード行を追加します。これにより、バンドルが開始および停止するタイミングを簡単に識別できます。


[start=17]
. バンドル・アクティベータ・クラスの ``start()`` および ``stop()`` メソッドを変更して、次の行(太字部分)を追加します。

[source,java]
----

public class Activator implements BundleActivator {

    public void start(BundleContext context) throws Exception {
        *System.out.println("HelloActivator::start");
        context.registerService(Hello.class.getName(), new HelloImpl(), null);
        System.out.println("HelloActivator::registration of Hello service successful");*
    }

    public void stop(BundleContext context) throws Exception {
        *context.ungetService(context.getServiceReference(Hello.class.getName()));
        System.out.println("HelloActivator stopped");*
    }
}
----

バンドル・アクティベータ・クラスが ``org.osgi.framework.BundleActivator`` および ``org.osgi.framework.BundleContext`` をインポートしていることが確認できます。デフォルトでは、生成されたクラスには ``start()`` および ``stop()`` の2つのメソッドが含まれています。OSGiフレームワークは、 ``start()`` メソッドおよび ``stop()`` メソッドを呼び出して、バンドルの提供する機能を開始および停止します。バンドルが開始されると、そのバンドルの提供するサービス・コンポーネントが、OSGiサービス・レジストリに登録されます。あるバンドルが登録されると、他のバンドルは、そのレジストリを使用してアクティブなサービスを検索し、バンドル・コンテキストを経由してそのサービスを使用できます。

プロジェクトのPOMを見ると、 ``maven-bundle-plugin`` のconfiguration要素の下にバンドル・アクティベータを指定する ``<Bundle-Activator>`` 要素を確認できます。


[source,xml]
----

<plugin>
    <groupId>org.apache.felix</groupId>
    <artifactId>maven-bundle-plugin</artifactId>
    <version>2.3.7</version>
    <extensions>true</extensions>
      <configuration>
            <instructions>
                  *<Bundle-Activator>com.mycompany.mavenhelloserviceimpl.Activator</Bundle-Activator>*
            </instructions>
      </configuration>
</plugin>
----

バンドルをビルドすると、プラグインは、マニフェスト・ヘッダーをJAR内にあるバンドルのマニフェスト・ファイルに生成し、バンドル・アクティベータ・クラスを指定します。バンドルがデプロイされると、OSGiランタイムがマニフェスト・ファイル内の ``Bundle-Activator`` ヘッダーを検索します。


[start=18]
.  ``Activator.java`` のインポート文を修正して、 ``com.mycompany.mavenhelloserviceapi.Hello`` をインポートします。変更を保存します。

[start=19]
. 「依存性」ノードを展開し、 ``org.osgi.core`` アーティファクトが依存性として表示されたことを確認します。

NOTE: 「依存性」ノードに古いバージョンのアーティファクトがリストされている場合、アーティファクトを右クリックして「依存性を削除」を選択し、削除します。依存性は、MavenHelloServiceApiプロジェクトおよび ``org.osgi.core`` アーティファクトのみである必要があります。

image::images/cdi-implproject.png[title="「プロジェクト」ウィンドウのActivatorクラス"]
   


=== OSGiバンドルのビルドとデプロイ

この課題では、OSGiバンドルをビルドし、バンドルをGlassFishにデプロイします。

1. 「プロジェクト」ウィンドウでMavenOSGiCDIProjectノードを右クリックし、「消去してビルド」を選択します。

プロジェクトをビルドすると、IDEによって各プロジェクトの ``target`` フォルダ内にJARファイルが作成され、ローカル・リポジトリにもスナップショットJARがインストールされます。「ファイル」ウィンドウで、2つのバンドル・プロジェクトの ``target`` フォルダをそれぞれ展開すると、2つのJARアーカイブ( ``MavenHelloServiceApi-1.0-SNAPSHOT.jar`` および ``MavenHelloServiceImpl-1.0-SNAPSHOT.jar`` )が表示されます。


[start=2]
. GlassFishサーバーを起動します(まだ起動していない場合)。

[start=3]
.  ``MavenHelloServiceApi-1.0-SNAPSHOT.jar`` をGlassFishインストールの ``glassfish/domains/domain1/autodeploy/bundles/`` ディレクトリにコピーします。

「出力」ウィンドウ内のGlassFishのサーバー・ログに、次のような出力が表示されるはずです。


[source,java]
----

INFO: Started bundle: file:/glassfish-4.0/glassfish/domains/domain1/autodeploy/bundles/MavenHelloServiceApi-1.0-SNAPSHOT.jar

----

「出力」ウィンドウにサーバー・ログが表示されない場合は、「サービス」ウィンドウのGlassFishサーバー・ノードを右クリックして、「ドメイン・サーバー・ログを表示」を選択します。


[start=4]
. これらの手順を繰り返して、 ``MavenHelloServiceImpl-1.0-SNAPSHOT.jar`` を ``autodeploy/bundles`` ディレクトリにコピーします。

これで、GlassFishのサーバー・ログに次のような出力が表示されるはずです。


[source,java]
----

INFO: HelloActivator::start
INFO: HelloActivator::registration of Hello service successful
INFO: Started bundle: file:/glassfish-4.0/glassfish/domains/domain1/autodeploy/bundles/MavenHelloServiceImpl-1.0-SNAPSHOT.jar
INFO: Started bundle: file:/glassfish-4.0/glassfish/domains/domain1/autodeploy/bundles/MavenHelloServiceImpl-1.0-SNAPSHOT.jar
        
----

または、GlassFish OSGi管理コンソールからバンドルをインストールすることもできます。詳細は、<<Exercise_4,OSGi管理コンソールのインストールと使用>>の項を参照してください。


== Webクライアント・アプリケーションの作成

この項では、OSGiバンドルの提供するサービスにアクセスするJava EE Webクライアントの作成方法について説明します。単純なサーブレットをWebアプリケーションで作成し、宣言されたサービスを注入します。プロジェクトを作成する前に、親POMプロジェクトに依存性管理要素をいくつか追加します。


=== 親POMプロジェクトでの依存性の構成

この課題では、親POMプロジェクトに依存性要素を指定します。また、プロジェクトによって使用されるアーティファクトのリポジトリも追加します。

1. 「プロジェクト」ウィンドウで*MavenOSGiCDIProject*プロジェクトの「プロジェクト・ファイル」ノードを展開し、 ``pom.xml`` をダブルクリックしてエディタでこのファイルを開きます。
2. 親の ``pom.xml`` を変更して、次の依存性管理要素(太字部分)を追加します。変更を保存します。

[source,xml]
----

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>MavenOSGiCDIProject</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    ...    
            
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.osgi</groupId>
                <artifactId>org.osgi.core</artifactId>
                <version>4.3.0</version>
                <scope>provided</scope>
            </dependency>
            *<dependency>
                <groupId>org.osgi</groupId>
                <artifactId>org.osgi.compendium</artifactId>
                <version>4.2.0</version>
                <scope>provided</scope>
            </dependency>
            <dependency>
                <groupId>org.glassfish</groupId>
                <artifactId>osgi-cdi-api</artifactId>
                <version>3.1-b41</version>
                <type>jar</type>
                <scope>provided</scope>
            </dependency>*
          
        </dependencies>
    </dependencyManagement>

    ...
</project>

----

[start=3]
. 次の要素を追加して、POMにGlassFishリポジトリを追加します。変更を保存します。

[source,xml]
----

<project>

    ...

    </dependencyManagement>

    *<repositories>
        <!-- glassfish nexus repo for glassfish dependencies -->
        <repository>
            <id>glassfish-repo-archive</id>
            <name>Nexus repository collection for Glassfish</name>
            <url>http://maven.glassfish.org/content/groups/glassfish</url>
            <snapshots>
                <updatePolicy>never</updatePolicy>
            </snapshots>
        </repository>
    </repositories>*
    <modules>
        <module>MavenHelloServiceApi</module>
        <module>MavenHelloServiceImpl</module>
    </modules>
</project>
            
----

POMにGlassFishリポジトリを追加した後、「サービス」ウィンドウで「Mavenリポジトリ」ノードの下のリポジトリのリストを表示すると、IDEによってGlassFishリポジトリのノードが自動的に追加されたことがわかります。デフォルトでは、ローカルMavenリポジトリのノードがIDEに表示されます。開いているプロジェクトにリポジトリを指定すると、IDEによって「Mavenリポジトリ」ノードの下にリポジトリのノードが自動的に追加されます。

image::images/cdi-maven-repositories.png[title="「Mavenリポジトリ」ウィンドウのGlassFishリポジトリ"]

この課題では、プロジェクトで使用される追加のアーティファクトとアーティファクト・バージョンを追加しました。また、 ``osgi-cdi-api`` アーティファクトを含むGlassFishリポジトリも追加しました。


=== MavenHelloWebClient Webアプリケーションの作成

最初に通常のWebアプリケーションを作成し、次にプロジェクトを変更してOSGiバンドル(Webアプリケーション・バンドル(WAB))にします。

1. メイン・メニューから「ファイル」>「新規プロジェクト」を選択します。
2. 「Maven」カテゴリから「Webアプリケーション」を選択します。「次」をクリックします。
3. 「プロジェクト名」に「*MavenHelloWebClient*」と入力します。
4. 「参照」をクリックし、「場所」として「*MavenOSGiCDIProject*」POMプロジェクトを指定します(まだ選択されていない場合)。「次」をクリックします。
5. サーバーとして「GlassFish Server」を選択し、Java EEバージョンとして「Java EE 6 Web」または「Java EE 7 Web」を選択します。「終了」をクリックします。
6. プロジェクト・ノードを右クリックし、「新規」>「サーブレット」を選択します。
7. 「クラス名」に「*HelloServlet*」と入力します。
8. パッケージとして ``com.mycompany.mavenhellowebclient`` を選択します。「終了」をクリックします。
9. IDEによって生成されたサーブレット内のデフォルトのメソッド( ``processRequest`` 、 ``doGet`` 、 ``doPost`` 、 ``getServletInfo`` )を削除します。

NOTE: HttpServletメソッドを削除するには、エディタの折りたたみを展開する必要があります。


[start=10]
. 次のコード(太字部分)を入力してサービスを注入します。

[source,java]
----

@WebServlet(name = "HelloServlet", urlPatterns = {"/HelloServlet"})
public class HelloServlet extends HttpServlet {

    *@Inject
    @OSGiService(dynamic=true)
    Hello hello;*
}
----

[start=11]
. 次の ``doGet`` メソッドを追加します。

[source,java]
----

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        PrintWriter out = response.getWriter();
        out.println(hello.sayHello("Duke"));
    }
----

[start=12]
. プロジェクト・ノードを右クリックし、「新規」>「その他」を選択します。

[start=13]
. 「コンテキストと依存性の注入」カテゴリで*beans.xml*を選択します。「次」をクリックします。

[start=14]
. デフォルトのファイル名( ``beans`` )を使用します。「終了」をクリックします。

「終了」をクリックすると、ウィザードによってWebアプリケーション内に ``beans.xml`` ファイルが作成されます。 ``beans.xml`` がアプリケーションの一部である場合は、CDIが自動的に有効になります。


[start=15]
.  ``beans.xml`` ファイルを変更して、 ``bean-discovery-mode`` のデフォルト値を ``all`` に変更します。

[source,java]
----

bean-discovery-mode="*all*"
----

変更内容を保存し、ファイルを閉じます。

 ``bean-discovery-mode`` 値の間の違いについては、次のページを参照してください。

* Java EE 7チュートリアルのlink:http://docs.oracle.com/javaee/7/tutorial/doc/cdi-adv001.htm[+25.1 CDIアプリケーションのパッケージ+]
* link:http://stackoverflow.com/questions/18107858/cdi-inject-fails-on-maven-embedded-glassfish-plugin-org-jboss-weld-exceptions[+http://stackoverflow.com/questions/18107858/cdi-inject-fails-on-maven-embedded-glassfish-plugin-org-jboss-weld-exceptions+]

[start=16]
. 「プロジェクト」ウィンドウのMavenHelloWebClientの「依存性」ノードを右クリックし、「依存性の追加」を選択します。

[start=17]
. 「スコープ」として「*Provided*」を選択します。

[start=18]
. 「ライブラリの追加」ダイアログで、「開いているプロジェクト」タブをクリックし、「*MavenHelloServiceApi OSGiバンドル*」を選択します。「追加」をクリックします。

[start=19]
. もう一度「依存性」ノードを右クリックし、「依存性の追加」を選択します。

[start=20]
. 「ライブラリの追加」ダイアログで「依存性管理」タブをクリックし、親POMプロジェクトで指定した ``osgi-cdi-api`` アーティファクトを選択します。「追加」をクリックします。

image::images/cdi-add-dependency3.png[title="「ライブラリの追加」ダイアログの「依存性管理」タブ"]


[start=21]
. エディタで ``HelloServlet.java`` 内を右クリックし、「インポートを修正」([Alt]-[Shift]-[I]、Macの場合は[⌘]-[Shift]-[I])を選択して ``com.mycompany.mavenhelloserviceapi.Hello`` 、 ``javax.inject.Inject`` および ``org.glassfish.osgicdi.OSGiService`` を追加します。変更を保存します。

NOTE:  ``com.mycompany.mavenhelloserviceapi.Hello`` のインポート文がIDEによって自動的に追加されない場合は、手動で追加する必要があります。


[start=22]
. MavenOSGiCDIProjectを右クリックし、「消去してビルド」を選択します。

プロジェクトをビルドすると、「出力」ウィンドウに次のような出力が表示されるはずです。


[source,java]
----

Reactor Summary:

MavenOSGiCDIProject ............................... SUCCESS [0.798s]
MavenHelloServiceApi OSGi Bundle .................. SUCCESS [7.580s]
MavenHelloServiceImpl OSGi Bundle ................. SUCCESS [1.142s]
MavenHelloWebClient ............................... SUCCESS [8.072s]
------------------------------------------------------------------------
BUILD SUCCESS
----

NOTE: MavenOSGiCDIProjectプロジェクトをビルドするときに、Webアプリケーションが自動的にビルドされない場合は、Webアプリケーションを手動でビルドする必要があります。

「ファイル」ウィンドウで、Webアプリケーションのプロジェクト・ノードを展開して、アーカイブ ``MavenHelloWebClient-1.0-SNAPSHOT.war`` がターゲット・ディレクトリに作成されたことを確認します。WebクライアントのWARアーカイブを展開して ``MANIFEST.MF`` を調べると、マニフェストに次のような行が含まれていることがわかります。


[source,java]
----

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: nb
Build-Jdk: 1.7.0_45
----


=== OSGiバンドルとしてのWebアプリケーションのビルド

 ``@OSGiService`` を使用して登録済のOSGiバンドルを取得するには、Webアプリケーションを ``BundleContext`` にアクセスできるバンドルにする必要があります。WARをOSGiバンドル(Webアプリケーション・バンドル)にするには、WAR内の ``MANIFEST.MF`` に ``Web-ContextPath`` メタデータを追加します。  これを行うには、 ``maven-bundle-plugin`` への指示の中に ``<Web-ContextPath>`` 要素を指定し、このプラグインによって生成されるマニフェストにこの要素を含めます。次に、 ``maven-war-plugin`` の構成を変更して、 ``maven-bundle-plugin`` によって生成されたマニフェストをWARアーカイブに追加するようにプラグインに指示します。

1. 「プロジェクト」ウィンドウで、MavenHelloWebClientの下の「プロジェクト・ファイル」ノードを展開し、 ``pom.xml`` をダブルクリックしてエディタでこのファイルを開きます。
2. 次のエントリを追加して、POMに ``maven-bundle-plugin`` を追加します。

[source,xml]
----

<build> 
    <plugins>
        *<plugin>
             <groupId>org.apache.felix</groupId>
             <artifactId>maven-bundle-plugin</artifactId>
             <version>2.2.0</version>
             <extensions>true</extensions>
             <configuration>
                 <supportedProjectTypes>
                     <supportedProjectType>ejb</supportedProjectType>
                     <supportedProjectType>war</supportedProjectType>
                     <supportedProjectType>bundle</supportedProjectType>
                     <supportedProjectType>jar</supportedProjectType>
                 </supportedProjectTypes>
                 <instructions>
                     <!-- Specify elements to add to MANIFEST.MF -->
                     <Web-ContextPath>/mavenhellowebclient</Web-ContextPath>
                     <!-- By default, nothing is exported -->
                     <Export-Package>!*.impl.*, *</Export-Package>
                 </instructions>
             </configuration>
             <executions>
                 <execution>
                     <id>bundle-manifest</id>
                     <phase>process-classes</phase>
                     <goals>
                         <goal>manifest</goal>
                     </goals>
                 </execution>
                 <execution>
                     <id>bundle-install</id>
                     <phase>install</phase>
                     <goals>
                         <goal>install</goal>
                     </goals>
                 </execution>
             </executions>
         </plugin>*
            
----

[start=3]
.  ``maven-war-plugin`` の構成要素を変更して、 ``MANIFEST.MF`` にバンドル情報を追加します。変更を保存します。

[source,xml]
----

 <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.3</version>
     <configuration>
         *<archive>
             <!-- add bundle plugin generated manifest to the war -->
             <manifestFile>
                 ${project.build.outputDirectory}/META-INF/MANIFEST.MF
             </manifestFile>
             <!-- For some reason, adding Bundle-ClassPath in maven-bundle-plugin
             confuses that plugin and it generates wrong Import-Package, etc.
             So, we generate it here.-->
             <manifestEntries>
                 <Bundle-ClassPath>WEB-INF/classes/</Bundle-ClassPath>
             </manifestEntries>
         </archive>*
         <failOnMissingWebXml>false</failOnMissingWebXml>
     </configuration>
 </plugin>
----

[start=4]
. 「プロジェクト」ウィンドウでMavenHelloWebClientプロジェクト・ノードを右クリックし、「消去してビルド」を選択します。

これで、WARアーカイブを展開して ``MANIFEST.MF`` をエディタで開くと、 ``maven-bundle-plugin`` の構成で指定した ``Web-ContextPath: /mavenhellowebclient`` エントリやバンドル名エントリを含む追加情報が ``MANIFEST.MF`` に含まれていることがわかります。


[source,java]
----

Manifest-Version: 1.0
Export-Package: com.mycompany.mavenhellowebclient;uses:="com.mycompany
 .mavenhelloserviceapi,javax.servlet,org.glassfish.osgicdi,javax.injec
 t,javax.servlet.annotation,javax.servlet.http";version="1.0.0.SNAPSHO
 T"
Bundle-ClassPath: WEB-INF/classes/
Built-By: nb
Tool: Bnd-1.50.0
Bundle-Name: MavenHelloWebClient
Created-By: Apache Maven Bundle Plugin
*Web-ContextPath: /mavenhellowebclient*
Build-Jdk: 1.7.0_45
Bundle-Version: 1.0.0.SNAPSHOT
Bnd-LastModified: 1395053424008
Bundle-ManifestVersion: 2
Import-Package: com.mycompany.mavenhelloserviceapi;version="[1.0,2)",j
 avax.inject,javax.servlet,javax.servlet.annotation,javax.servlet.http
 ,org.glassfish.osgicdi;version="[1.0,2)"
Bundle-SymbolicName: com.mycompany.MavenHelloWebClient
Archiver-Version: Plexus Archiver
----

WebアプリケーションをOSGiバンドルとしてビルドする方法の詳細は、次のページを参照してください。

* link:http://weblogs.java.net/blog/2009/06/04/osgi-enabled-web-applications-inglassfish[+http://weblogs.java.net/blog/2009/06/04/osgi-enabled-web-applications-inglassfish+]
* link:http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html[+http://felix.apache.org/site/apache-felix-maven-bundle-plugin-bnd.html+]


=== Webアプリケーション・バンドルのデプロイ

この課題では、Webアプリケーション・バンドルをGlassFishインストールの ``autodeploy/bundles`` フォルダにコピーします。

1.  ``MavenHelloWebClient-1.0-SNAPSHOT.war`` を含む ``target`` ディレクトリに移動します。
2.  ``MavenHelloWebClient-1.0-SNAPSHOT.war`` をGlassFishインストールの ``autodeploy/bundles`` フォルダにコピーします。

WARアーカイブをこのディレクトリにコピーすると、GlassFishのサーバー・ログに次のような出力が表示されます。


[source,java]
----

INFO: Started bundle: file:/glassfish-3.1.1/glassfish/domains/domain1/autodeploy/bundles/MavenHelloWebClient-1.0-SNAPSHOT.war
...
INFO: ---- Injection requested for framework service type interface com.mycompany.mavenhelloserviceapi.Hello and annotated with dynamic=true, serviceCriteria=
INFO: WEB0671: Loading application [com.mycompany.MavenHelloWebClient_1.0.0.SNAPSHOT] at [/mavenhellowebclient]
INFO: Registered ServletContext as a service with properties: {osgi.web.symbolicname=com.mycompany.MavenHelloWebClient, osgi.web.version=1.0.0.SNAPSHOT, osgi.web.contextpath=/mavenhellowebclient} 
        
----

これで、次のリンクをクリックすることで、ブラウザにサーブレットを表示できます。link:http://localhost:8080/mavenhellowebclient/HelloServlet[+http://localhost:8080/mavenhellowebclient/HelloServlet+]


== OSGi管理コンソールのインストールと使用

GlassFish OSGi管理コンソールを使用して、サーバーにデプロイされているOSGiバンドルをインストール、起動および停止できます。この課題では、GlassFish OSGi管理コンソールを有効にしてから、登録済のOSGiバンドルのリストを表示します。

OSGiコンソールを有効にし、デプロイされたバンドルをGlassFishドメイン管理コンソールに表示するには、次の手順を実行して必要なGlassFishアドオンをインストールします。

1. ブラウザでGlassFishドメイン管理コンソールを開きます。

「サービス」ウィンドウのGlassFishサーバー・ノードを右クリックし、「ドメイン管理コンソールを表示」を選択します。


[start=2]
. 左側のナビゲーション列で「更新ツール」をクリックします。

[start=3]
. 利用可能なアドオンの一覧から ``glassfish-osgi-gui`` を選択します。

「インストール」をクリックしてライセンスに同意します。

image::images/cdi-glassfish-addons.png[title="更新ツールGlassFish管理コンソール"]


[start=4]
. GlassFishサーバーを再起動します。

*重要: *GlassFish Server 3.1.2.2を使用している場合、 ``_GLASSFISH-INSTALL_/glassfish/config/`` ディレクトリにある ``osgi.properties`` ファイルを変更し、 ``org.osgi.framework.startlevel.beginning`` プロパティの値を"2"に設定する( ``org.osgi.framework.startlevel.beginning=2`` )必要があります。
詳細は、次のフォーラムの投稿を参照してください。
link:http://www.java.net/forum/topic/glassfish/glassfish/cannot-start-web-console-glassfish-version-3122[+ Cannot start web console in Glassfish version 3.1.2.2+].


[start=5]
. 管理コンソールを再度開き、左側のナビゲーション列で「*サーバー(管理サーバー)*」をクリックします。

[start=6]
. 「OSGiコンソール」タブをクリックして、デプロイされているOSGiバンドルの一覧を表示します。

image::images/cdi-glassfish-console.png[title="「ライブラリの追加」ダイアログの「依存性管理」タブ"]

NOTE: OSGiバンドルのリストを表示する際に、ユーザー名とパスワードの入力を求められることがあります。OSGiコンソール・タブにバンドルのリストが表示されない場合は、承認ダイアログが非表示になっていないことを確認します。IDEのインストール時にGlassFish 4サーバーをインストールした場合、サーバーのデフォルトのユーザー名は ``admin`` です。デフォルトでは、パスワードは空白です。

一覧を下にスクロールして登録済のOSGiバンドルのステータスを表示したり、個々のバンドルを起動および停止したりできます。一覧をIDで(最大から最小へ)ソートすると、デプロイした3つのバンドルが一覧の最上位付近に表示されることがわかります。


link:/about/contact_form.html?to=3&subject=Feedback:%20Using%20CDI%20to%20Inject%20OSGi%20Bundles%20as%20Services[+このチュートリアルに関するご意見をお寄せください+]



== 関連項目

NetBeans IDEおよびMavenを使用してOSGiバンドルを開発する方法の詳細は、次のリソースを参照してください。

* link:http://wiki.netbeans.org/OSGiAndNetBeans[+wiki.netbeans.orgのOSGiおよびNetBeans+]
* link:http://wiki.netbeans.org/MavenBestPractices[+NetBeans IDEでのApache Mavenのベスト・プラクティス+]
* link:https://blogs.oracle.com/arungupta/entry/totd_125_creating_an_osgi[+今日のヒント第125回: NetBeansを使用したOSGiバンドルの作成およびGlassFishでのデプロイ+]
* link:../../trails/java-ee.html[+Java EEおよびJava Webの学習+]

link:../../../community/lists/top.html[+nbj2eeメーリング・リストに登録する+]ことによって、NetBeans IDE Java EE開発機能に関するご意見やご提案を送信したり、サポートを受けたり、最新の開発情報を入手したりできます。

