FeaturesPluginsDocs & SupportCommunityPartners

NetBeans IDE 5.0 FeedReader チュートリアル

ダウンロード先のリンク:

NetBeans IDE 5.0 FeedReader チュートリアルへようこそ。このチュートリアルで構築する FeedReader アプリケーションは Mozilla Firefox の Sage プラグインを参考にしてモデル化された、簡単な RSS/Atom フィードブラウザです。ブラウザで開くことができる個々のフィードエントリを表すサブノードを持つ、フィードのツリーを提供します。例として、PlanetNetBeans RSS フィードのフィードエントリを NetBeans IDE の内部ブラウザで開いた様子を示します。

 

目次

はじめに

アプリケーションの確認

アプリケーションの設定

FeedReader ウィンドウの作成

アプリケーションの動作確認

アプリケーションへのコードの追加

アプリケーションのブランディング

アプリケーションの配布

はじめに

FeedReader アプリケーションのコーディングを始める前に、NetBeans IDE のアプリケーション開発の分野でよく使われる用語を理解しておきましょう。その過程で、これから作成するアプリケーションの概要について理解し、学習内容を知り、必要な設定を行います。

頻出用語について

このチュートリアルは、NetBeans に組み込まれているインフラストラクチャーの基本概念を理解していることが前提です。理解すべきことはそれほど多くはありません。次に、知っておくべき頻出用語を示します。

  • NetBeans Platform。 ほとんどのデスクトップアプリケーションで必要とされる最小限のものを提供するアプリケーションフレームワークです。NetBeans Platform には、標準のメニュー、ツールバー、ドキュメント管理、および設定など、アプリケーションで一般的に必要とされるものが、すぐに使える状態で用意されています。「NetBeans 上」にアプリケーションを構築することは、アプリケーションを一から書き起こすのではなく、NetBeans Platform にあらかじめ用意されていないアプリケーション部品だけを作成することを意味します。また、NetBeans Platform の必要でない部分は除外できます。開発サイクルの最後に、アプリケーションに NetBeans Platform をバンドルしますが、このとき自作の実行ファイルやスプラッシュ画面も一緒にバンドルします。そうすることで多くの時間と労力を節約し、堅牢で信頼できるアプリケーションになります。
  • システムファイルシステム。 NetBeans の構成情報を含み、登録済みモジュールの layer.xml 構成ファイルから構築される汎用レジストリです。NetBeans は、広範囲の各種構成情報を システムファイルシステムに格納します。たとえばシステムファイルシステムには Menu というフォルダがあり、このフォルダには、File および Edit などの名前を持つサブフォルダが含まれています。これらのサブフォルダには、IDE の「ファイル」および「編集」メニューに表示されるアクションを実装している Java クラスを表すファイルが含まれています。
  • プラグインモジュール。 アプリケーションに特定の機能を提供する Java クラスのグループです。たとえば、このチュートリアルで構築するプラグインモジュール内の Java クラスによって、RSS/Atom フィードリーダーの機能が提供されます。これらの Java クラスは、manifest.mf ファイルを使用してプラグインモジュールを宣言し、layer.xml 構成ファイルを使用してシステムファイルシステム内にその機能を登録します。

余談ですが、NetBeans の用語では、「プラグイン」は形容詞で「モジュール」は名詞です。両者の間に意味的な違いはありません。

  • NetBeasn API。 プラグインモジュールの作成者およびアプリケーションの作成者が利用できる、public インタフェースとクラスです。これら API は、対応する機能の違いに応じていくつかの API に分けられています。API リファレンスドキュメントで規定されているように、Java ソースパッケージとそのサブパッケージの内容および動作は API です。すべての NetBeans API の一覧については、こちらを参照してください。
  • モジュールスイート。 まとめて配備され、相互に依存するプラグインモジュールのグループです。IDE では、モジュールスイートのブランディングが行えます。たとえば、スプラッシュ画面を追加したり、アプリケーションで提供したくない NetBeans Platform の部分を指定したりできます。

FeedReader アプリケーションについて

FeedReader アプリケーションの作成には、NetBeans インフラストラクチャーを大いに利用します。最初に利用するのは、システムファイルシステムです。先ほど指摘したように、システムファイルシステムには、構成データが含まれています。これは、システム内にあるすべてのプラグインモジュールの構成ファイル (それぞれ「layer.xml」ファイルとしてディスクに格納されている) から構築され、これらのファイルをユーザーの設定ディレクトリに書き込みます。

システムファイルシステムは、ディスク上にあるユーザーのファイルの認識に使用されるのと同じインフラストラクチャーを使ってファイルの認識を行います。このことは、IDE の構成データの内部にあるフォルダの表示が、ディスク上のフォルダを表示するのと同じくらい簡単にできることを意味します。このように、ファイルやツリーの表示などには、NetBeans に組み込まれているすべての plumb 機能を使用できます。実際、IDE に見られる多くのビューには、これと同じ手法が使用されています。たとえば、「お気に入り」ウィンドウは、システムファイルシステム内のフォルダを表示するビューであり、このフォルダにはディスク上のファイルへのリンクが含まれています。また、「実行時」ウィンドウの内容もシステムファイルシステムのフォルダのビューであるため、プラグインモジュールはそこにノードを追加できます。ディスク上のファイル認識に用いられるのと同じ仕組みが使用されるため、フォルダ内部のオブジェクトには、どんなアイコンや表示名でも選択できます。

使用するほかの要素として、ノード API があります。ノード API は TreeNode を汎用的にしたものですが、ノードは、ツリー以外にもさまざまなビューアコンポーネントに表示できます。一般にノードは、DataObject を表します。基本的に DataObject は解析済みのファイル、すなわち、ファイルの内容やファイルが表すものの意味を認識し、それを使用してなんらかの処理を実行できる Java オブジェクトです。ノードは、アクションや各言語対応の表示名、アイコンなどの、ユーザーが対話する DataObject に機能を追加します。

