Spring Roo 入門
第 3 回 Spring Roo のアドオンを開発する
コンテンツシリーズ
このコンテンツは全#シリーズのパート#です: Spring Roo 入門
このコンテンツはシリーズの一部分です:Spring Roo 入門
このシリーズの続きに乞うご期待。
はじめに
連載「Spring Roo 入門」では、第 1 回と第 2 回にわたり、Spring
Roo を使って一から本格的なエンタープライズ・アプリケーションを構築しました。この最初の 2 回の記事では、Spring Roo
のアプリケーション開発環境を使用して短時間で Web アプリケーションを構築する方法に焦点を当て、JPA、Selenium テスト、Spring Security、E メールの統合、Spring Roo のソーシャル機能、データベース・リバース・エンジニアリングなど、多数の機能を紹介しました。今回焦点を当てるのは、Spring Roo のアドオン・アーキテクチャーです。アドオン・アーキテクチャーの概要を説明した後、addon create
コマンドを使用して Spring Roo のアドオンを作成する方法を紹介します。この記事を読み終える頃には、Spring Roo のアドオンを素早く簡単に作成できるようになっているはずです。
Spring Roo のアドオン・アーキテクチャー
最も単純な形のアドオンは、特定の機能をソフトウェア・アプリケーションに追加するソフトウェア・コンポーネントです。例えば、ほとんどの Web ブラウザーでは、アドオンによって動画サポートを提供しています。また、Eclipse (多くの Java 開発者が実際に使用しているか、少なくとも知っているオープンソースの IDE) もその一例で、JUnit サポート、SVN サポートなど、その機能の多くはアドオンによって提供されています。ここではアドオンという言葉を、プラグインおよび拡張機能を総称する用語として使用しています。
Spring Roo でのアドオンの概念には、以下のものも含まれます。
- サード・パーティーの開発者が Spring Roo の機能を拡張できるようにするためのもの
- Spring Roo が新しい機能を追加しやすくするためのもの
- Spring Roo を小さな魔法使いにとどめておくためのもの (つまり、Spring Roo のサイズを抑えるということ)
Spring Roo の論理コンポーネント
Spring Roo は、2 つの論理部分に分けられます。
Spring Roo のコア・コンポーネント: アドオン開発を可能にするために、Spring Roo では、各種のアドオンをホストする実行環境を形成する一連のコア・コンポーネントを用意しています。用意されているコア・コンポーネントには、まずクラスパス (Classpath) があります。クラスパス (Classpath) はプロセス・マネージャー (Process manager) とシェル (Shell) をサポートします。プロセス・マネージャー (Process manager) はプロジェクト (Project) およびファイル操作取り消し (File undo) をサポートします。プロジェクト (Project) はモデル (Model)、メタデータ (Metadata)、およびファイル・モニター (File monitor) をサポートします。さらに、これらのコンポーネントのすべてが共通して使用するサポート (Support) コンポーネントがあります。図 1 に、以上のコア・コンポーネントの関係を図示します。
図 1. Spring Roo のコア・コンポーネント

