| //  | 
 | //     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. | 
 | // | 
 |  | 
 | = Maven を使用した NetBeans プラットフォーム CRUD アプリケーションの作成 | 
 | :jbake-type: platform_tutorial | 
 | :jbake-tags: tutorials  | 
 | :jbake-status: published | 
 | :syntax: true | 
 | :source-highlighter: pygments | 
 | :toc: left | 
 | :toc-title: | 
 | :icons: font | 
 | :experimental: | 
 | :description: Maven を使用した NetBeans プラットフォーム CRUD アプリケーションの作成 - Apache NetBeans | 
 | :keywords: Apache NetBeans Platform, Platform Tutorials, Maven を使用した NetBeans プラットフォーム CRUD アプリケーションの作成 | 
 |  | 
 | link:https://netbeans.apache.org/platform/[*NetBeans プラットフォーム*]へようこそ! | 
 |  | 
 | このドキュメントでは、データベースに対して読み書きを行う簡単な NetBeans プラットフォームアプリケーションを、Maven 構築フレームワークを使用して作成する方法を示します。このドキュメントでは、Maven 原型を使用して、NetBeans プラットフォームのアプリケーションおよびモジュールを作成します。また、Swing UI ツールキットおよび「Matisse」GUI ビルダーを使用して、ウィンドウコンポーネントを作成します。 | 
 |  | 
 | このドキュメントは、Ant ベースの「 link:nbm-crud_ja.html[NetBeans プラットフォーム: NetBeans CRUD アプリケーションのチュートリアル]」に基づいており、NetBeans プラットフォームのアプリケーション開発において、Ant を使用する場合と Maven を使用する場合の違いについていくつか説明します。Maven と Ant との相違点を理解すれば、「 link:https://netbeans.apache.org/kb/docs/platform_ja.html[NetBeans プラットフォームの学習]」のチュートリアルを容易に理解できるようになります。 | 
 |  | 
 | CRUD サンプルアプリケーションは、「新規プロジェクト」ウィザードで利用できる Maven サンプルの 1 つです。 | 
 |  | 
 | NetBeans プラットフォームをはじめて使用する場合は、スクリーンキャストシリーズの「 link:https://netbeans.apache.org/tutorials/nbm-10-top-apis.html[NetBeans API のトップ 10]」を視聴いただくことをお勧めします。 | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 |  | 
 | NOTE:  | 
 |  | 
 | * JavaDB データベースサーバーおよびサンプルデータベースは、バンドルされている GlassFish Server Open Source Edition 3.0.1 に含まれています。 | 
 | * NetBeans プラットフォーム用のアプリケーション開発のために、別々のバージョンの NetBeans プラットフォームをダウンロードする必要はありません。通常、NetBeans IDE でアプリケーションおよびモジュールを開発し、NetBeans プラットフォームおよびアプリケーションを実行するのに必要なモジュールのみを追加します。 | 
 |  | 
 | このチュートリアルを開始する前に、必要に応じて次のドキュメントをお読みください。 | 
 |  | 
 | *  link:http://wiki.netbeans.org/MavenBestPractices[NetBeans 6.x での Apache Maven のベストプラクティス] | 
 | *  link:http://www.sonatype.com/books/maven-book/reference/introduction.html[Chapter 1. Introducing Apache Maven] (『 link:http://www.sonatype.com/books/maven-book/reference/public-book.html[Maven: The Definitive Guide]』) | 
 | *  link:https://netbeans.apache.org/kb/docs/java/gui-functionality_ja.html[GUI 構築入門] | 
 |  | 
 |  | 
 | == Maven の構成 | 
 |  | 
 | これがはじめての Maven プロジェクトである場合は、「オプション」ウィンドウで Maven の構成設定を確認します。このチュートリアルを完了するには、ローカルシステムに Maven がインストールされている必要があります。インストーラは  link:http://maven.apache.org/[Maven のサイト]からダウンロードできます。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「オプション」ウィンドウの「その他」カテゴリを選択して、「Maven」タブをクリックします。 | 
 |  | 
 | [start=2] | 
 | 1. Maven をインストールするローカルの場所を指定します (2.0.9 以降が必要)。 | 
 |  | 
 | [start=3] | 
 | 1. Maven のローカルリポジトリの場所が正しいことを確認します。 | 
 |  | 
 | [start=4] | 
 | 1. 「了解」をクリックします。 | 
 |  | 
 | ほとんどの場合、Maven の設定が標準的であれば、「オプション」ウィンドウの情報はすでに正しいものになっています。 | 
 |  | 
 | IDE は、Maven SCM を使用して Maven アーティファクトのチェックアウトを行います。ソースのチェックアウトを行うために必要なすべてのクライアントが、ローカルマシンにインストールされていて正しく設定されているか確認することをお勧めします。 | 
 |  | 
 | Maven SCM の詳細については、「 link:http://maven.apache.org/scm/index.html[Maven SCM のページ]」を参照してください。 | 
 |  | 
 |  | 
 | === Maven リポジトリの表示 | 
 |  | 
 | Maven ですべてのプロジェクトを構築するために使用されるアーティファクトは、Maven のローカルリポジトリに格納されます。アーティファクトがプロジェクトの依存リソースとして宣言されると、そのアーティファクトは登録されたリモートリポジトリの 1 つからローカルリポジトリにダウンロードされます。 | 
 |  | 
 | デフォルトで、NetBeans リポジトリおよびよく知られているインデックス付きの Maven リポジトリがいくつか登録され、リポジトリブラウザウィンドウに一覧表示されます。NetBeans リポジトリには、プロジェクトの構築に必要な、ほとんどの公開アーティファクトが含まれています。Maven リポジトリブラウザを使用すると、ローカルリポジトリとリモートリポジトリの内容を確認することができます。「ローカルリポジトリ」ノードを展開すると、ローカルにあるアーティファクトを表示できます。NetBeans リポジトリノードの下に一覧表示されているアーティファクトは、プロジェクトの依存リソースとして追加できますが、すべてのアーティファクトがローカルにあるわけではありません。これらはプロジェクトの依存リソースとして宣言されたときにだけ、ローカルリポジトリに追加されます。 | 
 |  | 
 | Maven リポジトリブラウザを開くには、次の手順に従います。 | 
 |  | 
 | * メインメニューから「ウィンドウ」>「その他」>「Maven リポジトリブラウザ」を選択します。 | 
 |  | 
 | image::images/maven-quickstart68_maven-nbm-netbeans-repo.png[title="Maven リポジトリブラウザのスクリーンショット"] | 
 |  | 
 | カーソルをアーティファクトの上に置くと、アーティファクトのコーディネートとともにツールチップが表示されます。ブラウザで、アーティファクトの JAR ファイルをダブルクリックすると、アーティファクトについての追加の詳細情報を確認できます。 | 
 |  | 
 | Maven リポジトリブラウザのツールバーにある「検索」ボタンをクリックするか、メインツールバーにあるクイック検索のテキストフィールドを使用すると、アーティファクトを検索できます。 | 
 |  | 
 | IDE での Maven のクラスパス依存リソースの管理と、Maven リポジトリの操作の詳細については、「 link:http://wiki.netbeans.org/MavenBestPractices[NetBeans 6.x での Apache Maven のベストプラクティス]」の「 link:http://wiki.netbeans.org/MavenBestPractices#Dependency_management[依存リソースの管理]」の節を参照してください。 | 
 |  | 
 | Artifact Viewer の使用方法のデモンストレーションを確認するには、「 link:https://netbeans.apache.org/kb/docs/java/maven-dependencies-screencast.html[Maven 依存リソースの操作]」のスクリーンキャストを参照してください。 | 
 |  | 
 |  | 
 | == NetBeans プラットフォームアプリケーションプロジェクトの作成 | 
 |  | 
 | この節では、「新規プロジェクト」ウィザードを使用して、Maven 原型から NetBeans プラットフォームアプリケーションを作成します。このウィザードにより、NetBeans プラットフォームアプリケーションを開発するために必要な Maven モジュールプロジェクトが作成されます。また、「新規プロジェクト」ウィザードを使用して、NetBeans モジュールも作成します。 | 
 |  | 
 |  | 
 | === プロジェクトの作成 | 
 |  | 
 | 「新規プロジェクト」ウィザードを使用して NetBeans プラットフォームアプリケーションを作成するには、次の手順を実行します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択し、「新規プロジェクト」ウィザードを開きます。 | 
 |  | 
 | [start=2] | 
 | 1. 「Maven」カテゴリから「Maven NetBeans アプリケーション」を選択します。「次へ」をクリックします。 | 
 |  | 
 | [start=3] | 
 | 1. 「プロジェクト名」に「*MavenPlatformCRUDApp*」と入力し、「プロジェクトの場所」を設定します。「完了」をクリックします。 | 
 |  | 
 | NOTE:  このウィザードでは、プラットフォームアプリケーションを作成するときに「次へ」をクリックするとモジュールプロジェクトを作成できますが、このチュートリアルはデモンストレーションであるため、アプリケーションとモジュールを別々に作成します。 | 
 |  | 
 |  | 
 | image::images/maven-crud_mavencrud-new-project.png[title="「新規プロジェクト」ウィザードのスクリーンショット"] | 
 |  | 
 | 「完了」をクリックすると、デフォルトで IDE が次のような Maven プロジェクトタイプを作成します。 | 
 |  | 
 | * *NetBeans Platform Application。*このプロジェクトはプラットフォームアプリケーションのコンテナプロジェクトです。このプロジェクトに、包含する各モジュールおよびプロジェクトのリポジトリの場所が一覧表示されます。このプロジェクトにソースは含まれません。IDE は、このプロジェクトのサブディレクトリに、ソースおよびリソースを含むモジュールを生成します。 | 
 | * *NetBeans Platform based application。*このプロジェクトは、アプリケーションをコンパイルするために必要なアーティファクト (ソース) を指定します。必要な依存リソース (IDE アーティファクト、モジュールアーティファクト) は、このプロジェクトの  ``pom.xml``  ファイルに指定されます。 | 
 | * *Platform application branding resources。*このプロジェクトには、アプリケーションのブランド設定に使用されるリソースが含まれています。 | 
 |  | 
 | image::images/maven-crud_mavencrud-projects-window1.png[title="「プロジェクト」ウィンドウのプロジェクト構造"] | 
 |  | 
 | NOTE:  | 
 |  | 
 | * これが Maven を使用した最初の NetBeans プラットフォームアプリケーションである場合、IDE が必要なすべてのアーティファクトを NetBeans リポジトリからダウンロードする必要があるため、プロジェクト作成まで少し時間がかかることがあります。 | 
 | * プロジェクトを作成するとき、いくつかのプロジェクト (NetBeans Platform based application プロジェクトなど) にバッジが付いていますが、これは  ``pom.xml``  ファイル (POM) で宣言されている依存リソースに使用できないものがあるためです。 | 
 |  | 
 |  | 
 | ===  モジュールの作成 | 
 |  | 
 | この課題では、「新規プロジェクト」ウィザードを使用して、NetBeans モジュールを作成します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択し、「新規プロジェクト」ウィザードを開きます。 | 
 |  | 
 | [start=2] | 
 | 1. 「Maven」カテゴリから「Maven NetBeans モジュール」を選択します。「次へ」をクリックします。 | 
 |  | 
 | [start=3] | 
 | 1. 「プロジェクト名」に「*MavenPlatformCRUDApp-dbaccess*」と入力します。 | 
 |  | 
 | [start=4] | 
 | 1. 「プロジェクトの場所」で「参照」をクリックして、*MavenPlatformCRUDApp* ディレクトリを指定します。「開く」をクリックします。 | 
 | image::images/maven-crud_mavencrud-select-location.png[title="プロジェクトディレクトリを示す「プロジェクトの場所を選択」ダイアログ"] | 
 |  | 
 | [start=5] | 
 | 1. 「完了」をクリックします。 | 
 |  | 
 | 「完了」をクリックすると、ウィザードによって *MavenPlatformCRUDApp-dbaccess* という名前の NetBeans モジュールプロジェクトが作成されます。モジュールはサブディレクトリに保存されると、アプリケーションに含まれるように自動的に設定されます。このプロジェクトの POM を開くと、MavenPlatformCRUDApp が親プロジェクトとして宣言されているのが確認できます。 | 
 |  | 
 |  | 
 | [source,xml] | 
 | ---- | 
 |  | 
 | <parent> | 
 |     <artifactId>MavenPlatformCRUDApp</artifactId> | 
 |     <groupId>com.mycompany</groupId> | 
 |     <version>1.0-SNAPSHOT</version> | 
 | </parent> | 
 | <artifactId>MavenPlatformCRUDApp-dbaccess</artifactId> | 
 | <packaging>nbm</packaging> | 
 | <version>1.0-SNAPSHOT</version> | 
 | <name>MavenPlatformCRUDApp - dbaccess NetBeans Module</name> | 
 |  | 
 | ---- | 
 |  | 
 | POM の  ``<name>``  要素を編集するか、プロジェクトの「プロパティー」ウィンドウで名前を変更すれば、モジュールの表示名を変更できます。デフォルトの表示名は、プロジェクトのアーティファクト ID  ``MavenPlatformCRUDApp-dbaccess``  です。 | 
 |  | 
 | 「プロジェクト」ウィンドウで「プロジェクトファイル」ノードの下にある NetBeans プラットフォームアプリケーションの POM を見ると、3 つのモジュールがアプリケーションのモジュールとして一覧表示されているのが確認できます。 | 
 |  | 
 |  | 
 | [source,xml] | 
 | ---- | 
 |  | 
 | <modules> | 
 |    <module>branding</module> | 
 |    <module>application</module> | 
 |    <module>MavenPlatformCRUDApp-dbaccess</module> | 
 | </modules> | 
 |  | 
 | ---- | 
 |  | 
 |  | 
 | === モジュールの依存リソース設定 | 
 |  | 
 | ここで、モジュールを「NetBeans Platform based application」の依存リソースとして追加する必要があります。依存リソースの追加は、エディタで  ``pom.xml``  を編集するか、「依存リソースを追加」ダイアログボックスを使用して行います。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「プロジェクト」ウィンドウで「*NetBeans Platform based application*」ノードを展開します。 | 
 |  | 
 | [start=2] | 
 | 1. 「ライブラリ」ノードを右クリックし、「依存リソースを追加」を選択します。 | 
 |  | 
 | [start=3] | 
 | 1. 「開いているプロジェクト」タブをクリックして、「*MavenPlatformCRUDApp - dbaccess*」を選択します。「了解」をクリックします。 | 
 | image::images/maven-crud_mavencrud-add-dependency1.png[title="「依存リソースを追加」ダイアログの「開いているプロジェクト」タブ"] | 
 |  | 
 | 「プロジェクト」ウィンドウで「NetBeans Platform based application」の「ライブラリ」ノードを展開すると、MavenPlatformCRUDApp-dbaccess が依存リソースとして表示されるようになっているのが確認できます。 | 
 |  | 
 | 「NetBeans Platform based application」の POM を見ると、モジュールのアーティファクト  ``MavenPlatformCRUDApp-dbaccess``  が、アプリケーションのコンパイルのための必須依存リソースとして表示されているのが確認できます。このアーティファクトは、モジュールプロジェクトを構築して、アーティファクトをローカルリポジトリにインストールしたあとで使用できます。 | 
 |  | 
 |  | 
 | [source,xml] | 
 | ---- | 
 |  | 
 | <dependency> | 
 |     <groupId>${project.groupId}</groupId> | 
 |     <artifactId>*MavenPlatformCRUDApp-dbaccess*</artifactId> | 
 |     <version>${project.version}</version> | 
 | </dependency> | 
 | ---- | 
 |  | 
 |  | 
 | === アプリケーションのブランド設定 | 
 |  | 
 | ブランド設定モジュールは、プラットフォームアプリケーションの構築時に使用されるブランド設定リソースを指定します。ブランド設定ダイアログでは、アプリケーション名、スプラッシュ画面、およびアプリケーションアイコンの指定や、テキスト要素の値の変更が簡単に行えます。 | 
 |  | 
 | この課題では、デフォルトのスプラッシュ画像を置き換えます。デフォルトでは、IDE によって生成されるブランド設定モジュールには、プラットフォームアプリケーションの起動時に表示される画像が含まれています。次の手順を実行して、この画像を別の画像に置き換えられます。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「プロジェクト」ウィンドウで「*Platform application branding resources*」モジュールを右クリックして、「ブランド設定」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「スプラッシュ画面」タブで、デフォルトのスプラッシュ画面の画像の隣にある「参照」ボタンをクリックして、使用する画像の場所に移動し、スプラッシュ画面として使用する画像を指定します。「了解」をクリックします。 | 
 |  | 
 | たとえば、次の画像をローカルシステムにコピーして、ブランド設定ダイアログでこの画像を指定することもできます。 | 
 |  | 
 |  | 
 | image::images/maven-crud_splash-crud.gif[title="デフォルトのスプラッシュ画像の例"] | 
 |  | 
 | アプリケーションを起動すると、起動中に新しい画像が表示されます。 | 
 |  | 
 |  | 
 | == エンティティークラスの作成 | 
 |  | 
 | この節では、Java DB データベースの表からエンティティークラスをいくつか生成します。アプリケーションにエンティティークラスを作成して JPA (Java Persistence API) を使用するには、データベースサーバーおよび JPA 持続性プロバイダライブラリにアクセスできる必要があります。このチュートリアルでは JavaDB データベースサーバーを使用しますが、アプリケーションがほかのデータベースサーバーを使用するように設定することもできます。 | 
 |  | 
 | リソースを使用できるようにするもっとも簡単な方法は、IDE にバンドルされている GlassFish Server Open Source Edition 3.0.1 のインスタンスを登録することです。Java DB データベースサーバー、サンプルデータベース、および JPA 持続性プロバイダは、GlassFish サーバーに含まれています。エンティティークラスを作成する前に、次の手順を実行して Java DB を起動してください。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「サービス」ウィンドウで「サーバー」ノードを展開して、GlassFish インスタンスが登録されていることを確認してください。 | 
 |  | 
 | [start=2] | 
 | 1. 「データベース」ノードを展開して、Java DB の *app* データベースのデータベース接続ノード ( ``jdbc:derby://localhost:1527/sample [APP の app]`` ) を右クリックし、「接続」を選択します。 | 
 |  | 
 | 「接続」を選択すると、データベースが起動していない場合は IDE によって起動されます。 | 
 |  | 
 |  | 
 | === 実行時依存リソースとしての DerbyClient の追加 | 
 |  | 
 | この課題では、依存リソースとして derbyclient-10.5.3.0_1 ライブラリを追加します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. *dbaccess* モジュールの「ライブラリ」ノードを右クリックし、「依存リソースを追加」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「グループ ID」に「*org.apache.derby*」、「アーティファクト ID」に「*derbyclient*」、そして「バージョン」に「*10.5.3.0_1*」と入力してライブラリを追加します。 | 
 |  | 
 | [start=3] | 
 | 1. 「スコープ」ドロップダウンリストから「*runtime*」を選択します。「了解」をクリックします。 | 
 | image::images/maven-crud_mavencrud-add-dependency-derby.png[title="「依存リソースを追加」ダイアログで derbyclient JAR を追加する"] | 
 |  | 
 | 「プロジェクト」ウィンドウで「実行時ライブラリ」ノードを展開すると、 ``derbyclient``  ライブラリが依存リソースとして表示されているのが確認できます。 | 
 |  | 
 | エディタで POM を変更して、依存リソースの  ``<scope>``  要素の値を指定することもできます。 | 
 |  | 
 |  | 
 | [source,xml] | 
 | ---- | 
 |  | 
 | <dependency> | 
 |             <groupId>org.apache.derby</groupId> | 
 |             <artifactId>derbyclient</artifactId> | 
 |             <version>10.5.3.0_1</version> | 
 |             <scope>runtime</scope> | 
 |         </dependency> | 
 | ---- | 
 |  | 
 |  | 
 | === データベースからのエンティティークラスの生成 | 
 |  | 
 | この節では、ウィザードを使用して *dbaccess* モジュールにエンティティークラスを生成します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. *dbaccess* モジュールの「ソースパッケージ」を右クリックして、「新規」>「その他」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「持続性」カテゴリから「データベースからのエンティティークラス」を選択します。「次へ」をクリックします。 | 
 |  | 
 | [start=3] | 
 | 1. 「データベース接続」ドロップダウンリストから Java DB サンプルデータベースを選択します。 | 
 |  | 
 | [start=4] | 
 | 1. 「使用可能な表」から「CUSTOMER」表を選択し、「追加」をクリックします。「追加」をクリックすると、関連する表である「DISCOUNT_CODE」も「選択した表」の一覧に追加されます。「次へ」をクリックします。 | 
 |  | 
 | [start=5] | 
 | 1. 「パッケージ」の名前に「*com.mycompany.mavenplatformcrudapp.dbaccess*」と入力します。「持続フィールド用の NamedQuery 注釈を生成」および「持続性ユニットを作成」が選択されていることを確認してください。「完了」をクリックします。 | 
 |  | 
 | 「完了」をクリックすると、IDE によって Customer および DiscountCode エンティティークラスが生成されます。また、IDE によって、 ``src/main/resources``  ディレクトリの「その他のソース」ノードの下にある  ``META-INF``  パッケージに  ``persistence.xml``  ファイルも生成されます。 | 
 |  | 
 |  | 
 | == READ: レコードの読み取りと表示 | 
 |  | 
 | この節では、ウィザードを使用して、*dbaccess* モジュールにウィンドウコンポーネントを追加します。ウィンドウコンポーネントでツリー表示を可能にして、オブジェクトをノードとして表示できるようにします。ノードのプロパティーウィンドウで、各レコードのデータを確認できます。 | 
 |  | 
 |  | 
 | === ウィンドウコンポーネントの追加 | 
 |  | 
 | この課題では、ウィンドウコンポーネントを作成します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「プロジェクト」ウィンドウでプロジェクトノードを右クリックし、「新規」>「ウィンドウ」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「ウィンドウの位置」ドロップダウンリストから「*editor*」を選択し、「*アプリケーションの起動時に開く*」を選択します。「次へ」をクリックします。 | 
 | image::images/maven-crud_mavencrud-new-window-customer.png[title="「新規ウィンドウ」ウィザードの「基本設定」ページ"] | 
 |  | 
 | [start=3] | 
 | 1. 「クラス名の接頭辞」に「*Customer*」と入力します。 | 
 |  | 
 | [start=4] | 
 | 1. 「パッケージ」に「*com.mycompany.mavenplatformcrudapp.viewer*」と入力します。「完了」をクリックします。 | 
 |  | 
 | ウィザードにより、作成されるファイルと変更されるファイルの一覧が表示されます。 | 
 |  | 
 | 「完了」をクリックすると、IDE によって「ソースパッケージ」の下の「 ``com.mycompany.mavenplatformcrudapp.viewer`` 」に  ``CustomerTopComponent.java``  クラスが生成されているのが「プロジェクト」ウィンドウで確認できます。プロジェクトの構造は、「ファイル」ウィンドウで確認できます。Maven プロジェクトをコンパイルするには、「ソースパッケージ」(「ファイル」ウィンドウの  ``src/main/java``  ディレクトリ) の下にソースファイルだけを配置する必要があります。リソースファイル (XML ファイルなど) は、「その他のソース」(「ファイル」ウィンドウの  ``src/main/resources``  ディレクトリ) の下に配置しなければいけません。 | 
 |  | 
 |  | 
 | === ツリー表示の追加 | 
 |  | 
 | ここで、ウィンドウコンポーネントを変更して、データベースレコードをツリー表示できるようにします。コンストラクタにエンティティーマネージャーを追加して、Bean のツリー表示を可能にします。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1.  ``CustomerTopComponent.java``  の「ソース」タブをクリックして、エディタでソースコードを表示します。 | 
 |  | 
 | [start=2] | 
 | 1. コンストラクタに次のコードを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public CustomerTopComponent() { | 
 |     initComponents(); | 
 |     setName(NbBundle.getMessage(CustomerTopComponent.class, "CTL_CustomerTopComponent")); | 
 |     setToolTipText(NbBundle.getMessage(CustomerTopComponent.class, "HINT_CustomerTopComponent")); | 
 | //        setIcon(ImageUtilities.loadImage(ICON_PATH, true)); | 
 |  | 
 |     *EntityManager entityManager = Persistence.createEntityManagerFactory("com.mycompany_MavenPlatformCRUDApp-dbaccess_nbm_1.0-SNAPSHOTPU").createEntityManager(); | 
 |     Query query = entityManager.createQuery("SELECT c FROM Customer c"); | 
 |     List<Customer> resultList = query.getResultList();* | 
 | } | 
 | ---- | 
 |  | 
 | コードの持続性ユニットの名前を  ``persistence.xml``  で指定されている名前と比較して、正しい名前になっているか確認してください。 | 
 |  | 
 |  | 
 | [start=3] | 
 | 1.  ``ExplorerManager.Provider``  を実装するように、クラスの署名を次のように変更します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public final class CustomerTopComponent extends TopComponent *implements ExplorerManager.Provider* | 
 | ---- | 
 |  | 
 |  | 
 | [start=4] | 
 | 1.  ``*javax.persistence.Query*``  および  ``*javax.util.List*``  をインポートするために、インポートを修正します。 | 
 |  | 
 | [start=5] | 
 | 1. 次のようにして、ExplorerManager の宣言と初期化を行います。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private static ExplorerManager em = new ExplorerManager(); | 
 | ---- | 
 |  | 
 |  | 
 | [start=6] | 
 | 1. abstract メソッドを実装し、 ``getExplorerManager``  メソッドを変更して、 ``em``  を返すようにします。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 | public ExplorerManager getExplorerManager() { | 
 |     return em; | 
 | } | 
 | ---- | 
 |  | 
 | クラスの署名に挿入カーソルを置いて Alt+Enter を押すと、abstract メソッドを実装できます。 | 
 |  | 
 |  | 
 | [start=7] | 
 | 1. コンストラクタに次のコードを追加して、ツリー表示を有効にします。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | BeanTreeView beanTreeView = new BeanTreeView(); | 
 | add(beanTreeView, BorderLayout.CENTER); | 
 | ---- | 
 |  | 
 |  | 
 | [start=8] | 
 | 1. 「デザイン」ビューでコンポーネントを右クリックして、「レイアウトを設定」>「ボーダーレイアウト」を選択します。変更を保存します。 | 
 |  | 
 |  | 
 | === ファクトリクラスの作成 | 
 |  | 
 | ここで、 ``com.mycompany.mavenplatformcrudapp.viewer``  パッケージに、データベース内の各顧客に新しい BeanNode を作成する新しいクラス *CustomerChildFactory* を作成します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「 ``*com.mycompany.mavenplatformcrudapp.viewer*`` 」パッケージを右クリックし、「新規」>「Java クラス」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「クラス名」に「*CustomerChildFactory*」と入力します。「完了」をクリックします。 | 
 |  | 
 | [start=3] | 
 | 1. 署名を変更して、 ``ChildFactory<Customer>``  を拡張します。 | 
 |  | 
 | [start=4] | 
 | 1. 表の項目一覧のためのフィールド  ``resultList``  を宣言して、 ``CustomerChildFactory``  メソッドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private List<Customer> resultList; | 
 |  | 
 | public CustomerChildFactory(List<Customer> resultList) { | 
 |     this.resultList = resultList; | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=5] | 
 | 1.  ``createKeys``  abstract メソッドを実装してから変更します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 |     protected boolean createKeys(List<Customer> list) { | 
 |       for (Customer customer : resultList) { | 
 |           list.add(customer); | 
 |       } | 
 |       return true; | 
 |     } | 
 | ---- | 
 |  | 
 |  | 
 | [start=6] | 
 | 1. ノードを作成するメソッドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 | protected Node createNodeForKey(Customer c) { | 
 |     try { | 
 |         return new BeanNode(c); | 
 |     } catch (IntrospectionException ex) { | 
 |         Exceptions.printStackTrace(ex); | 
 |         return null; | 
 |     } | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=7] | 
 | 1.  ``org.openide.nodes.Node``  および  ``java.beans.InstrospectionException``  をインポートするために、インポートを修正します。変更を保存します。 | 
 |  | 
 | クラスは次のようになります。 | 
 |  | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | package com.mycompany.mavenplatformcrudapp.viewer; | 
 |  | 
 | import com.mycompany.mavenplatformcrudapp.dbaccess.Customer; | 
 | import java.beans.IntrospectionException; | 
 | import java.util.List; | 
 | import org.openide.nodes.BeanNode; | 
 | import org.openide.nodes.ChildFactory; | 
 | import org.openide.nodes.Node; | 
 | import org.openide.util.Exceptions; | 
 |  | 
 | public class CustomerChildFactory extends ChildFactory<Customer> { | 
 |  | 
 |     private List<Customer> resultList; | 
 |  | 
 |     public CustomerChildFactory(List<Customer> resultList) { | 
 |         this.resultList = resultList; | 
 |     } | 
 |  | 
 |     @Override | 
 |     protected boolean createKeys(List<Customer> list) { | 
 |         for (Customer customer : resultList) { | 
 |             list.add(customer); | 
 |         } | 
 |         return true; | 
 |     } | 
 |  | 
 |     @Override | 
 |     protected Node createNodeForKey(Customer c) { | 
 |         try { | 
 |             return new BeanNode(c); | 
 |         } catch (IntrospectionException ex) { | 
 |             Exceptions.printStackTrace(ex); | 
 |             return null; | 
 |         } | 
 |     } | 
 |  | 
 | } | 
 | ---- | 
 |  | 
 | ここで、*CustomerTopComponent* を変更して、ExplorerManager を使用して JPA クエリーの結果リストを Node に渡すようにします。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. CustomerTopComponent コンストラクタに次の行を追加して、ノードのルートコンテキストを設定し、TopComponent の Lookup に TopComponent の ActionMap および ExplorerManager を追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 |     EntityManager entityManager =  Persistence.createEntityManagerFactory("com.mycompany_MavenPlatformCRUDApp-dbaccess_nbm_1.0-SNAPSHOTPU").createEntityManager(); | 
 |     Query query = entityManager.createQuery("SELECT c FROM Customer c"); | 
 |     List<Customer> resultList = query.getResultList(); | 
 |     *em.setRootContext(new AbstractNode(Children.create(new CustomerChildFactory(resultList), true))); | 
 |     associateLookup(ExplorerUtils.createLookup(em, getActionMap()));* | 
 | ---- | 
 |  | 
 | これにより、選択した各ノードのプロパティーウィンドウおよびツールチップのテキストが同期します。 | 
 |  | 
 |  | 
 | [start=2] | 
 | 1. インポートを修正して変更内容を保存します。 | 
 |  | 
 |  | 
 | === アプリケーションの実行 | 
 |  | 
 | この課題では、アプリケーションが正常にデータベースの表にアクセスして、読み取りを行えるかどうかを確認するためのテストを行います。アプリケーションは、 ``org-openide-nodes``  および  ``org-openide-explorer``  JAR に直接依存リソースを必要とするため、アプリケーションを構築および実行できるようにするには、POM を修正する必要があります。「プロジェクト」ウィンドウで依存リソースを変更できます。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「*dbaccess*」モジュールの「ライブラリ」ノードを展開します。 | 
 |  | 
 | [start=2] | 
 | 1. 「 ``org-openide-nodes`` 」JAR を右クリックし、「直接依存リソースとして宣言」を選択します。 | 
 |  | 
 | [start=3] | 
 | 1. 「 ``org-openide-explorer`` 」JAR を右クリックし、「直接依存リソースとして宣言」を選択します。 | 
 |  | 
 | [start=4] | 
 | 1. 「*MavenPlatformCRUDApp NetBeans Platform based application*」を右クリックして、「依存関係で構築」を選択します。 | 
 |  | 
 | 「出力」ウィンドウに、含まれるモジュールが表示されます。 | 
 |  | 
 |  | 
 | image::images/maven-crud_mavencrud-build-output1.png[title="構築順序を示す「出力」ウィンドウ"] | 
 |  | 
 | 「出力」ウィンドウには、構築状態も表示されます。 | 
 |  | 
 |  | 
 | image::images/maven-crud_mavencrud-build-output2.png[title="構築の成功を示す「出力」ウィンドウ"] | 
 |  | 
 | [start=5] | 
 | 1. アプリケーションを右クリックし、「実行」を選択します。 | 
 |  | 
 | アプリケーションが起動すると、データベースの表の各レコードのノードと一緒に「Customer」ウィンドウが表示されます。 | 
 |  | 
 |  | 
 | image::images/maven-crud_mavencrud-customer-window1.png[title="アプリケーションの「Customer」ウィンドウ"] | 
 |  | 
 | 「Customer」ウィンドウツリーでノードを右クリックして「プロパティー」を選択すると、その項目に関する追加情報が表示されます。 | 
 |  | 
 |  | 
 | image::images/maven-crud_mavencrud-read-properties.png[title="選択したノードの詳細を示す「プロパティー」ウィンドウ"] | 
 |  | 
 |  | 
 | == UPDATE: レコードの編集 | 
 |  | 
 | この節では、レコードの詳細を編集するためのウィンドウコンポーネントを追加します。 | 
 |  | 
 |  | 
 | === エディタウィンドウの作成 | 
 |  | 
 | この課題では、選択したノードの name および city フィールドを編集するための 2 つのテキストフィールドを含む、新しいウィンドウ「MyEditor」を作成します。そのあと、 ``layer.xml``  ファイルを変更して、「Customer」ウィンドウがエディタモードではなくエクスプローラモードで開くようにします。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「*dbaccess*」モジュールを右クリックして、「新規」>「ウィンドウ」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. ドロップダウンリストから「*editor*」を選択し、「*アプリケーションの起動時に開く*」を選択します。「次へ」をクリックします。 | 
 |  | 
 | [start=3] | 
 | 1. 「クラス名の接頭辞」に「*MyEditor*」と入力します。 | 
 |  | 
 | [start=4] | 
 | 1. 「パッケージ」に「*com.mycompany.mavenplatformcrudapp.editor*」と入力します。「完了」をクリックします。 | 
 |  | 
 | [start=5] | 
 | 1. 「 ``MyEditorTopComponent`` 」の「デザイン」ビューで、2 つの JLabel と 2 つの JTextField を追加します。 | 
 |  | 
 | [start=6] | 
 | 1. ラベルのテキストに「Name」と「City」を設定し、2 つの JTextField の変数名にそれぞれ「 ``*jTextField1*`` 」と「 ``*jTextField2*`` 」を設定します。変更を保存します。 | 
 | image::images/maven-crud_mavencrud-myeditor-window.png[title="「デザイン」ビューのウィンドウコンポーネント"] | 
 |  | 
 | [start=7] | 
 | 1. 「プロジェクト」ウィンドウで「重要なファイル」ノードを展開して「*XML レイヤー*」をダブルクリックし、エディタで  ``layer.xml``  ファイルを開きます。 | 
 |  | 
 | [start=8] | 
 | 1.  ``layer.xml``  を変更して、「CustomerTopComponent」ウィンドウがエクスプローラモードで表示されるようにします。変更を保存します。 | 
 |  | 
 | [source,xml] | 
 | ---- | 
 |  | 
 | <folder name="Modes"> | 
 |     <folder name="editor"> | 
 |         <file name="MyEditorTopComponent.wstcref" url="MyEditorTopComponentWstcref.xml"/> | 
 |     </folder> | 
 |     *<folder name="explorer"> | 
 |         <file name="CustomerTopComponent.wstcref" url="CustomerTopComponentWstcref.xml"/> | 
 |     </folder>* | 
 | </folder> | 
 |              | 
 | ---- | 
 |  | 
 | ここで、アプリケーションをテストして、ウィンドウが開くかどうか、および正しい位置に表示されるかどうかを確認できます。 | 
 |  | 
 | 「依存関係で構築」を実行する前に、アプリケーションに対して「生成物を削除」を実行するようにしてください。 | 
 |  | 
 | これで、「Customer」ウィンドウのノードを選択したときに、オブジェクトの name および city フィールドをエディタに表示するためのコードを追加できるようになりました。 | 
 |  | 
 |  | 
 | === LookupListener の使用 | 
 |  | 
 | この課題では、「Customer」ウィンドウを変更して、ノードを選択すると新しい  ``Customer``  オブジェクトが Node の Lookup に追加されるようにします。そのあと MyEditor を変更して、Lookup に追加された  ``Customer``  オブジェクトを待機する  `` link:http://bits.netbeans.org/dev/javadoc/org-openide-util-lookup/org/openide/util/LookupListener.html[LookupListener]``  をウィンドウに実装します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. *CustomerChildFactory* の  ``createNodeForKey``  メソッドが、 ``BeanNode``  ではなく  ``AbstractNode``  を作成するように変更します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 | protected Node createNodeForKey(Customer c) { | 
 |   *Node node = new AbstractNode(Children.LEAF, Lookups.singleton(c)); | 
 |   node.setDisplayName(c.getName()); | 
 |   node.setShortDescription(c.getCity()); | 
 |   return node;* | 
 | //        try { | 
 | //            return new BeanNode(c); | 
 | //        } catch (IntrospectionException ex) { | 
 | //            Exceptions.printStackTrace(ex); | 
 | //            return null; | 
 | //        } | 
 | } | 
 | ---- | 
 |  | 
 | 「Customer」ウィンドウで新しいノードを選択すると、選択された  ``Customer``  オブジェクトがウィンドウの Lookup に追加されます。 | 
 |  | 
 |  | 
 | [start=2] | 
 | 1. *MyEditorTopComponent* の「ソース」タブをクリックして、クラス署名が  ``LookupListener``  を実装するように変更します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public final class MyEditorTopComponent extends TopComponent *implements LookupListener* | 
 | ---- | 
 |  | 
 |  | 
 | [start=3] | 
 | 1. 結果を格納する変数を追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private Lookup.Result result = null; | 
 | ---- | 
 |  | 
 |  | 
 | [start=4] | 
 | 1. 必要な abstract メソッドを実装して、 ``resultChanged``  メソッドを追加します。 | 
 |  | 
 | [start=5] | 
 | 1.  ``resultChanged``  メソッドを変更して、新しい  ``Customer``  オブジェクトが Lookup に挿入されるたびに jTextField が更新されるようにします。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 |       @Override | 
 |       public void resultChanged(LookupEvent le) { | 
 |           Lookup.Result r = (Lookup.Result) le.getSource(); | 
 |           Collection<Customer> coll = r.allInstances(); | 
 |           if (!coll.isEmpty()) { | 
 |               for (Customer cust : coll) { | 
 |                   jTextField1.setText(cust.getName()); | 
 |                   jTextField2.setText(cust.getCity()); | 
 |               } | 
 |           } else { | 
 |               jTextField1.setText("[no name]"); | 
 |               jTextField2.setText("[no city]"); | 
 |           } | 
 |       } | 
 |  | 
 | ---- | 
 |  | 
 | LookupListener を定義したら、グローバルコンテキストから取得した  ``Lookup.Result``  に追加できます。グローバルコンテキストは、選択された Node のコンテキストの代わりとして機能します。たとえば、ツリー階層で「Ford Motor Co」を選択すると、「Ford Motor Co」の  ``Customer``  オブジェクトが Node の Lookup に追加されます。これが現時点で選択された Node となるため、「Ford Motor Co」の  ``Customer``  オブジェクトはグローバルコンテキストで使用できるようになります。次に、このオブジェクトが  ``resultChanged``  に渡され、テキストフィールドに値が取り込まれます。 | 
 |  | 
 |  | 
 | [start=6] | 
 | 1.  ``componentOpened``  および  ``componentClosed``  メソッドを変更して、エディタウィンドウが開いているときに LookupListener がアクティブになるようにします。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 |       @Override | 
 |       public void componentOpened() { | 
 |           result = WindowManager.getDefault().findTopComponent("CustomerTopComponent").getLookup().lookupResult(Customer.class); | 
 |           result.addLookupListener(this); | 
 |           resultChanged(new LookupEvent(result)); | 
 |       } | 
 |  | 
 |       @Override | 
 |       public void componentClosed() { | 
 |           result.removeLookupListener(this); | 
 |           result = null; | 
 |       } | 
 | ---- | 
 |  | 
 | アプリケーションが起動するとエディタウィンドウが開くように設定されているので、LookupListener はアプリケーションの起動時に使用可能になります。 | 
 |  | 
 | この例では、「Customer」ウィンドウによって提供されるローカルの Lookup を使用しています。ウィンドウは、この場合「 ``CustomerTopComponent`` 」という文字列で明示的に識別されます。この文字列は、 ``CustomerTopComponent``  のソースコードで、CustomerTopComponent の ID として指定されています。この方法は、MyEditorTopComponent が「CustomerTopComponent」の ID で TopComponent を検出できる場合にだけ機能します。 | 
 |  | 
 | 選択モデルの書き直しなどの、より柔軟な方法については、 link:http://weblogs.java.net/blog/timboudreau/archive/2007/01/how_to_replace.html[Tim Boudreau 氏によるこのブログエントリ]で説明されています。 | 
 |  | 
 | 「生成物を削除」および「依存関係で構築」を実行したら、アプリケーションを再度実行できます。「Customer」ウィンドウで新しい Node を選択すると、エディタウィンドウが更新されるようになりました。 ``BeanNode``  の代わりに  ``AbstractNode``  を使用しているため、ノードの「プロパティー」ウィンドウにプロパティーは表示されません。 | 
 |  | 
 |  | 
 | === 元に戻すおよび再実行の追加 | 
 |  | 
 | この課題では、 `` link:http://bits.netbeans.org/dev/javadoc/org-openide-awt/org/openide/awt/UndoRedo.html[UndoRedo]``  マネージャーを実装して、元に戻すおよび再実行機能を有効にします。ツールバーの「Undo」および「Redo」ボタンと、「Undo」および「Redo」メニュー項目は、ユーザーが「Editor」ウィンドウのいずれかのフィールドを変更すると有効になります。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 新しい UndoRedoManager を MyEditorTopComponent の先頭で宣言し、インスタンス化します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private UndoRedo.Manager manager = new UndoRedo.Manager(); | 
 | ---- | 
 |  | 
 |  | 
 | [start=2] | 
 | 1. 次のようにして、MyEditorTopComponent に  ``getUndoRedo()``  メソッドを作成します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 | public UndoRedo getUndoRedo() { | 
 |     return manager; | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=3] | 
 | 1. コンストラクタに次のコードを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | jTextField1.getDocument().addUndoableEditListener(manager); | 
 | jTextField2.getDocument().addUndoableEditListener(manager); | 
 | ---- | 
 |  | 
 | アプリケーションを実行して、「Undo」および「Redo」機能のボタンとメニュー項目が機能するかどうかをテストできます。 | 
 |  | 
 |  | 
 | === 保存機能の追加 | 
 |  | 
 | この課題では、NetBeans プラットフォームの保存機能を統合します。 ``layer.xml``  ファイルを変更して、ツールバーの「Save All」ボタンを隠し、「Save」ボタンを追加します。そのあと、テキストフィールドの変更を検出するリスナーと、変更が検出されたときにトリガーされる  ``fire``  メソッドを追加します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. *dbaccess* モジュールの  ``layer.xml``  ファイルを開き、Toolbar 要素を追加します。 | 
 |  | 
 | [source,xml] | 
 | ---- | 
 |  | 
 |     *<folder name="Toolbars"> | 
 |       <folder name="File"> | 
 |           <file name="org-openide-actions-SaveAction.shadow"> | 
 |               <attr name="originalFile" stringvalue="Actions/System/org-openide-actions-SaveAction.instance"/> | 
 |               <attr name="position" intvalue="444"/> | 
 |           </file> | 
 |           <file name="org-openide-actions-SaveAllAction.shadow_hidden"/> | 
 |       </folder> | 
 |     </folder>* | 
 | </filesystem> | 
 | ---- | 
 |  | 
 |  | 
 | [start=2] | 
 | 1. *MyEditorTopComponent* コンストラクタで、テキストフィールドで変更が検出されたときにメソッドを起動する、次の呼び出しを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public MyEditorTopComponent() { | 
 |  | 
 |           ... | 
 |     jTextField1.getDocument().addUndoableEditListener(manager); | 
 |     jTextField2.getDocument().addUndoableEditListener(manager); | 
 |  | 
 |     *jTextField1.getDocument().addDocumentListener(new DocumentListener() { | 
 |         public void insertUpdate(DocumentEvent arg0) { | 
 |           fire(true); | 
 |         } | 
 |         public void removeUpdate(DocumentEvent arg0) { | 
 |           fire(true); | 
 |         } | 
 |         public void changedUpdate(DocumentEvent arg0) { | 
 |           fire(true); | 
 |         } | 
 |     }); | 
 |  | 
 |     jTextField2.getDocument().addDocumentListener(new DocumentListener() { | 
 |         public void insertUpdate(DocumentEvent arg0) { | 
 |           fire(true); | 
 |         } | 
 |         public void removeUpdate(DocumentEvent arg0) { | 
 |           fire(true); | 
 |         } | 
 |         public void changedUpdate(DocumentEvent arg0) { | 
 |           fire(true); | 
 |         } | 
 |     }); | 
 |  | 
 |     //Create a new instance of our SaveCookie implementation: | 
 |     impl = new SaveCookieImpl(); | 
 |  | 
 |     //Create a new instance of our dynamic object: | 
 |     content = new InstanceContent(); | 
 |  | 
 |     //Add the dynamic object to the TopComponent Lookup: | 
 |     associateLookup(new AbstractLookup(content));* | 
 |  | 
 |     ... | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=3] | 
 | 1. 変更が検出されたときに呼び出される  ``fire``  メソッドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public void fire(boolean modified) { | 
 |   if (modified) { | 
 |       //If the text is modified, | 
 |       //we add SaveCookie impl to Lookup: | 
 |       content.add(impl); | 
 |   } else { | 
 |       //Otherwise, we remove the SaveCookie impl from the lookup: | 
 |       content.remove(impl); | 
 |   } | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=4] | 
 | 1.  ``fire``  メソッドによって  ``InstanceContent``  に追加される、次の  `` link:http://bits.netbeans.org/dev/javadoc/org-openide-nodes/org/openide/cookies/SaveCookie.html[SaveCookie]``  の実装を追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private class SaveCookieImpl implements SaveCookie { | 
 |  | 
 |   @Override | 
 |   public void save() throws IOException { | 
 |  | 
 |      Confirmation message = new NotifyDescriptor.Confirmation("Do you want to save \"" | 
 |               + jTextField1.getText() + " (" + jTextField2.getText() + ")\"?", | 
 |               NotifyDescriptor.OK_CANCEL_OPTION, | 
 |               NotifyDescriptor.QUESTION_MESSAGE); | 
 |  | 
 |       Object result = DialogDisplayer.getDefault().notify(message); | 
 |       //When user clicks "Yes", indicating they really want to save, | 
 |       //we need to disable the Save action, | 
 |       //so that it will only be usable when the next change is made | 
 |       //to the JTextArea: | 
 |       if (NotifyDescriptor.YES_OPTION.equals(result)) { | 
 |           fire(false); | 
 |           //Implement your save functionality here. | 
 |       } | 
 |   } | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=5] | 
 | 1. MyEditorTopComponent に次のフィールドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private final SaveCookieImpl impl; | 
 | private final InstanceContent content; | 
 |  | 
 | ---- | 
 |  | 
 |  | 
 | [start=6] | 
 | 1. インポートを修正して変更内容を保存します。 | 
 |  | 
 | [start=7] | 
 | 1. 「プロジェクト」ウィンドウで、「ライブラリ」ノードの下の「 ``org-openide-dialogs`` 」JAR を右クリックし、「直接依存リソースとして宣言」を選択します。 | 
 |  | 
 | ここで、アプリケーションに対して「生成物を削除」、「依存関係で構築」、および「実行」を行うと、テキストフィールドを変更したときに「Save」ボタンが有効になることを確認できます。 | 
 |  | 
 |  | 
 | === 変更内容の持続 | 
 |  | 
 | この課題では、変更内容を持続させるコードを追加します。現時点のアプリケーションでは、フィールドが変更されると正常にそれを認識し、変更内容を保存するオプションを有効にします。「Save」をクリックすると、変更内容を保存するかどうかの確認を求めるダイアログが表示されます。ただし、ダイアログで「了解」をクリックしても、変更内容は持続しません。変更内容を持続させるには、データベースの変更を維持するための JPA コードをいくつか追加する必要があります。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. *MyEditorTopComponent* に次のフィールドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | private Customer customer; | 
 | ---- | 
 |  | 
 |  | 
 | [start=2] | 
 | 1.  ``save``  メソッドを変更して、変更内容を持続させる JPA コードを追加します。これを行うには、「 ``//Implement your save functionality here.`` 」というコメントを次のコードに置き換えます。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 | public void save() throws IOException { | 
 | ... | 
 |     if (NotifyDescriptor.YES_OPTION.equals(result)) { | 
 |         fire(false); | 
 |         *EntityManager entityManager = Persistence.createEntityManagerFactory("com.mycompany_MavenPlatformCRUDApp-dbaccess_nbm_1.0-SNAPSHOTPU").createEntityManager(); | 
 |         entityManager.getTransaction().begin(); | 
 |         Customer c = entityManager.find(Customer.class, customer.getCustomerId()); | 
 |         c.setName(jTextField1.getText()); | 
 |         c.setCity(jTextField2.getText()); | 
 |         entityManager.getTransaction().commit();* | 
 |     } | 
 | } | 
 | ---- | 
 |  | 
 | 持続性ユニットの名前が正しいことを確認します。 | 
 |  | 
 | 「 ``customer.getCustomerId()`` 」の「customer」は、現時点では定義されていません。次の手順で、顧客 ID の取得に使用する現在の  ``Customer``  オブジェクトを  ``customer``  に設定します。 | 
 |  | 
 |  | 
 | [start=3] | 
 | 1. 次のボールドの行を  ``resultChanged``  メソッドに追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | @Override | 
 | public void resultChanged(LookupEvent le) { | 
 |     Lookup.Result r = (Lookup.Result) le.getSource(); | 
 |     Collection<Customer> coll = r.allInstances(); | 
 |     if (!coll.isEmpty()) { | 
 |       for (Customer cust : coll) { | 
 |           *customer = cust;* | 
 |           jTextField1.setText(cust.getName()); | 
 |           jTextField2.setText(cust.getCity()); | 
 |       } | 
 |     } else { | 
 |       jTextField1.setText("[no name]"); | 
 |       jTextField2.setText("[no city]"); | 
 |     } | 
 | } | 
 | ---- | 
 |  | 
 |  | 
 | [start=4] | 
 | 1. インポートを修正して変更内容を保存します。 | 
 |  | 
 | アプリケーションを実行してデータをいくつか変更すると、保存機能が正常に機能して変更内容が持続するかどうかをテストできます。この時点では、変更されたデータはエディタのフィールドに反映されません。データが持続するかどうかを確認するには、アプリケーションを再起動する必要があります。 | 
 |  | 
 | 次の課題では、データベースからデータを再読み込みして、エディタで変更内容が表示されるようにする「更新」機能を追加します。 | 
 |  | 
 |  | 
 | === 更新機能の追加 | 
 |  | 
 | この課題では、「Customer」ウィンドウのルートノードに「Refresh」メニュー項目を追加して、Customer ビューアを更新する機能を追加します。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「 ``*com.mycompany.mavenplatformcrudapp.viewer*`` 」パッケージを右クリックし、「新規」>「Java クラス」を選択して、*CustomerRootNode* という名前のクラスを作成します。 | 
 |  | 
 | [start=2] | 
 | 1. クラスで  ``AbstractNode``  を拡張し、次のメソッドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public class CustomerRootNode extends AbstractNode { | 
 |  | 
 |     *public CustomerRootNode(Children kids) { | 
 |       super(kids); | 
 |       setDisplayName("Root"); | 
 |     } | 
 |  | 
 |     @Override | 
 |     public Action[] getActions(boolean context) { | 
 |       Action[] result = new Action[]{ | 
 |           new RefreshAction()}; | 
 |       return result; | 
 |     } | 
 |  | 
 |     private final class RefreshAction extends AbstractAction { | 
 |  | 
 |       public RefreshAction() { | 
 |           putValue(Action.NAME, "Refresh"); | 
 |       } | 
 |  | 
 |       public void actionPerformed(ActionEvent e) { | 
 |           CustomerTopComponent.refreshNode(); | 
 |       } | 
 |     }* | 
 |  | 
 | } | 
 | ---- | 
 |  | 
 | 「Refresh」アクションは、新しいルートノードにバインドされます。 | 
 |  | 
 |  | 
 | [start=3] | 
 | 1. * ``javax.swing.Action`` * をインポートするために、インポートを修正します。変更を保存します。 | 
 |  | 
 | [start=4] | 
 | 1. *CustomerTopComponent* を変更して、ビューを再表示するための次のメソッドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public static void refreshNode() { | 
 |     EntityManager entityManager = Persistence.createEntityManagerFactory("com.mycompany_MavenPlatformCRUDApp-dbaccess_nbm_1.0-SNAPSHOTPU").createEntityManager(); | 
 |     Query query = entityManager.createQuery("SELECT c FROM Customer c"); | 
 |     List<Customer> resultList = query.getResultList(); | 
 |     em.setRootContext(new *CustomerRootNode*(Children.create(new CustomerChildFactory(resultList), true))); | 
 | } | 
 | ---- | 
 |  | 
 | このメソッドは、ルートコンテキストの設定に *CustomerRootNode* を使用します。 | 
 |  | 
 |  ``CustomerRootNode``  クラスでは、 ``refreshNode``  が含まれる行で Alt+Enter を押すと、IDE によってメソッドのスケルトンが生成されます。 | 
 |  | 
 |  | 
 | [start=5] | 
 | 1. CustomerTopComponent のコンストラクタのコードを、*AbstractNode* の代わりに *CustomerRootNode* への呼び出しに変更します。 | 
 |  | 
 |  ``CustomerRootNode``  を呼び出すと自動的に  ``refreshNode``  メソッドが呼び出され、「Refresh」が呼び出されます。 | 
 |  | 
 |  | 
 | [start=6] | 
 | 1. インポートを修正して変更内容を保存します。 | 
 |  | 
 | アプリケーションを実行すると、ポップアップメニューで「Refresh」アクションが使用できる、新しいルートノードがあることが確認できます。 | 
 |  | 
 |  ``refreshNode``  メソッドを再利用して自動再表示を実装できます。 ``save``  メソッドから  ``refreshNode``  メソッドを呼び出してください。または、「Refresh」アクションを含む別のモジュールを作成して、このモジュールをモジュール間で共有することもできます。 | 
 |  | 
 |  | 
 | == CREATE: 新規レコードの作成 | 
 |  | 
 | この節では、データベース内にユーザーが新しいエントリを作成できるようにします。 | 
 |  | 
 |  | 
 | === 作成アクションの追加 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「*dbaccess*」モジュールを右クリックして、「新規」>「アクション」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「常に有効化」を選択します。「次へ」をクリックします。 | 
 |  | 
 | [start=3] | 
 | 1. 「カテゴリ」ドロップダウンリストから「*ファイル*」を選択します。 | 
 |  | 
 | [start=4] | 
 | 1. 「大域ツールバーボタン」を選択します。「次へ」をクリックします。 | 
 | image::images/maven-crud_mavencrud-new-action.png[title="「新規アクション」ウィザードの「GUI の登録」"] | 
 |  | 
 | [start=5] | 
 | 1. 「クラス名」に「*NewAction*」と入力します。 | 
 |  | 
 | [start=6] | 
 | 1. 「表示名」に「*My New Action*」と入力します。 | 
 |  | 
 | [start=7] | 
 | 1. 「参照」をクリックして、ツールバーで使用する画像を選択します。 | 
 |  | 
 | 次の画像  ``abc16.png``  をデスクトップにコピーして、ウィザードでこの画像を指定することもできます。(  | 
 | image::images/maven-crud_abc16.png[title="サンプル 16 x 16 アイコン"] ) | 
 |  | 
 |  | 
 | [start=8] | 
 | 1. 「*com.mycompany.mavenplatformcrudapp.editor*」パッケージを選択します。「完了」をクリックします。 | 
 |  | 
 | [start=9] | 
 | 1.  ``NewAction``  クラスを、MyEditorTopComponent を開いてフィールドを削除するように変更します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | import java.awt.event.ActionEvent; | 
 | import java.awt.event.ActionListener; | 
 |  | 
 | public final class NewAction implements ActionListener { | 
 |  | 
 |     public void actionPerformed(ActionEvent e) { | 
 |         MyEditorTopComponent tc = MyEditorTopComponent.getDefault(); | 
 |         tc.resetFields(); | 
 |         tc.open(); | 
 |         tc.requestActive(); | 
 |     } | 
 |  | 
 | } | 
 | ---- | 
 |  | 
 | このアクションは、ActionListener クラスを実装します。このクラスは、レイヤーファイル内のエントリを通じてアプリケーションにバインドされ、「新規アクション」ウィザードによってアプリケーションに挿入されます。 | 
 |  | 
 |  | 
 | === 新規オブジェクトの作成および保存 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. *MyEditorTopComponent* で、JTextFields をリセットし、新しい  ``Customer``  オブジェクトを作成する次のメソッドを追加します。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public void resetFields() { | 
 |     customer = new Customer(); | 
 |     jTextField1.setText(""); | 
 |     jTextField2.setText(""); | 
 | } | 
 | ---- | 
 |  | 
 |  ``NewAction``  クラスでは、 ``resetFields``  への呼び出しで Alt+Enter を押すと、IDE によって MyEditorTopComponent にメソッドのスケルトンが生成されます。 | 
 |  | 
 |  | 
 | [start=2] | 
 | 1. SaveCookie で、null の戻り値が、既存のエントリの更新ではなく、新しいエントリが保存されたことを示すようにします。 | 
 |  | 
 | [source,java] | 
 | ---- | 
 |  | 
 | public void save() throws IOException { | 
 |  | 
 |     Confirmation message = new NotifyDescriptor.Confirmation("Do you want to save \"" | 
 |                   + jTextField1.getText() + " (" + jTextField2.getText() + ")\"?", | 
 |                   NotifyDescriptor.OK_CANCEL_OPTION, | 
 |                   NotifyDescriptor.QUESTION_MESSAGE); | 
 |  | 
 |     Object result = DialogDisplayer.getDefault().notify(msg); | 
 |  | 
 |     //When user clicks "Yes", indicating they really want to save, | 
 |     //we need to disable the Save button and Save menu item, | 
 |     //so that it will only be usable when the next change is made | 
 |     //to the text field: | 
 |     if (NotifyDescriptor.YES_OPTION.equals(result)) { | 
 |         fire(false); | 
 |         EntityManager entityManager = Persistence.createEntityManagerFactory("CustomerLibraryPU").createEntityManager(); | 
 |         entityManager.getTransaction().begin(); | 
 |         *if (customer.getCustomerId() != null) {* | 
 |             Customer c = entityManager.find(Customer.class, cude.getCustomerId()); | 
 |             c.setName(jTextField1.getText()); | 
 |             c.setCity(jTextField2.getText()); | 
 |             entityManager.getTransaction().commit(); | 
 |         *} else { | 
 |             Query query = entityManager.createQuery("SELECT c FROM Customer c"); | 
 |             List<Customer> resultList = query.getResultList(); | 
 |             customer.setCustomerId(resultList.size()+1); | 
 |             customer.setName(jTextField1.getText()); | 
 |             customer.setCity(jTextField2.getText()); | 
 |             //adds more fields that will populate the zip and discountCode columns | 
 |             customer.setZip("12345"); | 
 |             customer.setDiscountCode(entityManager.find(DiscountCode.class, 'H')); | 
 |  | 
 |             entityManager.persist(customer); | 
 |             entityManager.getTransaction().commit(); | 
 |         }* | 
 |     } | 
 |  | 
 | } | 
 | ---- | 
 |  | 
 | また、DiscountCode を空にすることはできないため、このフィールドに任意のデータを書き込んでいます。 | 
 |  | 
 |  | 
 | [start=3] | 
 | 1.  ``*javax.persistence.Query*``  をインポートするために、インポートを修正します。変更を保存します。 | 
 |  | 
 |  | 
 | == アプリケーションの構築と実行 | 
 |  | 
 | これで、アプリケーションは CRUD 機能のうちの 3 つ (Create、Read、および Update) を実行できるようになりました。ここでアプリケーションを構築および実行し、すべての機能が正常に動作するかを確認できます。 | 
 |  | 
 |  | 
 | [start=1] | 
 | 1. 「*MavenPlatformCRUDApp NetBeans Platform based application*」のプロジェクトノードを右クリックして、「生成物を削除」を選択します。 | 
 |  | 
 | [start=2] | 
 | 1. 「*MavenPlatformCRUDApp NetBeans Platform based application*」のプロジェクトノードを右クリックして、「依存関係で構築」を選択します。 | 
 |  | 
 | [start=3] | 
 | 1. 「*MavenPlatformCRUDApp NetBeans Platform based application*」のプロジェクトノードを右クリックして、「実行」を選択します。 | 
 |  | 
 | 「実行」をクリックすると、IDE によってプラットフォームアプリケーションが起動します。アプリケーションは、データベースの顧客名を使用して「Customer」ウィンドウにツリーを生成します。「Customer」ウィンドウでノードを選択すると、選択した顧客の名前および都市が「My Editor」ウィンドウに表示されます。「Name」および「City」フィールドのデータを変更して保存できます。新しい顧客を作成するには、ツールバーで「My Action」ボタンをクリックし、「My Editor」ウィンドウの空のテキストフィールドに名前と都市を入力してから、「Save」をクリックします。 | 
 |  | 
 |  | 
 | image::images/maven-crud_mavencrud-finished-app.png[title="「Customer」および「MyEditor」ウィンドウを表示する完成したアプリケーション"] | 
 |  | 
 | 保存機能に「Refresh」アクションを実装しなかった場合は、顧客を作成または変更したあとに、「Customer」ウィンドウのルートノードを再表示する必要があります。 | 
 |  | 
 | このチュートリアルでは、Maven を使用した NetBeans プラットフォームアプリケーションの作成方法が、Ant を使用した作成方法と大きく違わないことを示しました。主な違いは、Maven POM によるアプリケーション組み立ての制御方式です。ほかの NetBeans プラットフォームアプリケーションおよびモジュール構築の例については、「 link:https://netbeans.apache.org/kb/docs/platform.html[NetBeans プラットフォームの学習]」に一覧表示されている各チュートリアルを参照してください。 | 
 |  | 
 |  | 
 | == 関連項目 | 
 |  | 
 | これで、CRUD チュートリアルを終了します。このドキュメントは、Maven 構築フレームワークを使用して、CRUD 機能を備えた新しい NetBeans プラットフォームアプリケーションを作成する方法について説明しました。アプリケーションの作成と開発の詳細については、次のリソースを参照してください。 | 
 |  | 
 | *  link:https://netbeans.apache.org/kb/docs/platform_ja.html[NetBeans プラットフォームの学習] | 
 | *  link:http://bits.netbeans.org/dev/javadoc/[NetBeans API Javadoc] | 
 |  | 
 | NetBeans プラットフォームに関して質問がある場合は、dev@platform.netbeans.org のメーリングリストに投稿していただくか、 link:https://mail-archives.apache.org/mod_mbox/netbeans-dev/[NetBeans プラットフォームメーリングリストのアーカイブ]を参照してください。 | 
 |  |