そこで、ウィザードを使用して基本のテンプレートを生成したあとで、layer.xml ファイルを使用して、システムファイルシステム内に RSS フィードオブジェクト用のフォルダを作成します (RssFeeds フォルダの作成)。次に、生成したファイルの 1 つを基にして、IDE の「プロジェクト」ウィンドウまたは「ファイル」ウィンドウに類似した、フォルダのビューを構築します (フィードウィンドウの拡張)。このビューは、RSS フィードオブジェクト用のフォルダに基づきます。続いて、このフォルダを表す DataObject とそのノードを取得します。さらに、このノードを FilterNode にラップします (RssFeeds フォルダの作成)。FilterNode は、別のノードのラッパーとして動作するノードです。デフォルトでは、ほかのノードと同じように動作しますが、メソッドをオーバーライドして設定を変更することで、独自のアイコン、表示名、およびアクションを与えることができます。その後、FilterNode のそれぞれの子ノードもラップし、同じように設定を変更します。

次に、ルートノード上に「Add Feed」アクションを作成します。ユーザーが RSS フィードを追加したときに、次のような簡単な処理を行います。新しいフィードオブジェクト (実際は、その URL を含むただのオブジェクト。フィードオブジェクトの作成を参照) を作成し、このフィードオブジェクトを RSSFeeds フォルダのファイルとしてシリアライズします。ファイルの視覚化に NetBeans 組み込みインフラストラクチャーを使用しているので (ファイルの追加や削除を認識できる、フォルダの標準ノードを取得しているため)、新たに追加されたフィードのノードがユーザーインタフェースに即座に現れます。このように、システムファイルシステムを使用すると、終了時に RSS フィードの一覧を保存するためのコードを書く必要がなくなります。フィードをユーザーが作成した時に保存すれば、そのデータは自動的にディスクに保持されます。そのため、基本的には、Feed POJO をフォルダにドロップするだけで、そのフォルダのビューが表示されます。それ以外のことは、ほぼすべてシステムが処理します。

このチュートリアルについて

このチュートリアルでは、次のことが学べます。

  • NetBeans IDE 5.0 が提供するウィザードやその他の機能を使用した、NetBeans Platform 上でのアプリケーション作成。
  • NetBeans IDE 5.0 のウィザードを使用した、スケルトンウィンドウコンポーネントおよびスケルトンメニュー項目の作成。
  • NetBeans ノード API を使用した、フィードおよびフィードエントリのノード作成。
  • NetBeans のシステムファイルシステムへのアプリケーション登録。
  • 独自のスプラッシュ画面やタイトルバーなどを使用した、アプリケーションのブランディング。
  • 配布版アプリケーションの提供。

必要なソフトウェアのインストールが完了したら、このチュートリアルに要する時間は 60 分ほどです。

リソースについて

始める前に、コンピュータに次のリソースをインストールする必要があります。

アプリケーションの確認

アプリケーションを作成する前に、最終成果物について知りたいと思われるかもしれません。FeedReader アプリケーションは正式な NetBeans サンプルとして IDE にバンドルされているので、いつでも「新規プロジェクト」ウィザードから開くことができます。

アプリケーションのインストール

このサンプルをインストールするには、次の手順に従います。

  1. IDE を起動します。
  2. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択し、「サンプル」を展開して、「NetBeans プラグインモジュール」、「FeedReader」の順に選択します。「次へ」をクリックします。
  3. プロジェクトに好きな名前を付け、保存する場所を選択して、「完了」をクリックします。IDE で FeedReader サンプルが開きます。
  4. FeedReader Application」プロジェクトノードを右クリックし、「プロジェクトを実行」を選択します。アプリケーションが起動します。インストールの途中で、スプラッシュ画面が表示されます。

アプリケーションの紹介