以下に、上記の図に示されているコア・モジュールについて説明します。
- サポート (Support) —
org.springframework.roo.support
モジュールは、すべてのコア・モジュールおよびアドオンで共通して使用するユーティリティー・クラスを提供します。これらのユーティリティー・クラスには、Assert
、FileCopyUtils
、XmlUtils
、StringUtils
、FileUtils
などがあります。例えば、あるファイルの内容を別のファイルにコピーしたい場合には、FileCopyUtils
が自動的にコピーしてくれます。 - メタデータ (Metadata) — org.springframework.roo.metadata モジュールは、依存関係の登録およびキャッシングが組み込まれたメタデータ・サービス・プロバイダーのインターフェースおよび実装を提供します。
- ファイル・モニター (File monitor) — org.springframework.roo.file.monitor モジュールは、ファイルシステムの変更が検出されると、イベントをパブリッシュします (デフォルト実装では自動調整ディスク・ポーリングを使用します)。
- ファイル操作取り消し (File undo) — org.springframework.roo.file.undo モジュールは、プロセス・マネージャーが使用するファイル操作取り消し機能を提供します。
- プロジェクト (Project) — org.springframework.roo.project モジュールは、Apache Maven や Apache Ant などの一般的なエンド・ユーザー・プロジェクト・ビルド・システムを抽象化します。
- プロセス・マネージャー (Process manager) — org.springframework.roo.process.manager モジュールは、ACID のようなファイルシステム抽象化を提供します。この抽象化には、ディスク・ロールバックとプロセス同期が含まれます。
- クラスパス (Classpath) — org.springframework.roo.classpath モジュールは、Java および AspectJ コンパイル・ユニットの抽象構文ツリーの構文解析および型バインディングを実行します。
Spring Roo の基本アドオン: Spring Roo の機能はいずれもアドオンによって提供されます。Roo V1.1.3 に同梱されている基本アドオンを以下に記載します。
- アドオン・クリエーター — org.springframework.roo.addon.creator アドオンを使用すると、サード・パーティーは Roo アドオンを容易に作成できるようになります。
- バックアップ — org.springframework.roo.addon.backup アドオンを使用して「backup」と入力すると、ZIP ファイルの形でバックアップが作成されます。
- Cloud Foundry — org.springframework.roo.addon.cloud.foundry アドオンを使用すると、VMware Cloud Foundry がサポートされるようになります。
- 構成機能 — org.springframework.roo.addon.configurable アドオンを使用すると、AspectJ ITD による Spring の @Configurable アノテーションの導入がサポートされます。
- データベース・リバース・エンジニアリング — org.springframework.roo.addon.dbre アドオンを使用すると、既存のデータベースのインクリメンタル・リバース・エンジニアリングがサポートされます。
- データ・オンデマンド — org.springframework.roo.addon.dod アドオンを使用すると、結合テストで使用するサンプル・データの自動作成がサポートされます。
- E メール — org.springframework.roo.addon.email アドオンを使用すると、Spring の E メール・サポートをターゲット・プロジェクトに統合して構成できるようになります。
- エンティティー — org.springframework.roo.addon.entity アドオンを使用すると、Java Persistence API @Entity クラスの自動保守が広範にサポートされます。
- 動的ファインダー — org.springframework.roo.addon.finder を使用すると、コード補完対応のタイプ・セーフな JPA 問い合わせ言語ファインダーを作成できるようになります。
- Git — org.springframework.roo.addon.git アドオンを使用すると、プロジェクトにおける GIT の統合がサポートされます。これにより、コマンドが正常に完了するたびに、ローカル GIT リポジトリーに自動的にコミットされます。
- GWT — org.springframework.roo.addon.gwt アドオンを使用すると、Google Web Toolkit を使用した UI の scaffold 生成がサポートされます。
- JavaBean — org.springframework.roo.addon.javabean アドオンを使用すると、@RooJavaBean アノテーションが設定されたクラスの JavaBean ゲッター/セッターの自動保守が行えるようになります。
- JDBC — org.springframework.roo.addon.jdbc アドオンを使用すると、さまざまなバンドルに同梱された JDBC ドライバーに対する OSGi 準拠のアクセスをカプセル化することが可能になります (主に他のアドオンが使用)。
- JMS — org.springframework.roo.addon.jms アドオンを使用すると、ターゲット・プロジェクトにおける Java Messaging System 設定の構成がサポートされます。
- JPA — org.springframework.roo.addon.jpa アドオンを使用すると、指定された JPA プロバイダーのインストールと、そのプロバイダーに応じた JDBC のセットアップが可能になります。
- JSON — org.springframework.roo.addon.json アドオンを使用すると、JSON 関連のシリアライズおよびデシリアライズ・メソッドを POJO に追加できるようになります。
- ロギング — org.springframework.roo.addon.logging アドオンを使用すると、コマンドごとのログ・レベルの構成を含め、Log4j のセットアップが可能になります。
- 複数形変換 — org.springframework.roo.addon.plural アドオンを使用すると、名詞を複数形に変換できるようになります (主に他のアドオンが使用)。
- プロパティー・エディター — org.springframework.roo.addon.property.editor アドオンを使用すると、Spring MVC の必要に応じてプロパティー・エディターを管理できるようになります。
- プロパティー・ファイル — org.springframework.roo.addon.propfiles アドオンを使用すると、ターゲット・プロジェクトでのプロパティー・ファイルの管理がサポートされるようになります。
- RooBot クライアント — org.springframework.roo.addon.roobot.client アドオンを使用すると、RooBot サーバーを介したアドオン管理のサポートが提供されます。
- セキュリティー — org.springframework.roo.addon.security アドオンを使用すると、ログイン・ページ、フィルター、および依存関係を含め、Spring Security がセットアップされます。
- シリアライズ — org.springframework.roo.addon.plural アドオンを使用すると、要求された Java 型に対する java.io.Serializable サポート (UID 保守など) が追加されます。
- Solr — org.springframework.roo.addon.solr アドオンを使用すると、ターゲット・プロジェクトでの Apache Solr 機能の構成および統合がサポートされます。
- 結合テスト — org.springframework.roo.addon.test アドオンを使用すると、プロジェクト・エンティティーの JUnit 結合テストが生成できるようになります。
- ToString — org.springframework.roo.addon.tostring アドオンを使用すると、
@RooToString
アノテーション付きのあらゆるクラスに対し、有効なtoString()
メソッドを生成できるようになります。 - WebFlow — org.springframework.roo.addon.web.flow アドオンを使用すると、ターゲット・プロジェクトでの Spring Web Flow 機能の構成および統合をサポートできるようになります。
- Web MVC コントローラー — org.springframework.roo.addon.web.mvc.controller アドオンを使用すると、ターゲット・プロジェクトでの Spring MVC コントローラーの構成および統合がサポートされるようになります。
- Web MVC 組み込み — org.springframework.roo.addon.web.mvc.embedded アドオンを使用すると、MVC アドオンを拡張して、地図や動画などの組み込み機能を Web ページに追加できるようになります。
- Web MVC JSP — org.springframework.roo.addon.web.mvc.jsp アドオンを使用すると、ターゲット・プロジェクトで Spring MVC JSP 機能を構成および統合できるようになります。
- Selenium — org.springframework.roo.addon.web.selenium アドオンを使用すると、ターゲット・プロジェクトで Selenium Web テストを構成および統合できるようになります。
Spring Roo のコア・コンポーネントと付属の基本アドオンについて説明したところで、ここからは、独自のアドオンの作成に取り掛かります。
OSGi ランタイム環境
Spring Roo がベースとしているのは、Roo のアドオン・アーキテクチャーに最適な OSGi です。OSGi は、モジュール単位で組み込むサービス指向のアプリケーションを開発するには非常に優れたインフラストラクチャーとなります。
Roo シェルは、Apache Felix をその OSGi ランタイム・フレームワークとして使用し、コンポーネントの管理には SCR (Service Component
Runtime) を、バンドルの解決には OBR (OSGi Bundle Repository) を使用します。Roo シェルには、さまざまな OSGi
コマンドが用意されています。これらのコマンドは、「help osgi
」と入力すると一覧表示することができます (リスト 1 を参照)
リスト 1. OSGi に対する Roo の help コマンド
roo> help osgi * osgi find - Finds bundles by name * osgi framework command - Passes a command directly through to the Felix shell infrastructure * osgi headers - Display headers for a specific bundle * osgi install - Installs a bundle JAR from a given URL * osgi log - Displays the OSGi log information * osgi obr deploy - Deploys a specific OSGi Bundle Repository (OBR) bundle * osgi obr info - Displays information on a specific OSGi Bundle Repository (OBR) bundle * osgi obr list - Lists all available bundles from the OSGi Bundle Repository (OBR) system * osgi obr start - Starts a specific OSGi Bundle Repository (OBR) bundle * osgi obr url add - Adds a new OSGi Bundle Repository (OBR) repository file URL * osgi obr url list - Lists the currently-configured OSGi Bundle Repository (OBR) repository file URLs * osgi obr url refresh - Refreshes an existing OSGi Bundle Repository (OBR) repository file URL * osgi obr url remove - Removes an existing OSGi Bundle Repository (OBR) repository file URL * osgi ps - Displays OSGi bundle information * osgi resolve - Resolves a specific bundle ID * osgi scr config - Lists the current SCR configuration * osgi scr disable - Disables a specific SCR-defined component * osgi scr enable - Enables a specific SCR-defined component * osgi scr info - Lists information about a specific SCR-defined component * osgi scr list - Lists all SCR-defined components * osgi start - Starts a bundle JAR from a given URL * osgi uninstall - Uninstalls a specific bundle * osgi update - Updates a specific bundle * osgi version - Displays OSGi framework version
Spring Roo のアドオン作成コマンド
Spring Roo は、各種のアドオンを作成するためのアドオン作成コマンドがあらかじめバンドルされて提供されます。addon
create
コマンドを公開するアドオン・クリエーターも、Roo のアドオンの 1 つです。Roo では現在、以下の 4 つのタイプのアドオンをサポートしています。
- 国際化対応アドオン — Roo の scaffold で生成した Spring MVC アプリケーションに言語翻訳を追加できるようにします (例えば、ヒンディー語の翻訳を追加するなど)。
- シンプル・アドオン — シンプル・アドオンでは、プロジェクトの依存関係または構成、あるいはその両方に多少の変更を加えることができます (例えば、JAR や Maven プラグインを追加して maven pom.xml を変更するなど)。
- アドバンスド・アドオン — 力仕事を行うこのアドオンは、Java コードの作成が必要となる本格的な Spring Roo アドオンを作成する場合に使用します
(例えば、ドメイン・オブジェクトの
equals
およびhashcode
メソッドを作成可能なアドオンを作成するなど)。これらの機能を提供するアドオンは、すでにコミュニティー・アドオンにあります。 - ラッパー・アドオン — このアドオンは、OSGi 対応のバンドルを作成するために Maven 成果物をラップします。アドオンがその機能を完成するためには依存関係が必要となる場合には、このタイプのアドオンが必要です。例えば、Spring Roo のデータベース・リバース・エンジニアリング・アドオンがそのタスクを完了するには Postgres JDBC ドライバーが必要なため、このアドオンを使用して Postgres JDBC ドライバーをラップすることになります。
これらのアドオンは、以下の新しいアドオンを作成することによって、Roo アドオン開発を容易にするためのコマンドを作成します。
- Google Code での SVN ソース・コード管理と統合されたアドオン
- Google Code プロジェクトの一部として作成され、公開 Maven リポジトリーでホストされるアドオン
- RooBot に準拠したアドオン。RooBot は、VMware でホストされているサービスで、公開 Roo OBR ファイルの重要なコンテンツに索引を付けます。OBR ファイルは、バンドル・メタデータの XML ベースの表現です。RooBot に準拠するためのアドオンの要件には以下に挙げるものがあります。
- OSGi に準拠していること
- 公開鍵を持つ PGP 署名付き成果物であること
- httppgp:// プロトコルによって登録されていること
Roo の addon create
コマンドを使用すれば、以上のすべての要件を満たすアドオンが自動的に構成されます。したがって、アドオンを作成して外部に公開するまでにかかる時間が短縮されるというわけです。
アドオンの作成を始める前に、実際に機能する Spring Roo 環境が用意されていることを確認してください。Spring Roo のインストール手順は、この連載の第 1 回に記載されています。
ヒンディー語のサポートが必要な場合 (i18N アドオンの作成)
Spring Roo で Spring MVC ベースの Web アプリケーションを作成するときには、web mvc
language
コマンドを使って、各国語のサポートを追加することができます。Spring Roo であらかじめサポートされている言語は、英語、ドイツ語、スペイン語、イタリア語、オランダ語、スウェーデン語です。国際化に対応するための Web MVC JSP アドオンは、JSPX ファイルを webapp ディレクトリーに配置すると使用できるようになります。JSPX ファイルは、単純な JAR ベースのアプリケーションを Spring MVC Web アプリケーションに変換するコントローラー・コマンドによって生成されます。
インド人である私は、作成した Web アプリケーションにヒンディー語のサポートを追加することにしました。Spring Roo に用意されている addon create i18n
コマンドは、web mvc install language
コマンド
を拡張して、ヒンディー語などの新しい言語のサポートを追加します。このコマンドに必要なのは、目的の言語で翻訳された messages.properties ファイルのみです。
Spring Roo は Spring MVC Web アプリケーションを作成するときに、application.properties と messages.properties という 2 つのプロパティー・ファイルを作成します。application.properties ファイルにはアプリケーションに固有のプロパティー (アプリケーション名など) が格納されます。一方、messages.properties ファイルに格納されるプロパティーは特定のアプリケーションに固有のものではありません。例えば、削除ボタンをクリックすると表示される「Are you sure want to delete this item? (この項目を削除しますか?)」というようなメッセージや、ログイン、ログアウトなどの際に表示されるメッセージが、このファイルに格納されます。したがって、i18n アドオンを作成するには、messages.properties ファイルの翻訳バージョンが必要になるというわけです。
Spring Roo でのデフォルトの国際化対応について説明したので、これからヒンディー語のサポートを追加するための i18n アドオンを作成します。Google Code
にプロジェクトをセットアップする方法、コマンドを使用してアドオンを作成する方法、作成したアドオンを外部に公開してリリースする方法、そして最後にアドオンを RooBot
サービスに登録する方法を説明します。RooBot サービスへの登録は重要です。RooBot サービスに登録すると、RooBot がアドオンに索引を付けるため、他の開発者が addon search
コマンドで検索したときに、そのアドオンが表示されます。
プロジェクトのセットアップ
Spring Roo のドキュメントに、Google Code にプロジェクトと Maven リポジトリーをセットアップする方法が詳しく説明されているので、ここで説明を繰り返すことはしません。このプロジェクトの名前には「roo-hind-addon」を使用するとだけ言っておきます。
i18N アドオンを作成する
プロジェクトをセットアップした後には、roo-hindi-addon という名前の空のディレクトリーが作成されています。このディレクトリーに移動して、roo コマンド
を実行してください。シェルがアクティブになったら、「addon create
i18n
」と入力します。Tab キーを押すと、このコマンドが取る 7 つの属性が表示されます。このうち、必須の属性は、topLevelPackage
(新規アドオンの最上位レベルのパッケージ)、locale
(イタリア語を表す「it」など、ロケールの略語)、messageBundle
(message_xx.properties への完全修飾パス。ここで、xx はロケール名です) の 3
つです。残りの 4 つの属性はオプションで、language
は言語の完全な名称、flagGraphic
は xx.png ファイルへのフル・パス (ここで、xx はフラグの名前)、description
はアドオンの説明、projectName
はプロジェクトの名前 (指定しない場合は、最上位レベルのパッケージ名が使用されます) を指定します。projectName
属性は指定することをお勧めします。projectName
属性の値には、Google Code でホストされるプロジェクトの名前を設定してください。この例の場合、値には roo-hindi-addon を設定することになります。
上記の属性のうち、最も重要なのは、翻訳された messages.properties ファイルを指定する messageBundle
です。messages.properties をヒンディー語に翻訳するのに最も簡単な方法は、Google 翻訳などのサービスを利用して各プロパティーを
1 つずつ変換した後、messages_hi.properties に書き込むことですが、この例の場合には使用できません。その理由は、Java
プロパティー・ファイルが使用する ISO-8859-1 エンコード方式では、ヒンディー語の文字をサポートしていないからです。この問題を克服するために、私は Eclipse ResourceBundle Editor という Eclipse プラグインを使用しました。このプラグインを使えば、さまざまな言語用に翻訳したリソース・バンドルを作成することができます。Eclipse ResourceBundle Editor は、http://www.nightlabs.de/updatesites/development/ 更新サイトからインストールすることができます。messages.properties から messages_hi.properties ファイルへの変換については、この記事では取り上げません。ResourceBundle Editor プラグインは簡単に使用することができます。注意していただきたいことは、対象とする言語の文字がサポートされていたら、ResourceBundle Editor を使用する必要はなかったということです。リスト 2 に、messages_hi.properties ファイルの例を示します。
リスト 2. messages_hi.properties ファイルの例
button_cancel = \u0930\u0926\u094D\u0926 button_end = \u0905\u0902\u0924 button_find = \u0916\u094B\u091C\u0947\u0902 button_home = \u0918\u0930 ...
ファイル全体を見るには、ここをクリックしてください。翻訳済み messages_hi.properties ファイルの準備が完了すれば、後はたった 1 つのコマンドを入力するだけでアドオンを作成することができます。リスト 3 のコマンドを Roo シェルに入力すると、ヒンディー語のアドオンを作成することができます。
リスト 3. ヒンディー語のアドオンを作成するコマンド
addon create i18n --locale hi --topLevelPackage org.xebia.roo.addon.i18n.hindi --messageBundle <location to messages_hi.properties> \ --language hindi --projectName roo-hindi-addon --flagGraphic <full path to flag hi.png>
リスト 4 に、上記の addon create i18n
コマンドによる成果物を記載します。
リスト 4. 作成された成果物
Created ROOT/pom.xml Created ROOT/readme.txt Created ROOT/legal Created ROOT/legal/LICENSE.TXT Created SRC_MAIN_JAVA Created SRC_MAIN_RESOURCES Created SRC_TEST_JAVA Created SRC_TEST_RESOURCES Created SRC_MAIN_WEBAPP Created SRC_MAIN_RESOURCES/META-INF/spring Created ROOT/src/main/assembly Created ROOT/src/main/assembly/assembly.xml Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi/messages_hi.properties Created SRC_MAIN_RESOURCES/org/xebia/roo/addon/i18n/hindi/hi.png Created SRC_MAIN_JAVA/org/xebia/roo/addon/i18n/hindi Created SRC_MAIN_JAVA/org/xebia/roo/addon/i18n/hindi/HindiLanguage.java
上記のコマンドによって生成された Maven プロジェクトは、Eclipse にインポートすることも (m2eclipse を使用)、「File (ファイル)」 > 「Import (インポート)」 > 「Maven」 > 「Existing Maven projects (既存の Maven プロジェクト)」を順に選択することで SpringSource Tool Suite にインポートすることもできます。しかし、このプロジェクトの場合にはアドオンに変更を加える必要がないため、インポートする必要はありません。
今度は、完成したアドオンをインストールして、プロジェクトで使用し、外部に公開する作業に取り掛かります。けれどもその前に、生成されたコードをより深く理解できるように、成果物について説明しておきます。
- pom.xml — このファイルは、標準 Maven プロジェクト構成です。生成された pom.xml には各種の構成済みプラグインがあり、PGP を使用した成果物への署名付与、Maven リリース・プラグインを使用したアドオンのリリース、そして Maven バンドル・プラグインを使用したOSGi バンドルの作成に関連する作業を行えるようになっています。アドオンを Roo シェル内部で実行するために必要な OSGi および Felix 依存関係をプロジェクトに追加するのも、このファイルの役目です。
- assembly.xml — Maven アセンブリー・プラグインは、このファイルが定義する構成を使用して、アドオンをパッキングします。
- messages_hi.properties — このファイルは、アドオンの作成中に私たちが提供したメッセージ・バンドル・ファイルです。このファイルは、リソース・フォルダーにコピーされます。
- hi.png — このファイルは、アドオンの作成中に私たちが提供したフラグ PNG ファイルです。このファイルも、リソース・フォルダーにコピーされます。
- HindiLanguage.java — このファイルは、作成したアドオンによって作成された唯一の Java ファイルです。このファイルは、特定の言語に対応する情報を取得するために使用されます。例えば、ここにはロケール名、メッセージ・バンドル・リソース・ファイルなどが指定されます。
ヒンディー語のサポートをアプリケーションに追加する
ここからは、今までの説明で作成したアドオンを使用してアプリケーションにヒンディー語のサポートを追加する方法を説明します。
- Roo シェルを終了して、
mvn clean install
コマンドを実行します。ビルド・プロセスの実行中に、GPG パスフレーズの入力を求められます。 - Roo アドオンのビルドが完了したら、新しいコマンドラインを開き、i18n-hindi-client という名前のディレクトリーを作成します。ここに、アドオンの単純なクライアントを作成します。
- i18n-hindi-client ディレクトリーに移動して、
roo
コマンドを入力します。 - Roo シェルで以下のコマンドを実行します。これにより、単純な Spring MVC Web アプリケーションが作成されます。
リスト 5. MVC Web アプリケーションを作成する Roo コマンド
project --topLevelPackage com.shekhar.roo.i18n.client \ --projectName i18n-hindi-client persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY entity --class ~.domain.MyUser field string --fieldName name --notNull controller all --package ~.web
- コマンドとして「
web mvc language --code de en es it nl sv
」と入力し、Tab キーを押します。ヒンディー語サポートは表示されません。これは、ヒンディー語のアドオンをまだインストールしていないためです。
- アドオンをインストールするには、以下の内容を入力します。
osgi start --url file:///<location to addon target folder>/org.xebia.roo.addon.i18n.hindi-0.1.0.BUILD-SNAPSHOT.jar
上記のコードによって、Spring Roo ヒンディー語アドオンがインストールされてアクティブになります。アドオンのステータスは、
osgi ps
コマンドを使用して確認することができます。このコマンドを実行すると、以下のように OSGi バンドル情報とそのステータスが表示されます。[ 95] [Active ] [ 1] roo-hindi-addon (0.1.0.BUILD-SNAPSHOT)
- もう一度、「
web mvc language –code
」と入力して Tab キーを押します。今度は、ヒンディー語に対応するコードが表示されるはずです。「hi」コードを選択すると、ヒンディー語サポートがアプリケーションに追加されます。web mvc language –code hi
- Roo シェルを終了して、「
mvn tomcat:run
」と入力すると、フッターにインドの国旗が表示されます。この国旗をクリックすることで、アプリケーションはヒンディー語で表示されるようになります (図 2 を参照)。図 2. ヒンディー語のサポート
開発システムでアドオンが正常に機能していることをテストした後は、前に作成した Google Code プロジェクトにこのアドオンを送信してください。
内部での動作
作成したアドオンは正常に機能することがわかったところで、インディー言語がアプリケーションで使用できるようになった仕組みを調べてみましょう。
osgi start
コマンドによって、roo-hindi-addon が起動されました。- アドオンが起動すると、
addon create i18n コマンド
によって作成されたHindiLanguage
クラスが i18nComponent に登録されます。このコンポーネントは、i18n アドオンを登録および登録解除するための OSGi サービス・リスナーです。登録されたHindiLanguage
クラスは、Apache Felix で提供されている@Component
アノテーションと@Service
アノテーションでマーキングされます。この 2 つのアノテーションにより、コンポーネントとサービスが Roo シェルに登録されて使用可能な状態になります。 web mvc install language –code
コマンドを入力して Tab キーを押すと、Tab 補完サービスが i18nComponent クラスのgetSupportedLanguages()
メソッドを呼び出し、このメソッドによって i18n アドオンのjava.util.Set
が返されます。HindiLanguage
は i18nComponentに登録済みなので、このクラスも返されたというわけです。
アドオンを外部に公開する
アドオンを外部に公開するのは簡単です。なぜなら、Roo の create
コマンドが必要な Maven プラグインをすべてインストールして、作業の大部分を終わらせているからです。プロジェクトのルート・ディレクトリーに移動して、リスト 6 のコマンドを入力してください。
リスト 6. Roo プロジェクトを公開する
svn add pom.xml src/ legal/ readme.txt svn commit -m "Roo Hindi Addon first version" mvn release:prepare release:perform
Maven リリース・プラグインから、リリース・バージョン、タグ名、開発バージョンの入力を求められますが、単純にデフォルト設定を選択して先に進んでください。成果物が Google Code プロジェクトにリリースされて公開されるまでには数分かかります。この処理が完了すると、アドオンが Google Code プロジェクトに表示されます。
アドオンを RooBot に登録する
プラグインをリリースした後は、そのプラグインを s2-roobot@vmware.com に E メールで送信することで、アドオン・リポジトリーにプラグインを登録することができます。E メールの件名の行には、repository.xml ファイルが含まれていなければなりません。例えば、先ほど作成したアドオンの場合、repository.xml は http://code.google.com/p/roo-hindi-addon/source/browse/repo/repository.xml となります。RooBot への登録についての詳細は、Spring Roo のドキュメントを参照してください。
Java アプリケーションをモニターしたい場合 (シンプル・アドオンの作成)
アプリケーションのパフォーマンスのボトルネックを判別するために Java アプリケーションをモニターすることは、多くのエンタープライズ・アプリケーションに共通している要件です。私が作成したアプリケーションもその例外ではなかったため、この要件に対処するために利用できるオープンソースのソリューションを探すことにしました。Java Application Monitor (JAMon) は簡単に本番アプリケーションをモニターできる、無料でパフォーマンスに優れたスレッド・セーフの Java API です。
JAMon サポートを Web アプリケーションに追加するには、以下のことが必要です。
- jamon JAR を pom.xml に追加すること。
- アプリケーションのコンテキスト・ファイル内に
JamonPerformanceMonitorInterceptor
Bean を定義すること。リスト 7 に、この Bean 定義の一例を記載します。
リスト 7. JamonPerformanceMonitorInterceptor コード
<bean id="jamonPerformanceMonitorInterceptor" class=\ "org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"> <property name="trackAllInvocations" value="true"></property> <property name="useDynamicLogger" value="true"></property> </bean> <bean id="autoProxyCreator" class=\ "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <idref bean="jamonPerformanceMonitorInterceptor" /> </list> </property> <property name="beanNames"> <list> <value>speakerController</value> <value>talkController</value> </list> </property> </bean>
この Bean 定義は、どんな開発者でも簡単に記憶できるようなものではないので、この定型的な構成を自動化できるとしたら言うことありません。そこで私が思い立ったのは、JAMon 依存関係を追加して、インターセプター Bean を作成するというプロセスを自動化できるアドオンを作成することです。しかし、シンプル・アドオンとアドバンスド・アドオンのどちらが必要なのかは、どのように判断すればよいのでしょうか。
- Maven 依存関係または構成成果物、あるいはその両方をプロジェクトに追加する必要がある場合には、シンプル・アドオンを使用します。
- プロジェクトで既存の Java 型を拡張するか、新しい Java 型と AspectJ ITD を導入する必要がある場合、あるいはその両方を必要とする本格的なアドオンを作成する必要がある場合には、アドバンスド・アドオンを使用します。
JAMon サポートを追加するための要件は、jamon.jar をクラスパスに追加して、Bean 定義を格納するアプリケーション・コンテキスト・ファイルを作成することです。この場合、既存のコンテキスト・ファイルを使用するよりも、新しい Spring アプリケーション・コンテキスト・ファイルを作成するほうが、アプリケーション・コンテキストのモジュール化に役立つため、賢明と言えます。これらの要件を考えると、JAMon サポートを任意の Web アプリケーションに追加できるシンプル・アドオンを作成するべきであることは明らかです。
プロジェクトのセットアップ
今回のプロジェクトも、国際化対応アドオンのセットアップで行ったようにセットアップする必要があります。このプロジェクトは、「pring-roo-addon-jamon」と名付けます。
シンプル・アドオンを作成する
プロジェクトのセットアップが完了すると、.svn フォルダーだけが含まれる spring-roo-addon-jamon という名前のディレクトリーが作成されているはずです。spring-roo-addon-jamon ディレクトリーに移動して、Spring Roo シェルを起動したら、以下のコマンドを実行してください。
addon create simple --topLevelPackage org.xebia.roo.addon.jamon \ --projectName spring-roo-addon-jamon
アドオンを作成するために必要な作業は、たったこれだけです。
生成されたアドオンをインストールする
アドオンをインストールするには、以下のコマンドを使用します。
osgi start --url file://<Location to addon target folder>/org.xebia.roo.addon.jamon-0.1.0.BUILD-SNAPSHOT.jar
アドオンをインストールした後は、テストのために、i18n アドオン用に作成したような単純なクライアントを作成します。生成されたアドオンは、以下の 2 つのコマンドを提供します。
- 「
say hello
」。Roo シェルにウェルカム・メッセージを出力するコマンドです。このコマンドは常に使用できるので、Roo シェルを実行している間、いつでも入力することができます。 - 「
web mvc install tags
」。Web アプリケーションの scaffold によって生成されるデフォルトの MVC タグを置き換えるためのコマンドです。このコマンドは、Web アプリケーションを作成してからでないと使用することができません。
生成されたコードの内容
アドオンのテストが終わったところで、このアドオンによって生成されたファイルを調べてみましょう (リスト 8 を参照)。
リスト 8. spring-roo-addon-jamon 用に生成されたファイル
Created ROOT/pom.xml Created ROOT/readme.txt Created ROOT/legal Created ROOT/legal/LICENSE.TXT Created SRC_MAIN_JAVA Created SRC_MAIN_RESOURCES Created SRC_TEST_JAVA Created SRC_TEST_RESOURCES Created SRC_MAIN_WEBAPP Created SRC_MAIN_RESOURCES/META-INF/spring Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonCommands.java Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonOperations.java Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonOperationsImpl.java Created SRC_MAIN_JAVA/com/shekhar/roo/addon/jamon/JamonPropertyName.java Created ROOT/src/main/assembly Created ROOT/src/main/assembly/assembly.xml Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon/info.tagx Created SRC_MAIN_RESOURCES/com/shekhar/roo/addon/jamon/show.tagx
生成された pom.xml、assembly.xml、LICENSE.TXT、および readme.txt は、i18n アドオンで生成された成果物と同じです。これらのファイルについてはすでに説明したので、ここでもう一度繰り返すことはしません。今回注目すべき成果物は、JamonCommands、JamonOperations、JamonOperationsImpl、および JamonPropertyName です。シンプル・アドオン・コマンドによって生成されるコードを理解するために、これらのファイルについて個別に説明します。
- JamonCommands.java:JamonCommands — このクラスは、CommandMarker というマーカー・インターフェースを実装し、say hello と web mvc install tags という 2 つのコマンドを公開します (リスト 9 を参照)。
リスト 9. JamonCommands.java:JamonCommands から生成されたコード
@Component @Service public class JamonCommands implements CommandMarker { @Reference private JamonOperations operations; @Reference private StaticFieldConverter staticFieldConverter; protected void activate(ComponentContext context) { staticFieldConverter.add(JamonPropertyName.class); } protected void deactivate(ComponentContext context) { staticFieldConverter.remove(JamonPropertyName.class); } @CliAvailabilityIndicator("say hello") public boolean isSayHelloAvailable() { return true; } @CliCommand(value = "say hello", help = "Prints welcome message to the Roo shell") public void sayHello( @CliOption(key = "name", mandatory = true, help = "State your name") String name, @CliOption(key = "contryOfOrigin", mandatory = false, help = "Country of origin") JamonPropertyName country) { log.info("Welcome " + name + "!"); log.warning("Country of origin: " + (country == null ? \ JamonPropertyName.NOT_SPECIFIED.getPropertyName() : country.getPropertyName())); log.severe("It seems you are a running JDK " + operations.getProperty("java.version")); log.info("You can use the default JDK logger anywhere in your" + " add-on to send messages to the Roo shell"); } @CliAvailabilityIndicator("web mvc install tags") public boolean isInstallTagsCommandAvailable() { return operations.isInstallTagsCommandAvailable(); } @CliCommand(value = "web mvc install tags", help="Replace default Roo MVC tags used for scaffolding") public void installTags() { operations.installTags(); } }
コードが冗長にならないように、コード・ジェネレーターによって生成されたコメントはすべて削除しました。以下で、このクラスの重要なメンバーについて説明します。
- CommandMarker — すべてのコマンド・クラスに共通する要件は、CommandMarker インターフェースを実装し、
@Component
および@Service
アノテーションを付けることによって、それぞれのコマンド・クラスのコマンドを Roo シェルで使用可能にすることです。@Reference
アノテーションが付いたフィールドは、JamonCommands
クラスの依存関係で、Roo OSGi コンテナーによって注入されます。@Component
および@Service アノテーション
が付いたクラスはいずれも、他のアドオンに注入することができます。 - 起動および起動停止メソッド —
activate
メソッドとdeactivate
メソッドは、それぞれaddon install
コマンドでアドオンをインストールするとき、addon remove
コマンドでアドオンを削除するときに呼び出されるメソッドです。この 2 つのメソッドによってアドオンのライフサイクルに接続すると、Roo OSGi コンテナーによってそのライフサイクルが管理されます。 @CliAvailabilityIndicator
アノテーションが付けられたメソッド —@CliAvailabilityIndicator
アノテーションが付けられたメソッドは、コマンドが使用可能でないときに、そのコマンドを非表示にするためのメソッドです。例えば、Spring Security をプロジェクトにインストールするsecurity setup
コマンドは、プロジェクトが Web アプリケーションになるまでは表示されません。このようなメソッドを使用することは必須ではありませんが、ユーザーがその特定の時点で意味のないコマンドを起動できないようになるという点では役に立ちます。例えば、ユーザーが Web アプリケーションを使用できるようになる前に security setup コマンドを実行しても、何の意味もありません。@CliCommand
アノテーションが付けられたメソッド —@CliCommand
アノテーションが付けられたメソッドは、コマンドを Roo シェルに登録します。@CliCommand
には 2 つの属性があります。1 つはコマンド名を定義するvalue
、もう 1 つは、help
コマンドを入力すると表示されるヘルプ・メッセージを定義するhelp
です。すべてのコマンドは、コマンドの一部として示される@CliOption
アノテーションを使用して、必須属性とオプション属性を定義することができます。例えば、say hello
コマンドにはname
という必須属性と、country
というオプション属性があります。
- CommandMarker — すべてのコマンド・クラスに共通する要件は、CommandMarker インターフェースを実装し、
- JamonOperationsImpl.java —
コマンド・クラスは、コマンドの実行時に何らかの処理を行わなければなりません。これらの処理は、処理実行クラスによって行われます。
JamonOperationsImpl
は、依存関係を pom.xml に追加したり、リソースを目的の場所にコピーしたりするなどの実際の作業を引き受ける処理実行クラスです。JamonOperationsImpl
クラスはその処理を行うために、Spring Roo フレームワークが提供するコア・サービスを使用します。例えば、依存関係を追加する場合には、ProjectOperations
インターフェースを使用します。ファイルをコピーする場合には、FileManager
インターフェースを使用します。JamonOperationsImpl
クラスのコードを見ると、Roo アドオンをさらに深く理解することができます (リスト 10 を参照) 。リスト 10. JamonOpertionsImpl
@Component @Service public class JamonOperationsImpl implements JamonOperations { private static final char SEPARATOR = File.separatorChar; @Reference private FileManager fileManager; @Reference private ProjectOperations projectOperations; public boolean isInstallTagsCommandAvailable() { return projectOperations.isProjectAvailable() && fileManager.exists(projectOperations.getProjectMetadata(). getPathResolver().getIdentifier(Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR + "tags")); } public String getProperty(String propertyName) { Assert.hasText(propertyName, "Property name required"); return System.getProperty(propertyName); } public void installTags() { PathResolver pathResolver = projectOperations.getProjectMetadata().getPathResolver(); createOrReplaceFile(pathResolver.getIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR + "tags" + SEPARATOR + "util"), "info.tagx"); createOrReplaceFile(pathResolver.getIdentifier( Path.SRC_MAIN_WEBAPP, "WEB-INF" + SEPARATOR + "tags" + SEPARATOR + "form"), "show.tagx"); } private void createOrReplaceFile(String path, String fileName) { String targetFile = path + SEPARATOR + fileName; MutableFile mutableFile = fileManager.exists(targetFile) ? fileManager.updateFile(targetFile) : fileManager.createFile(targetFile); try { FileCopyUtils.copy(TemplateUtils.getTemplate(getClass(), fileName), mutableFile.getOutputStream()); } catch (IOException e) { throw new IllegalStateException(e); } } }
JamonOperationsImpl
クラスには、2 つの重要なメソッドが含まれています。それは、コマンドが使用可能であるかどうかをチェックするisInstallTagsCommandAvailable
メソッド、そしてターゲット・プロジェクトにタグをインストールするinstallTags
メソッドです。これらの処理を実行するために、JamonOperationsImpl
クラスは Spring Roo の以下のコア・サービスとユーティリティーを使用します。ProjectOperations: JamonOperationsImpl
クラスは、このProjectOperations
サービスを使用して、プロジェクトが使用可能であるかどうかをチェックし、tags フォルダーのパスを取得します。FileManager: JamonOperationsImpl
クラスは、このFileManager
サービスを使用して、ファイルが特定のパスに存在するかどうかをチェックし、ファイルの更新を取得するか、MutableFile
を新規に作成します。MutableFile
も Roo に固有のクラスで、変更可能なファイルへのハンドルを表します。TemplateUtils: TemplateUtils
ユーティリティー・クラスは、アドオン・バンドルに含まれるテンプレート・ファイル (info.tagx および show.tagx) へのInputStream
を獲得するために使用されます。FileCopyUtils: FileCopyUtils
ユーティリティー・クラスは、(TemplateUtils
の) テンプレートを (FileManager
の)MutableFile
にコピーするために使用されます。
要件を満たすようにアドオンを変更する
シンプル・アドオンに関する最初のセクションでは、このアドオンが任意の Spring MVC Web アプリケーションで JAMon を構成できるようにするために満たさなさなければならない 2 つの要件を説明しました。これらの要件は、以下のとおりです。
- JAMon JAR を pom.xml に追加すること。
- アプリケーションのコンテキスト・ファイル内に JamonPerformanceMonitorInterceptor Bean を定義すること
この 2 つの要件を満たすために、これから JamonCommands
クラスを以下のように変更して、jamon setup
コマンドがサポートされるようにします。その後、要件を満たすための実際の作業を行う、jamon setup
コマンドに対応する 1 つの処理を追加します。
JamonCommands
— JamonCommands
クラスには、2 つだけメソッドを持たせます。1 つは jamon
setup
コマンドが使用可能であるかどうかをチェックする isInstallJamon
、もう 1 つは、jamon setup
コマンドの起動に応じて JAMon をインストールする installJamon
です (リスト 11 を参照)。
リスト 11. JamonCommands のコード
@Component @Service public class JamonCommands implements CommandMarker { private Logger log = Logger.getLogger(getClass().getName()); @Reference private JamonOperations operations; @CliAvailabilityIndicator("jamon setup") public boolean isInstallJamon() { return operations.isInstallJamonAvailable(); } @CliCommand(value = "jamon setup", help = "Setup Jamon into your project") public void installJamon() { operations.installJamon(); } }
JamonCommands
クラスに必要なのは、これだけです。このコードは jamon setup
コマンドを公開するためにのみ必要なコードで、残りの作業はすべて JamonOperationsImpl
クラスに委ねられます (リスト 12 を参照)
リスト 12. JamonOperationsImpl のコード
JamonOperationsImpl JamonOperationsImpl need to implement two methods – \ isInstallJamonAvailable() and installJamon(). The isinstallJamonAvailable() method returns a boolean indicating whether command is available at this location or not. I want to enable JAMon only for the web applications so we need to perform the check whether the project is a web application or not. To do that we will write the code as shown below public boolean isInstallJamonAvailable() { return projectOperations.isProjectAvailable() && fileManager.exists(projectOperations.getPathResolver() .getIdentifier(Path.SRC_MAIN_WEBAPP, "/WEB-INF/web.xml")); }
リスト 12 に記載したコードでは、ProjectOperations
サービスを使用して、プロジェクトがこのロケーションで使用可能になっているかどうかをチェックし、web.xml ファイルのパスを取得します (web.xml ファイルは
Web アプリケーションにのみ存在します)。ProjectOperations
によって指定されたロケーションにweb.xml
が存在するかどうかをチェックするには、FileManager
サービスが使用されます。
実装しなければならない 2 つ目のメソッドは、installJamon()
です。このメソッドで、JAMon 依存関係を pom.xml に追加し、Bean 定義を webmvc-config.xml に追加しなければなりません。メソッドのコードを作成する前に、src/main/resources/org/xebia/roo/addon/jamon フォルダー内に configuration.xml という名前の XML ファイルを作成する必要があります。フォルダー構造 (org/xebia/roo/addon/jamon) は、Roo アドオンのパッケージ構造と同じです。configuration.xml は、リスト 13 に示す JAMon バージョンと JAMon JAR 依存関係を定義します。
リスト 13. configuration.xml の内容
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <configuration> <jamon> <properties> <jamon.version>2.4</jamon.version> </properties> <dependencies> <dependency> <groupId>com.jamonapi</groupId> <artifactId>jamon</artifactId> <version>${jamon.version}</version> </dependency> </dependencies> </jamon> </configuration>
次は、依存関係を pom.xml に追加するためのコードを作成します (リスト 14 を参照)。
リスト 14. pom.xml に依存関係を追加するためのコード
public void installJamon() { Element configuration = XmlUtils.getConfiguration(getClass()); updatePomProperties(configuration); updateDependencies(configuration); } private void updatePomProperties(Element configuration) { List<Element> properties = \ XmlUtils.findElements("/configuration/jamon/properties/*" , configuration); for (Element property : properties) { projectOperations.addProperty(new Property(property)); } } private void updateDependencies(Element configuration) { List<Dependency> dependencies = new ArrayList<Dependency>(); List<Element> jamonDependencies = XmlUtils.findElements( "/configuration/jamon/dependencies/dependency", configuration); for (Element dependencyElement : jamonDependencies) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies(dependencies); }
これは、pom.xml に依存関係を追加するための標準的なメカニズムであり、ほとんどの Roo アドオンでは、このメカニズムが使用されています。リスト 14
に記載したコードは、読めばその内容が明らかなように、Spring Roo ユーティリティー・クラス XmlUtils
を使用して configuration.xml の内容を読み取り、それから ProjectOperations
サービスを使用して pom.xml ファイルを更新します。
pom.xml 依存関係を追加した後は、web-jamon-config.xml という別の Spring 構成を作成する必要があります。ここに、JamonPerformanceMonitorInterceptor
の Bean 定義を含めます。
リスト 15. web-jamon-config.xml の内容
<?xml version="1.0" encoding="UTF-8" standalone="no"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" \ xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=\ "http://www.springframework.org/schema/beans \ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context \ http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc \ http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <bean id="jamonPerformanceMonitorInterceptor" class=\ "org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"> <property name="trackAllInvocations" value="true"></property> <property name="useDynamicLogger" value="true"></property> </bean> <bean id="autoProxyCreator" class=\ "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <idref bean="jamonPerformanceMonitorInterceptor" /> </list> </property> <property name="beanNames"> <list> <value></value> </list> </property> </bean> </beans>
リスト 15 に記載した web-jamon-config.xml ファイルには、Spring ベースのアプリケーションで JAMon に必要なあらゆるものを構成していますが、唯一指定していないのは、モニター対象とする Bean の名前です。コード・ジェネレーターがモニター対象の Bean を予測することはできないため、これを指定するのはアドオン開発者の仕事となります。
次に、この web-jamon-config.xml ファイルを webmvc-config.xml が常駐する WEB_INF/spring
フォルダーにコピーするためのコードを作成し、webmvc-config.xml 内に、web-jamon-config.xml をインポートするための add import
文のコードを作成します (リスト 16 を参照)。
リスト 16. pom.xml を操作するコード
public void installJamon() { // update pom.xml code PathResolver pathResolver =
projectOperations.getProjectMetadata().getPathResolver(); String resolvedSpringConfigPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP,
"/WEB-INF/spring"); if (fileManager.exists(resolvedSpringConfigPath + "/web-jamon-config.xml")) { return; } copyTemplate("web-jamon-config.xml", resolvedSpringConfigPath); String webMvcConfigPath = resolvedSpringConfigPath + "/webmvc-config.xml"; new XmlTemplate(fileManager).update(webMvcConfigPath, new DomElementCallback() { public boolean doWithElement(Document document, Element root) { if (null == XmlUtils.findFirstElement\ ("/beans/import[@resource='web-jamon-config.xml']", root)) { Element element = document.createElement("import"); element.setAttribute("resource", "web-jamon-config.xml"); root.appendChild(element); return true; } return false; } }); } private void copyTemplate(String templateFileName, String resolvedTargetDirectoryPath) { try { FileCopyUtils.copy(TemplateUtils.getTemplate(getClass(), templateFileName), fileManager.createFile( resolvedTargetDirectoryPath + "/" + templateFileName).getOutputStream()); } catch (IOException e) { throw new IllegalStateException( "Encountered an error during copying of resources for Jamon addon.", e); } }
上記で使用している XmlTemplate
クラスは、Spring Web フロー・アドオンにあります。したがって、この Web フロー・アドオンの依存関係をアドオンに追加しなければなりません (リスト 17 を参照)
リスト 17. Web フロー・アドオンの依存関係を追加する
<dependency> <groupId>org.springframework.roo</groupId> <artifactId>org.springframework.roo.addon.web.flow</artifactId> <version>${roo.version}</version> <type>bundle</type> </dependency>
リスト 17 に示されている roo.version
は、使用している Roo のバージョンです。
このアドオンで最後に必要な作業は、プロジェクトのロギングを構成して、トレースするログ・レベルを設定することです。それには、log4j
アドオンの処理実行クラス、LoggingOperations
を使用します。このクラスを使用するには、まず、pom.xml ファイルにロギング・アドオンの依存関係を追加する必要があります (リスト 18 を参照)。
リスト 18. ロギング・アドオンの依存関係を追加する XML コード
<dependency> <groupId>org.springframework.roo</groupId> <artifactId>org.springframework.roo.addon.logging</artifactId> <version>${roo.version}</version> <type>bundle</type> </dependency>
この依存関係を pom.xml に追加したら、以下のコード行を使用して LoggingOperation
を JamonOperationsImpl
クラスに追加します。
@Reference private LoggingOperations loggingOperations;
次に、以下の行を installJamon
メソッドに追加します。
loggingOperations.configureLogging(LogLevel.TRACE, LoggerPackage.PROJECT);
このアドオン用に作成しなければならないコードは、これですべてです。リスト 19 に、JamonOperationsImpl
クラスの完全なコードを記載します。
リスト 19. 完成した JamonOperationsImpl のコード
@Component @Service public class JamonOperationsImpl implements JamonOperations { @Reference private FileManager fileManager; @Reference private ProjectOperations projectOperations; @Reference private LoggingOperations loggingOperations; public boolean isInstallJamonAvailable() { return projectOperations.isProjectAvailable() && fileManager.exists(projectOperations.getPathResolver() .getIdentifier(Path.SRC_MAIN_WEBAPP,"/WEB-INF/web.xml")); } public void installJamon() { Element configuration = XmlUtils.getConfiguration(getClass()); updatePomProperties(configuration); updateDependencies(configuration); PathResolver pathResolver = projectOperations.getProjectMetadata().getPathResolver(); String resolvedSpringConfigPath = pathResolver.getIdentifier(Path.SRC_MAIN_WEBAPP, "/WEB-INF/spring"); if (fileManager.exists(resolvedSpringConfigPath + "/web-jamon-config.xml")) { return; } copyTemplate("web-jamon-config.xml", resolvedSpringConfigPath); String webMvcConfigPath = resolvedSpringConfigPath + "/webmvc-config.xml"; new XmlTemplate(fileManager).update(webMvcConfigPath, new DomElementCallback() { public boolean doWithElement(Document document, Element root) { if (null == XmlUtils.findFirstElement( "/beans/import[@resource='web-jamon-config.xml']", root)) { Element element = document.createElement("import"); element.setAttribute("resource", "web-jamon-config.xml"); root.appendChild(element); return true; } return false; } }); loggingOperations.configureLogging(LogLevel.TRACE, LoggerPackage.PROJECT); } private void copyTemplate(String templateFileName, String resolvedTargetDirectoryPath) { try { FileCopyUtils.copy( TemplateUtils.getTemplate(getClass(), templateFileName), fileManager.createFile(resolvedTargetDirectoryPath + "/" + templateFileName).getOutputStream()); } catch (IOException e) { throw new IllegalStateException( "Encountered an error during copying of resources for Jamon addon.", e); } } private void updatePomProperties(Element configuration) { List<Element> properties = XmlUtils .findElements("/configuration/jamon/properties/*",configuration); for (Element property : properties) { projectOperations.addProperty(new Property(property)); } } private void updateDependencies(Element configuration) { List<Dependency> dependencies = new ArrayList<Dependency>(); List<Element> jamonDependencies = XmlUtils.findElements( "/configuration/jamon/dependencies/dependency", configuration); for (Element dependencyElement : jamonDependencies) { dependencies.add(new Dependency(dependencyElement)); } projectOperations.addDependencies(dependencies); } }
このアドオンの完全なソース・コードは、Google Code リポジトリーからダウンロードすることができます。最後にいよいよ、作成したアドオンを使用してアプリケーションに JAMon サポートを追加します。
- Roo シェルを終了して、
mvn clean install
コマンドを実行します。ビルド・プロセスの実行中に、GPG パスフレーズの入力を求められます。 - Roo アドオンのビルドが完了したら、新しいコマンドラインを開き、jamon-client という名前のディレクトリーを作成します。ここに、アドオンの単純なクライアントを作成します。
- jamon-client ディレクトリーに移動し、
roo
コマンドを実行して Roo シェルを開きます。 - Roo シェルで、リスト 20 のコマンドを実行します。これにより、単純な Spring MVC Web アプリケーションが作成されます。
リスト 20. 単純な MVC Web アプリケーションの作成
project --topLevelPackage com.shekhar.roo.jamon.client --projectName jamon-client persistence setup --provider HIBERNATE --database HYPERSONIC_IN_MEMORY entity --class ~.domain.MyUser field string --fieldName name --notNull controller all --package ~.web
- 以下の内容を入力して、アドオンをインストールします。
osgi start --url <a href="../../../../">file:///</a><location \ to addon target folder > /org.xebia.roo.addon.jamon-0.1.0.BUILD-SNAPSHOT.jar
上記のコードによって、JAMon アドオンがインストールされて起動されます。アドオンのステータスを確認するには、
osgi ps
コマンドを使用します。 jamon setup
コマンドを入力すると、アプリケーションに構成された JAMon が表示されます。この時点でmvn tomcat:run
コマンドによってアプリケーションを実行しても、コンソールにログは表示されません。それは、モニター対象の Bean をまだ構成していないからです。そこで、リスト 21 のコードに従って、web-jamon-config.xml にmyUserController
Bean を構成してみましょう。リスト 21. web-jamon-config.xml での myUserController の構成
<bean id="autoProxyCreator" class=\ "org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames"> <list> <idref bean="jamonPerformanceMonitorInterceptor" /> </list> </property> <property name="beanNames"> <list> <value>myUserController</value> </list> </property> </bean>
mvn tomcat:run
コマンドを使用してアプリケーションを実行すると、今度は Maven コンソールに JAMon ログが表示されるはずです。その一例をリスト 22 に記載します。リスト 22. JAMon ログの例
TRACE MyUserController - JAMon performance statistics for method [MyUserController.populateMyUsers]: JAMon Label=MyUserController.populateMyUsers, Units=ms.: (LastValue=187.0, Hits=1.0, Avg=187.0, Total=187.0, Min=187.0, Max=187.0, Active=0.0, Avg Active=1.0, Max Active=1.0, First Access=Wed May 18 15:33:41 IST 2011, Last Access=Wed May 18 15:33:41 IST 2011)
開発システムでアドオンが正常に機能していることをテストした後は、前に作成した Google Code プロジェクトにこのアドオンを送信します。アドオンを外部に公開するには、i18n アドオンを公開したときの手順に従ってください。同じく、アドオンを RooBot に登録するための手順も、i18n を登録したときの手順と同じです。
まとめ
この記事では、Spring Roo アドオン・アーキテクチャーの概要と、国際化対応アドオンおよびシンプル・アドオンを作成する方法を説明しました。このアドオン・アーキテクチャーが Roo にとって重要な理由は、このアーキテクチャーがもたらす柔軟性によって、Roo では新しい機能を素早く追加できるようになっているためです。開発者にとっては、このアーキテクチャーは、機能が世界のさまざまな言語および文化で実装されるのを待たなくても、それぞれの要件を満たすことができる重要なアーキテクチャーです。また、後になって機能が Roo に組み込まれた場合でも、このアーキテクチャーのおかげで比較的簡単に実装を変更してカスタム・ソリューションを削除することができます。
連載「Spring Roo 入門」の第 4 回では、高度なラッパー・アドオンを作成する方法について説明します。
ダウンロード可能なリソース
関連トピック
- この連載の第 1 回と第 2 回を必ず読んでください。
- Spring Roo の資料を読んで、Spring Roo の機能について詳しく学んでください。
- Spring Roo コミュニティー・フォーラムではユーザーが互いに助け合えます。
- developerWorks podcasts ではソフトウェア開発者のための興味深いインタビューや議論を聞くことができます。
- Twitter で developerWorks をフォローしてください。
- オープンソース技術を使用して開発し、IBM の製品と併用するときに役立つ広範囲のハウツー情報、ツール、およびプロジェクト・アップデートについては、developerWorks Open source ゾーンを参照してください。
- IBM 製品の評価版をダウンロードするか、あるいは IBM SOA Sandbox のオンライン試用版で、DB2、Lotus、Rational、Tivoli、および WebSphere などが提供するアプリケーション開発ツールやミドルウェア製品を試してみてください。