FeedReader アプリケーションによって、「RSS/Atom フィード」というノードを含む「RSS/Atom フィード」ウィンドウが表示されます。

  1. 「RSS/Atom フィード」ノードを右クリックし、「追加」を選択して、RSS/Atom フィードに URL を入力します。たとえば、NetBeans.org の RSS フィード (http://www.netbeans.org/rss-091.xml) または PlanetNetBeans の RSS フィード (http://www.planetnetbeans.org/rss20.xml) を入力します。
  2. 「了解」をクリックします。フィード用のノードが追加されます。このノードの子はフィードエントリです。通常、フィードエントリは、フィードで提供する記事やトピックです。
  3. この操作を繰り返し、フィードをさらに追加します。
  4. フィードエントリをダブルクリックし、IDE のデフォルトブラウザで開きます。

このリッチクライアントアプリケーションによって、次のような機能も提供されます。

  • ノードを右クリックして「フォルダを追加」をクリックすると、新しいフォルダが作成されます。このフォルダはフィードの整理に使用できます。
  • フィードを右クリックして「削除」を選択すると、フィードが削除されます。
  • フィードエントリを右クリックして「開く」を選択すると、エディタ区画でフィードエントリが開きます。

ソースの紹介

この FeedReader サンプルは、メインファイル (Java クラス) および サポートファイルで構成されています。

メインファイル:

  • Feed.java
    URL および関連する Rome フィードをカプセル化します。
  • FeedAction.java
    「Open Feed Window」というラベルの付いたウィンドウメニューに現れるアクションを定義します。これにより、フィードウィンドウが開きます。
  • FeedTopComponent.java
    「Open Feed Window」というラベルの付いたウィンドウメニューに現れるアクションを定義します。これにより、フィードウィンドウが開きます。
  • RssNode.java
    RSS フィードフォルダおよびその子のノードクラスです。主に、実際の DataNode/DataFolder をシステムファイルシステム内の RssFeeds フォルダで代用します。これにより、削除機能や変更の待機など、多くの機能がもたらされます。そのため、新しいフィードオブジェクトを作成して、このフォルダ内にシリアライズするだけで、新しい RSS フィードを追加できます。

サポートファイル:

  • build.xml
    アプリケーションの構築や実行など、一般的な作業のための Ant ターゲットを提供します。
  • Bundle.properties
    地域対応のキーと値のペアです。
  • FeedTopComponentSettings.xml
    FeedReader アプリケーションのすべてのインタフェースを指定します。
  • FeedTopComponentWstcref.xml
    コンポーネントへの参照を指定します。
  • layer.xml
    システムファイルシステム内にフォルダおよびファイルを登録します。システムファイルシステムブラウザを使用してこのファイルを操作する方法を、あとで説明します。
  • project.xml
    モジュールの依存関係のようなプロジェクトメタデータを宣言します。「プロジェクトプロパティー」ダイアログを使用してこのファイルを操作する方法を、あとで説明します。
  • rss16.gif
    アプリケーションのメニュー項目によって、その「ヘルプ」>「製品について」ダイアログに表示されるアイコンです。
  • splash.gif
    スプラッシュ画面です。

アプリケーションの設定

NetBeans IDE では、アプリケーションの基盤として使用する多数のファイルを生成することから、NetBeans 上のアプリケーション構築が始まります。たとえば、NetBeans IDE は、NetBeans Platform 上に構築されるプラグインモジュールおよびアプリケーションで必要な基本ファイルをすべて設定する、「モジュールプロジェクト」ウィザード、「モジュールスイートプロジェクト」ウィザード、および「ライブラリラッパーモジュールプロジェクト」ウィザードを提供しています。

  • モジュールスイートプロジェクト。互いに依存関係を持つ一連のモジュールプロジェクトおよびライブラリラッパーモジュールプロジェクトをグループ化するプロジェクトで、グループ単位でまとめて配備を行うことができます。
  • ライブラリラッパーモジュールプロジェクト。ライブラリ JAR ファイルを自らのクラスパス上に置き、モジュールからライブラリ JAR ファイルのパッケージの一部または全部を公開パッケージとしてエクスポートするプロジェクトです。
  • モジュールプロジェクト。NetBeans Platform 上に構築されたプラグインモジュールまたはアプリケーションの機能、ビジネスロジック、およびユーザーインタフェースを実装するためのプロジェクトです。

モジュールスイートプロジェクトの作成

  1. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択します。「カテゴリ」で「NetBeans プラグインモジュール」を選択します。プロジェクトで「モジュールスイートプロジェクト」を選択します。「次へ」をクリックします。
  2. 「名前と場所」パネルで、「プロジェクト名」に「feedreader-suite」と入力します。「プロジェクトの場所」をコンピュータ上の任意のディレクトリに変更します (c:\mymodules など)。「完了」をクリックします。

IDE によって feedreader-suite プロジェクトが作成されます。このプロジェクトには、次で作成するモジュールプロジェクトおよびライブラリラッパーモジュールプロジェクトが含まれます。

IDE でプロジェクトが開きます。「プロジェクト」ウィンドウ (Ctrl-1) でプロジェクトの論理構造を、「ファイル」ウィンドウ (Ctrl-2) でそのファイル構造を見ることができます。

ライブラリのラップ

FeedReader アプリケーション全体を 1 つのプラグインモジュールとして統合することもできます。ただし、FeedReader アプリケーションは、Rome、Rome Fetcher、および JDom ライブラリを必要とします。

  • Rome。非常に簡単な API を使用して RSS および Atom の各フィードを読み取ります。
  • Rome Fetcher。HTTP 経由でのフィードの検索を可能にします。
  • JDom。XML 解析の API です。FeedReader は、Rome ライブラリで使用するためだけにこのライブラリを必要とします。

あとから FeedReader アプリケーションを拡張する場合、追加するモジュールでもこれらのライブラリを使用する可能性があります。追加するモジュールは、FeedReader 全体にではなく、ライブラリモジュールだけに依存させることをお勧めします。また、ライブラリモジュールは自動読み込みが可能です。これは、NetBeans が 必要なときにだけライブラリモジュールを読み込むことを意味します。それまでは、実行時にメモリーが占有されることはありません。

  1. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択します。「カテゴリ」で「NetBeans プラグインモジュール」を選択します。プロジェクトで「ライブラリラッパーモジュールプロジェクト」を選択します。「次へ」をクリックします。
  2. 「ライブラリの選択」パネルで、JDom をダウンロードしたフォルダに移動して、jdom.jar および LICENSE.txt を選択します。「次へ」をクリックします。
  3. 「名前と場所」パネルで、すべてのデフォルト値をそのまま使用します。ライブラリラッパーモジュールプロジェクトはモジュールスイートプロジェクト内に格納されます。別の場所に格納することもできますが、バージョン管理の目的上、モジュールスイートプロジェクト内に置くのが適切です。また、feedreader-suite モジュールスイートプロジェクトは「モジュールスイートに追加」ドロップダウンで選択されます。「次へ」をクリックします。
  4. 「基本モジュール構成」パネルで、すべてのデフォルト値をそのまま使用します。「完了」をクリックします。新しいライブラリラッパーモジュールプロジェクトが IDE で開かれ、「プロジェクト」ウィンドウに表示されます。
  5. Rome のライブラリラッパーモジュールプロジェクトを作成します。すべてのデフォルト値をそのまま使用します。
  6. Rome Fetcher のライブラリラッパーモジュールプロジェクトを作成します。

これで、JDom JAR ファイルを含むライブラリラッパーモジュールプロジェクトと、Rome および Rome Fetcher の各 JAR ファイルを含む別の 2 つのライブラリラッパーモジュールプロジェクトができました。

モジュールプロジェクトの作成

  1. 「ファイル」>「新規プロジェクト」(Ctrl-Shift-N) を選択します。「カテゴリ」で「NetBeans プラグインモジュール」を選択します。プロジェクトで「モジュールプロジェクト」を選択します。「次へ」をクリックします。
  2. 「名前と場所」パネルの「プロジェクト名」に「FeedReader」と入力します。すべてのデフォルト値をそのまま使用します。「次へ」をクリックします。
  3. 「基本モジュール構成」パネルで、「コード名ベース」の yourorgheremyorg に置き換えて、コード名ベースを org.myorg.feedreader. にします。地域対応のバンドルおよび XML レイヤーはそのままにしておきます。これらは org/myorg/feedreaderという名前のパッケージに格納されます。「完了」をクリックします。

IDE によって FeedReader プロジェクトが作成されます。このプロジェクトには、モジュールのソースと、プロジェクトの Ant 構築スクリプトなどのプロジェクトメタデータがすべて含まれます。IDE でこのプロジェクトが開きます。「プロジェクト」ウィンドウ (Ctrl-1) でプロジェクトの論理構造を、「ファイル」ウィンドウ (Ctrl-2) でそのファイル構造を見ることができます。「プロジェクト」ウィンドウには次のように表示されるはずです。

feedreader-suite プロジェクトノードを右クリックし、「プロパティー」を選択して、「プロジェクトプロパティー」ダイアログの「ソース」をクリックします。プロジェクトの作成中にモジュールスイートに追加されたモジュールが、パネルに表示されます。この「スイートモジュール」リストには、FeedReaderjdomrome、および rome-fetcherが表示されます。

FeedReader ウィンドウの作成

この節では、「ウィンドウコンポーネント」ウィザードを使用して、カスタムウィンドウコンポーネントを作成するファイルと、このコンポーネントを呼び出すアクションを作成するファイルを生成します。また、このウィザードは、アクションをメニュー項目として layer.xml 構成ファイルに登録し、ウィンドウ処理コンポーネントをシリアライズするためのエントリを追加します。この節のすぐあとで、「ウィンドウコンポーネント」ウィザードが生成するファイル動作を確認する方法を説明します。

  1. FeedReader プロジェクトノードを右クリックし、「新規」>「ファイル/フォルダ」を選択します。「カテゴリ」で「NetBeans モジュール開発」を選択します。「ファイルの種類」から「ウィンドウコンポーネント」を選択します。「次へ」をクリックします。
  2. 「基本設定」パネルで、ドロップダウンリストから explorer を選択し、「アプリケーションの起動時に開く」をクリックします。「次へ」をクリックします。
  3. 「名前と場所」パネルで「Feed as the Class Name Prefix」と入力し、rss16.gif を保存した場所に移動します。この GIF ファイルが、アクションを呼び出すメニュー項目に表示されます。
  4. 「完了」をクリックします。

IDE によって、次の新しいファイルが作成されます。

  • FeedAction.java。 「Open Feed Window」というラベルと rss16.gif 画像を使用して、「ウィンドウ」メニューに表示するアクションを定義します。フィードウィンドウを開きます。
  • FeedTopComponent.java。 フィードウィンドウを定義します。
  • FeedTopComponentSettings.xml。 org.myorg.feedreader リッチクライアントアプリケーションのすべてのインタフェースを指定します。それぞれインスタンス化することなく、インスタンスの簡単な検索を可能にします。クラスの読み込みやオブジェクト作成の必要をなくして、結果としてパフォーマンスを向上させます。layer.xml ファイルの Windows2/Components フォルダに登録されます。
  • FeedTopComponentWstcref.xml。 コンポーネントへの参照を指定します。コンポーネントを、複数のモードに属すことができるようにします。layer.xml ファイルの Windows2/Modes フォルダに登録されます。

IDE によって、次の既存ファイルが変更されます。

  • project.xml。 2 つのモジュール、ユーティリティ API (Javadoc を参照するにはここをクリック) および ウィンドウシステム API (Javadoc を参照するにはここをクリック) の依存関係が追加されています。
  • Bundle.properties。 次の 3 つのキーと値のペアが追加されています。

    CTL_FeedAction。
    FeedAction.java に定義されたメニュー項目のラベルをローカライズします。
    CTL_FeedTopComponent。
    FeedTopComponent.java のラベルをローカライズします。
    HINT_FeedTopComponent。 FeedTopComponent.java のツールチップをローカライズします。

  • 最後に、3 つの登録エントリが次のように layer.xml ファイルに追加されています。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN"
          "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<filesystem>
  <folder name="Actions">
      <folder name="Window">
          <file name="org-myorg-feedreader-FeedAction.instance"/>
      </folder>
  </folder>
  <folder name="Menu">
      <folder name="Window">
          <file name="FeedAction.shadow">
                <attr name="originalFile" stringvalue="Actions/Window/org-myorg-feedreader-FeedAction.instance"/>
          </file>
      </folder>
  </folder>
  <folder name="Windows2">
      <folder name="Components">
          <file name="FeedTopComponent.settings" url="FeedTopComponentSettings.xml"/>
      </folder>
      <folder name="Modes">
          <folder name="explorer">
              <file name="FeedTopComponent.wstcref" url="FeedTopComponentWstcref.xml"/
          </folder>
      </folder>
  </folder>
</filesystem>

layer.xml ファイル内のエントリは、次のように動作します。

  • <Actions>
    アクションを「Window」フォルダのアクションとして登録します。
  • <Menu>
    アクションを「「Window」メニュー」のメニュー項目として登録します。
  • <Windows2>
    FeedTopComponentSettings.xml を登録します。このファイルは、ウィンドウコンポーネントの検索に使用されます。コンポーネント参照ファイル、FeedTopComponentWstcref.xml を「editor」ウィンドウに登録します。別のウィンドウ内のコンポーネントを合体させるために、「explorer」を次に示す値の 1 つに手作業で変更できます。

    commonpalette|
    editor
    properties
    leftSlidingSide
    rightSlidingSide\
    bottomSlidingSide
    navigator
    debugger
    output

アプリケーションの動作確認

コードを入力することなく、この段階でアプリケーションの動作確認を行うことができます。ここでの動作確認とは、NetBeans IDE のインストール環境の別のインスタンスにアプリケーションを配備して、空のフィードウィンドウが正しく表示されるかどうかを確認することです。

NetBeans IDE は、Ant 構築スクリプトを使用して、アプリケーションの構築とインストールを行います。構築スクリプトは、モジュールプロジェクトの作成時に作成されたものです。

  1. 「プロジェクト」ウィンドウで feedreader-suite プロジェクトを右クリックし、「実行」を選択します。NetBeans IDE のインストール環境の別のインスタンス内で、アプリケーションの構築とインストールが行われます。IDE によって、新しいフィードウィンドウが開かれ、表示されます。
  2. IDE の「ウィンドウ」メニューに、新しいメニュー項目が表示されます。
  3. このウィンドウのラベル上にポインタを置きます。ヒントが表示されます。
  4. フィードウィンドウのラベルの右側にある小さな×印をクリックします。ウィンドウが閉じます。
  5. このウィンドウをふたたび開くには、「ウィンドウ」>「Open Feed Window」を選択します。
  6. IDE を終了するには、メインメニューから「ファイル」>「終了」を選択します。

アプリケーションへのコードの追加

アプリケーションの基本的な部分はできあがったので、次に独自のコードを追加してみましょう。その前に、アプリケーションの依存関係を指定する必要があります。そのあとで、「新規ファイル」ウィザードとソースエディタを使用して、ソースの紹介の項で説明した主クラスの作成とコーディングを行います。

アプリケーションの依存関係の指定

NetBeans API に属するいくつかのクラスをサブクラス化する必要があります。それぞれのクラスを依存関係として宣言する必要があります。このためには「プロジェクトプロパティー」ダイアログを使用します。

  1. 「プロジェクト」ウィンドウで FeedReader プロジェクトを右クリックし、「プロパティー」を選択します。「プロジェクトプロパティー」ダイアログで「ライブラリ」をクリックします。一部の API は、すでに「モジュールの依存関係」として宣言されています。この宣言は、「ウィンドウコンポーネント」ウィザードによって行われたものです。
  2. 「ライブラリ」パネルの一番上にある「追加...」をクリックします。
  3. 次の API を追加します。

    アクション API
    データシステム API
    ダイアログ API
    エクスプローラとプロパティーシート API
    ファイルシステム API
    ノード API
    rome
    rome-fetcher

  4. 「了解」をクリックして、「プロジェクトプロパティー」ダイアログを終了します。
  5. 必要に応じて、「プロジェクト」ウィンドウで IDE の FeedReader モジュールプロジェクトを展開してから「重要なファイル」ノードを展開し、「プロジェクトメタデータ」をダブルクリックして IDE で開きます。選択した API は、依存関係として宣言されています。
  6. 次に、JDom に対する Rome の依存関係を作成する必要があります。「プロジェクト」ウィンドウで Rome ライブラリラッパーモジュールプロジェクトを右クリックし、「プロパティー」を選択します。「プロジェクトプロパティー」ダイアログで「ライブラリ」をクリックし、「モジュールの依存関係」リストの隣にある「追加」をクリックします。JDom を追加します。「了解」をクリックして、「プロジェクトプロパティー」ダイアログを終了します。
  7. 最後に、Rome Fetcher は Rome と JDom の両方に依存しているので、Rome に対する Rome Fetcher の依存関係を作成する必要があります。Rome はすでに JDom に依存しているため、JDom に対する Rome Fetcher の依存関係を作成する必要はありません。
  8. 必要に応じて、「プロジェクト」ウィンドウで IDE の Rome モジュール、「重要なファイル」ノードを順に展開し、「プロジェクトメタデータ」をダブルクリックして IDE で開きます。Rome JAR ファイルがクラスパス上にあること、JDom がモジュール依存関係であること、それらのパッケージが公開されていることを確認します。Rome Fetcher のプロジェクトメタデータファイル内が同様であることを確認します。

RssFeeds フォルダの作成

システムファイルシステムブラウザを使用して、RSS フィードオブジェクトのフォルダを追加します。このあとで FeedTopComponent.java にコードを追加します。このファイルは、フォルダの内容を表示するために、「ウィンドウコンポーネント」ウィザードによって作成されたものです。

  1. 「プロジェクト」ウィンドウで、FeedReader プロジェクトノード、「重要なファイル」ノード、「XML レイヤー」ノードの順に展開します。システムファイルシステムブラウザが開きます。次のノードが表示されています。

    <このレイヤー>。
    現在のプラグインモジュールによって提供されているフォルダです。
    <コンテキスト内のこのレイヤー>。 システムファイルシステム内にある利用可能なすべてのフォルダです。

  2. <このレイヤー> ノードを右クリックし、「新規」>「フォルダ」を選択します。
  3. 「新規フォルダ」ダイアログに「RssFeeds」と入力します。「了解」をクリックします。layer.xml ファイルのノードをダブルクリックして、ソースエディタで開きます。次のエントリが追加されています。

    <folder name="RssFeeds"/>

フィードオブジェクトの作成

次に、URL とそれに関連づけられた Rome フィードをカプセル化する簡単な POJO を作成します。

  1. FeedReader プロジェクトノードを右クリックし、「新規」>「ファイル/フォルダ」を選択してから、「Java クラス」カテゴリ内の「Java クラス」をファイルの種類として選択します。「次へ」をクリックします。
  2. Feed クラスを指定し、「パッケージ」ドロップダウンで org.myorg.feedreader を選択します。「完了」をクリックします。
  3. ソースエディタで、デフォルトの Feed クラスを次のように書き換えます。
public class Feed implements Serializable {
	private static FeedFetcher s_feedFetcher = new HttpURLFeedFetcher( HashMapFeedInfoCache.getInstance());
	private transient SyndFeed m_syndFeed;
	private URL m_url;
	private String m_name;

	protected Feed() {
	}

	public Feed(String str) throws MalformedURLException
	{
		m_url = new URL(str);
		m_name = str;
	}
		
	public URL getURL()
	{
		return m_url;
	}
		
	public SyndFeed getSyndFeed() throws IOException {
		if (m_syndFeed == null) {
			try {
				m_syndFeed = s_feedFetcher.retrieveFeed(m_url);
				if (m_syndFeed.getTitle() != null)
					m_name = m_syndFeed.getTitle();
			} catch(Exception ex) {
				throw new IOException(ex.getMessage());
			}
		}
		return m_syndFeed;
	}

	public String toString(){
		return m_name;
	}

}

コードの多くに下線が引かれているのは、それらのパッケージが宣言されていないためです。次の手順でこれを行います。

このファイルを再フォーマットして依存関係を宣言するには、次の手順に従います。

  1. Ctrl-Shift-F キーを押し、コードをフォーマットします。
  2. Alt-Shift-F キーを押し、java.net.URL を選択して、「了解」をクリックします。IDE によって、パッケージ文の下に次のインポート文が追加されます。

    import com.sun.syndication.feed.synd.SyndFeed;
    import com.sun.syndication.fetcher.FeedFetcher;
    import com.sun.syndication.fetcher.impl.HashMapFeedInfoCache;
    import com.sun.syndication.fetcher.impl.HttpURLFeedFetcher;
    import java.io.IOException;
    import java.io.Serializable;
    import java.net.MalformedURLException;
    import java.net.URL;

これで、赤い下線がすべて消えます。そうならない場合、チュートリアルを続行する前に、この問題を解決してください。

フィードウィンドウの拡張

  1. FeedTopComponent.java をダブルクリックして、ソースエディタで開きます。
  2. クラス宣言の最後に「implements ExplorerManager.Provider」と入力します。
  3. その行で Alt-Enter キーを押し、提案の上をクリックします。IDE によって、必須のパッケージ org.openide.explorer.ExplorerManager のためのインポート文が追加されます。
  4. もう一度 Alt-Enter キーを押し、提案の上をクリックします。IDE によって、抽象メソッド getExplorerManager() が実装されます。
  5. 新しい getExplorerManager() メソッドの本体に「return manager;」と入力します。その行で Alt-Enter キーを押すと、IDE によって manager というフィールドが作成されます。デフォルトの定義を次のものに置き換えます。

    private final ExplorerManager manager = new ExplorerManager();

  6. 以前の手順で行なったフィールドの宣言のすぐ下に、次の宣言を追加します。

    private final BeanTreeView view = new BeanTreeView();

  7. 最後に、コンストラクタの最後に次のコードを追加します。
setLayout(new BorderLayout());
add(view, BorderLayout.CENTER);
view.setRootVisible(true);
try {
	manager.setRootContext(new RssNode.RootRssNode());
} catch (DataObjectNotFoundException ex) {
	ErrorManager.getDefault().notify(ex);
}
ActionMap map = getActionMap();
map.put("delete", ExplorerUtils.actionDelete(manager, true));
associateLookup(ExplorerUtils.createLookup(manager, map));

コードの多くには下線が引かれているのは、関連付けられているパッケージが宣言されていないためです。次の手順でこれを行います。

このファイルを再フォーマットして依存関係を宣言するには、次の手順に従います。

  1. Ctrl-Shift-F キーを押し、コードをフォーマットします。
  2. Alt-Shift-F キーを押し、org.openide.ErrorManager を選択して、「了解」をクリックします。IDE によって、パッケージ文の下にいくつかのインポート文が追加されます。インポート文の全リストは、次のようになります。

    import java.awt.BorderLayout;
    import java.io.Serializable;
    import javax.swing.ActionMap;
    import org.openide.ErrorManager;
    import org.openide.explorer.ExplorerManager;
    import org.openide.explorer.ExplorerUtils;
    import org.openide.explorer.view.BeanTreeView;
    import org.openide.loaders.DataObjectNotFoundException;
    import org.openide.util.NbBundle;
    import org.openide.util.RequestProcessor;
    import org.openide.util.Utilities;
    import org.openide.windows.TopComponent;

  3. manager.setRootContext(new RssNode.RootRssNode()); の行にはまだ赤い下線が引かれていますが、これは、RssNode.java が作成されていないためです。この作成は、次で行います。ほかの赤い下線はすべて消えているはずです。そうならない場合、チュートリアルを続行する前に、この問題を解決してください。

RssNode クラスの作成

  1. org.myorg.feedreader パッケージ内に RssNode.java を作成します。
  2. デフォルトのクラスを次のコードで置き換えます。
class RssNode extends FilterNode {

	/** ルート RSS ノードの子を宣言 */
	public RssNode(Node folderNode) throws DataObjectNotFoundException { 
		super(folderNode, new RssFolderChildren(folderNode));
	}
	/** 「Add Feed」アクションと「Add Folder」アクションを宣言 */
	public Action[] getActions(boolean popup) {
		DataFolder df = (DataFolder)getLookup().lookup(DataFolder.class);
		return new Action[] { new AddRssAction(df),
			new AddFolderAction(df) };
	}

	/** ルートノードを取得 */ 
	public static class RootRssNode extends RssNode {
		public RootRssNode() throws DataObjectNotFoundException {
			super(DataObject.find(
				Repository.getDefault().getDefaultFileSystem()
				.getRoot().getFileObject("RssFeeds")).getNodeDelegate());
		}
		public String getDisplayName() {
			return NbBundle.getMessage(RssNode.class, "FN_title");
		}
	}

	/** ルートノードの子を取得 */
	private static class RssFolderChildren extends FilterNode.Children {
		RssFolderChildren(Node rssFolderNode) {
			super(rssFolderNode);
		}
		protected Node[] createNodes(Object key) {
			Node n = (Node) key;
			try {
				if (n.getLookup().lookup(DataFolder.class) != null) {
					return new Node[] { new RssNode(n) };
				} else {
					Feed feed = getFeed(n);
					if (feed != null) {
						return new Node[] { new OneFeedNode(n, feed.getSyndFeed()) };
					} else {
						// ベストエフォート
						return new Node[] { new FilterNode(n) };
					}
				}
			} catch (IOException ioe) {
				ErrorManager.getDefault().notify(ioe);
			} catch (IntrospectionException exc) {
				ErrorManager.getDefault().notify(exc);
			}
			// その他の型のノード (なんらかの処理を行う必要あり)
			return new Node[] { new FilterNode(n) };
		}
	}

	/** フィードノードを取得して FilterNode 内にラップ */
	private static class OneFeedNode extends FilterNode {
		OneFeedNode(Node feedFileNode, SyndFeed feed) throws IOException, IntrospectionException {
			super(feedFileNode,
				new FeedChildren(feed),
				new ProxyLookup(new Lookup[] {
			Lookups.fixed(new Object[] { feed  }),
					feedFileNode.getLookup() }));
		}
		
		public String getDisplayName() {
			SyndFeed feed = (SyndFeed) getLookup().lookup(SyndFeed.class);
			return  feed.getTitle();
		}

		public Image getIcon(int type) {
			return Utilities.loadImage("org/myorg/feedreader/rss16.gif");
		}

		public Image getOpenedIcon(int type) {
			return getIcon(0);
		} 
		public Action[] getActions(boolean context) {
			return new Action[] { SystemAction.get(DeleteAction.class) };
		}
	}
	
	/** フィードノードの子を宣言 */
	private static class FeedChildren extends Children.Keys {
		private final SyndFeed feed;
		public FeedChildren(SyndFeed feed) {
			this.feed = feed;
		}
		
		protected void addNotify() {
			setKeys(feed.getEntries());
		}
		
		public Node[] createNodes(Object key) {
			try {
				return new Node[] { new EntryBeanNode((SyndEntry) key) };
			} catch (final IntrospectionException ex) {
				ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex);
				//決して発生しない - 上記の処理ができない理由はない
				return new Node[] { new AbstractNode(Children.LEAF) {
					public String getHtmlDisplayName() {
						return "<font color='red'>" + ex.getMessage() + "</font>";
					}
				}};
			}
		}
	}

	/** 子を FilterNode でラップ */
	private static class EntryBeanNode extends FilterNode {
		private SyndEntry entry;
		public EntryBeanNode(SyndEntry entry) throws IntrospectionException {
			super(new BeanNode(entry), Children.LEAF, Lookups.fixed(new Object[] { entry, new EntryOpenCookie(entry) }));
			this.entry = entry;
		}
		
		/** HtmlDisplayName の使用により、RSS エントリタイトル内の HTML が 
		/** 正しく処理され、エスケープされ、エンティティが解決されることなどを保証する */
		public String getHtmlDisplayName() {
			return entry.getTitle();
		}

		/** エントリの記述のツールチップを作成 */
		public String getShortDescription() {
			return entry.getDescription().getValue();
		}

		/** フィードエントリ上に Open アクションを用意 */
		public Action[] getActions(boolean popup) {
			return new Action[] { SystemAction.get(OpenAction.class) };
		}

		public Action getPreferredAction() {
			return (SystemAction) getActions(false) [0];
		}

      }
   
	/** ユーザーによる Open アクションの呼び出し時に何が起こるかを指定 */
	private static class EntryOpenCookie implements OpenCookie {
		private final SyndEntry entry;
		EntryOpenCookie(SyndEntry entry) {
			this.entry = entry;
		}

		public void open() {
			try {
				URLDisplayer.getDefault().showURL(new URL(entry.getUri()));
			} catch (MalformedURLException mue)       {
				ErrorManager.getDefault().notify(mue);
			}
		}
      }

	/** フィードを検索 */
	private static Feed getFeed(Node node) {
		InstanceCookie ck = (InstanceCookie) node.getCookie(InstanceCookie.class);
		if (ck == null) {
			throw new IllegalStateException("Bogus file in feeds folder: " + node.getLookup().lookup(FileObject.class));
		}
		try {
			return (Feed) ck.instanceCreate();
		} catch (ClassNotFoundException ex) {
			ErrorManager.getDefault().notify(ex);
		} catch (IOException ex) {
			ErrorManager.getDefault().notify(ex);
		}
		return null;
	}

	/** フィードをグループに分けて整理するためのフォルダを追加するアクションを作成 */
	private static class AddFolderAction extends AbstractAction {
		private DataFolder folder;
		public AddFolderAction(DataFolder df) {
			folder = df;
			putValue(Action.NAME, NbBundle.getMessage(RssNode.class, "FN_addfolderbutton"));
		}
		public void actionPerformed(ActionEvent ae) {
			NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine(
				NbBundle.getMessage(RssNode.class, "FN_askfolder_msg"), //NOI18N
				NbBundle.getMessage(RssNode.class, "FN_askfolder_title"), //NOI18N
				NotifyDescriptor.OK_CANCEL_OPTION,
				NotifyDescriptor.PLAIN_MESSAGE);
			Object result = DialogDisplayer.getDefault().notify(nd);
				if (result.equals(NotifyDescriptor.OK_OPTION)) {
					final String folderString = nd.getInputText();
					try {
						DataFolder.create(folder, folderString);
					} catch (IOException ex) {
						ErrorManager.getDefault().notify(ex);
					}
				}
		}
	}

	/** フィードを追加するアクションを作成 */
	private static class AddRssAction extends AbstractAction {
		private DataFolder folder;
		public AddRssAction(DataFolder df) {
			folder = df;
			putValue(Action.NAME, NbBundle.getMessage(RssNode.class, "FN_addbutton"));
		}
		public void actionPerformed(ActionEvent ae) {
			NotifyDescriptor.InputLine nd = new NotifyDescriptor.InputLine(
				NbBundle.getMessage(RssNode.class, "FN_askurl_msg"), //NOI18N
				NbBundle.getMessage(RssNode.class, "FN_askurl_title"), //NOI18N
				NotifyDescriptor.OK_CANCEL_OPTION,
				NotifyDescriptor.PLAIN_MESSAGE);
			Object result = DialogDisplayer.getDefault().notify(nd);
			if (result.equals(NotifyDescriptor.OK_OPTION)) {
				final String urlString = nd.getInputText();
				try {
					Feed f = new Feed(urlString);
					FileObject fld = folder.getPrimaryFile();
					String baseName = "RssFeed"; //NOI18N
					int ix = 1;
					while (fld.getFileObject(baseName + ix, "ser") != null) {
						ix++;
					}
					FileLock lock = null;
					try {
						FileObject writeTo = fld.createData(baseName + ix, "ser");
						lock = writeTo.lock();
						ObjectOutputStream str = new ObjectOutputStream(writeTo.getOutputStream(lock));
						str.writeObject(f);
					} catch (IOException ioe) {
						ErrorManager.getDefault().notify(ioe);
					} finally {
						if (lock != null)
							lock.releaseLock();
					}
				} catch (MalformedURLException ex) {
					IllegalArgumentException iae = new IllegalArgumentException(NbBundle.getMessage(RssNode.class,
						"FN_askurl_err", urlString), ex); //NOI18N
					throw iae;
				}
			}
		}
	}
}

コードの多くに下線が引かれているのは、それらのパッケージが宣言されていないためです。次の手順でこれを行います。このファイルを再フォーマットして依存関係を宣言するには、次の手順に従います。

  1. Ctrl-Shift-F キーを押し、コードをフォーマットします。
  2. Alt-Shift-F キーを押し、次のインポート文を選択します。

    org.openide.actions.OpenAction
    javax.swing.Action
    org.openide.nodes.Children
    org.openide.filesystems.FileLock
    java.awt.Image
    org.openide.nodes.Node
    org.openide.ErrorManager
    org.openide.util.Utilities
    java.net.URL
    org.openide.filesystems.Repository
    java.beans.IntrospectionException

  3. 「了解」をクリックすると、IDE によって多数のインポート文がパッケージ文の下に追加されます。これで、赤い下線がすべて消えたはずです。そうならない場合、チュートリアルを続行する前に、この問題を解決してください。

RssNode クラスのローカライズ

  1. FeedReader モジュールの Bundle.properties ファイルを開きます。
  2. 次のキーと値のペアを追加します。

    FN_title=RSS/Atom Feeds
    FN_addbutton=Add
    FN_askurl_title=New Feed
    FN_askurl_msg=Enter the URL of an RSS/Atom Feed
    FN_askurl_err=Invalid URL: {0}|
    FN_addfolderbutton=Add Folder
    FN_askfolder_msg=Enter the folder name
    FN_askfolder_title=New Folder

次に、この新しいキーと値のペアを説明します。このキーと値のペアによって、RssNode.java に定義された文字列がローカライズされます。

  • FN_title。 フィードウィンドウ内で最上位にあるノードのラベルをローカライズします。

次に、フィードを追加するユーザーインタフェースのローカライズについてを示します。

  • FN_addbutton。 最上位ノードのポップアップに現れる「追加」メニュー項目のラベルをローカライズします。
  • FN_askurl_title。 「New Feed」ダイアログのタイトルをローカライズします。
  • FN_askurl_msg。 「New Feed」ダイアログに現れるメッセージをローカライズします。
  • FN_askurl_err。 URL が無効な場合に表示されるエラー文字列をローカライズします。

次に、フォルダを追加するユーザーインタフェースのローカライズについて示します。

  • FN_addfolderbutton。 最上位ノードのポップアップに現れる「フォルダを追加」メニュー項目のラベルをローカライズします。
  • FN_askfolder_msg。 「フォルダを追加」ダイアログに現れるメッセージをローカライズします。
  • FN_askfolder_title。 「フォルダを追加」ダイアログのタイトルをローカライズします。

アプリケーションのブランディング

開発サイクルの最終段階で、アプリケーションを仕上げる間に、次のような疑問が生じます。

  • アプリケーションの実行可能ファイルの名前はどうすべきか。
  • アプリケーションの起動時、ユーザーに何を表示すべきか。進捗バーか、スプラッシュ画面か、またはその両方か。
  • アプリケーション起動時、タイトルバーには何を表示すべきか。
  • デフォルトで NetBeans Platform が提供するすべてのメニューおよびツールバーボタンが必要だろうか。

これらの疑問は、ブランディングに関係しています。これは、NetBeans Platform 上に構築されたアプリケーションを独自のものにするアクティビティーです。この IDE には、ブランディングを支援するパネルが、モジュールスイートプロジェクトの「プロジェクトプロパティー」ダイアログに用意されています。

  1. feedreader-suite プロジェクトノード (FeedReader プロジェクトノードではない) を右クリックし、「プロパティー」を選択します。「プロジェクトプロパティー」ダイアログで「アプリケーション」をクリックします。
  2. 「アプリケーション」パネルで「スタンドアロンアプリケーションを作成」をクリックします。IDE 関連のモジュールを除外するように促されます。FeedReader アプリケーションは、NetBeans IDE でソースエディタを提供するモジュールのような、IDE 関連のモジュールを必要としないので、「除外」をクリックします。
  3. 「ブランド名」フィールドに「feedreader」と入力します。「アプリケーションタイトル」フィールドに「Feed Reader Application」と入力します。ブランド名の値によって実行可能ファイルの名前が設定され、アプリケーションタイトルの値によってアプリケーションのタイトルバーが設定されます。
  4. 「ブラウズ」をクリックし、rss16.gif アイコンを探します。このアイコンは、「ヘルプ」>「製品について」ダイアログに表示されます。
  5. 「スプラッシュ画面」パネルで「ブラウズ」をクリックし、splash.gif を探します。必要に応じて、進捗バーの色およびテキストサイズを変更します。あるいは、進捗バーが必要ない場合は、「有効」を選択解除します。
  6. 「了解」をクリックします。
    FeedReader Application プロジェクトに branding フォルダが作成されます。このフォルダは、「ファイル」ウィンドウ (Ctrl-2) に表示されます。
  7. 「ファイル」ウィンドウで FeedReader Application プロジェクトノードを展開します。次のノードが見つかるまで、ノードの展開を続けます。
    branding/modules/org-netbeans-core-window.jar/org/netbeans/core/windows
  8. このノードを右クリックし、「新規」>「ファイル/フォルダ」を選択して、「その他」カテゴリから「フォルダ」を選択します。「次へ」をクリックし、フォルダ名として「resources」を入力します。「完了」をクリックします。
  9. 新しく作成された resources ノードを右クリックし、「新規」>「ファイル/フォルダ」を選択して、「XML」カテゴリから「XML ドキュメント」を選択します。「次へ」をクリックします。ファイル名として「layer」を入力します。「次へ」をクリックし、「完了」をクリックします。新しい layer.xml ファイルの内容を次のコードで置き換えます。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE filesystem PUBLIC "-//NetBeans//DTD Filesystem 1.1//EN" "http://www.netbeans.org/dtds/filesystem-1_1.dtd">
<!--
これは 「ブランディング」レイヤーです。ブランディング対象のレイヤーファイルとマージされます。
この場合、必要でないメニュー項目およびツールバーは非表示になります。
-->
<filesystem>

	<!-- 未使用のツールバーを非表示にする -->
	<folder name="Toolbars">
		<folder name="File_hidden"/>
		<folder name="Edit_hidden"/>
	</folder>

	<folder name="Menu">
		<folder name="File">
			<file name="org-openide-actions-SaveAction.instance_hidden"/>
			<file name="org-openide-actions-SaveAllAction.instance_hidden"/>
			<file name="org-netbeans-core-actions-RefreshAllFilesystemsAction.instance_hidden"/>            
			<file name="org-openide-actions-PageSetupAction.instance_hidden"/>
			<file name="org-openide-actions-PrintAction.instance_hidden"/>
		</folder>
		<folder name="Edit_hidden"/>
		<folder name="Tools_hidden"/>
	</folder>

</filesystem>

アプリケーションの配布

NetBeans IDE では、Ant 構築スクリプトを使用して、アプリケーションの配布版を作成します。構築スクリプトは、プロジェクトの作成時に作成されます。

  1. 「プロジェクト」ウィンドウで FeedReader Application プロジェクトノードを右クリックし、「配布用 ZIP を構築」を選択します。「出力」ウィンドウに、配布用 ZIP が作成される場所が表示されます。
  2. ファイルシステムにおいて、プロジェクトディレクトリの dist フォルダにある配布用の feedreader.zip を探します。そのファイルを展開します。bin フォルダにあるアプリケーションを起動します。起動中、スプラッシュ画面が表示されます。アプリケーションが起動したら、「ヘルプ」>「製品について」ダイアログに進み、アプリケーションのブランディング の節で指定したアイコンおよびスプラッシュ画面が表示されていることを確認します。

FeedReader アプリケーションの実行中は、「RSS/Atom フィード」というノードを含む「RSS/Atom フィード」ウィンドウが表示されます。詳細は、アプリケーションの確認を参照してください。

お疲れさまでした。以上で FeedReader チュートリアルは終了です。


Companion
Projects:
MySQL Database Server   Open JDK: an Open SourceJDK   GlassFish Community: an Open Source Application Server    Mobile & Embedded Community    Open Solaris   java.net - The Source for Java Technology Collaboration   Virtual Box - full virtualizer  Open ESB - The Open Enterprise Service Bus Powered by