Webサービス研究会での書籍管理アプリの製作に、 Mavenを使用し{ている|た}。 そのときの経験をベースに、 Mavenを利用してのプロジェクトの構成について、 特にEclipseとの連携を中心にまとめる。
Maven自体のインストールなどについては、 Maven自体のドキュメントや、 ここや ここが参考になる。*1
Mavenでは、基本的に一つのプロジェクトについて、 一つの成果物を作成するようになっている。 今回のプロジェクトでは、 Webサービス部分とUI部分の二つがウェブアプリケーションとして作成される。 一つのプロジェクトでは二つのwarを作ることは出来ないため、 プロジェクトをWS部とUI部に分割する。 またWS部、UI部共通となるWebサービスのインターフェイスやDTOを取り出し、 別プロジェクトとする。 さらに、これらのプロジェクトをまとめるプロジェクトを作成する。
プロジェクトの構成は以下のようになる。(bookshelfはこのプロジェクト全体の名前)
本来Mavenでは、マスター(親)プロジェクトのディレクトリ下に、 サブ(子)プロジェクトのディレクトリを置く入れ子構造になることを意識している。 今回のプロジェクトではEclipseと連携させるため、 すべてのプロジェクトを同一ディレクトリ内に置く必要がある。
製造にはEclipseを使用する。 そのため、階層構造を保ったままプロジェクトを作成することが出来ない。 全て同一階層にプロジェクトを作成し、 階層構造はproject.propertiesなどへの設定によって実現する。
まずはEclipseでプロジェクトを作成する。
次にコマンドラインから各プロジェクトのディレクトリで、 以下のコマンドを実行する。
maven genapp
uiはStrutsを使用することが決定しているので、 テンプレートにstruts-jstlを指定。 serviceはwebをのこりはdefaultのまま。 アプリケーション名適切に(笑)設定し、 パッケージ名はすべて「jp.co.nskint.wsrg.bookshelf」とした。
さらに、各ディレクトリで、
maven eclipse
と実行することで、mavenのproject設定が、 eclipseのproject設定に反映される。
Eclipse上でMavenの実行を可能にするため、 Eclipse用のプラグインであるMevenide*2 を導入する*3。
またこれをインストールすることで、 project.xmlの編集をXMLとしてではなく、 ウィザードのような画面で行うことが出来るようになる。
まずは、各プロジェクトがどのようなライブラリに依存するのかを設定する。
ui、serviceに共通である、 axis関連、spring関連のライブラリ、 ビルドに使用するmavenプラグイン、xdoclet関係は、 マスタープロジェクトのproject.xmlに設定する。 そして、ui、service、commonsのproject.xmlは、 マスタープロジェクトのproject.xmlを継承するように設定し、 uiにはstruts関連のものを、 serviceにはhibernate/DB関連のものを設定する。 また、uiとstrutsはcommonsの成果物(bookshelf-commons.jar)に依存するため、 これも依存関係を設定する。 さらに、warに含めるライブラリのプロパティに、 war.bundleをtrueとして設定する。
次に、各サブプロジェクトのproject.xmlにある、 設定のうち、マスターにあればいいもの (currentVersion、organization、inceptionYear、package、logo、uri、issueTrackingUrl?、siteAddress、siteDirectory、distributionDirectory、buildの各要素)を削除する。
また、マスタープロジェクトのproject.xmlの各要素を適切に編集する。
まずは、マスタープロジェクトに、 サブプロジェクトがどれであるか、 どこにあるかを教えるための設定をする。
project.propertiesへ設定した内容は以下の通り。
#これを設定しないと、サブプロジェクトを認識しない maven.multiproject.basedir="${basedir}/../" #サブプロジェクトのproject.xmlの場所 maven.multiproject.includes=bookshelf-commons/project.xml,bookshelf-service/project.xmlbookshelf-ui/project.xml
次に、各サブプロジェクトのproject.propertiesに、 成果物のタイプの指定を追加する。
ui、serviceはwarファイルを生成するため、
maven.multiproject.type=war
と設定する。
commonsは、
maven.multiproject.type=jar
と設定する。
すべてのプロジェクトをビルドするには、 goalにmultiproject:install *4 を指定する。
ビルド情報をまとめ、 サイトを生成するには、 multiprojectまたはmultiproject:siteを指定する。
Mavenのプラグインには、Hibernateを利用するのに威力を発揮するものがある。
hibernate-pluginを使用して、 マッピングファイルからJavaのソースコードを生成できるようになると、 さらに利便性が増すが、 XDocletをメインにするのなら現状で十分な機能を持っていると言える。
mavenを実行すると、 依存性を解決するため、 ネット上から依存するライブラリをダウンロードしてくる。 そのため、mavenを使用してビルドを行う時には、 ネットにつながっている必要がある。
また、大量のライブラリをダウンロードするため、 最初のビルドには、非常に時間がかかる。
プロジェクトでは、誰かが最初に実行して、 ローカルリポジトリの内容を、 配布したほうがいいかもしれない。
プロジェクトのディレクトリ構成は、 これまでのプロジェクトではお目にかかったことの無いような、 Maven特有のディレクトリ構成になる。 最初のうちはちょっと違和感を感じるかも知れない。*5
Antであれば、ビルド先のフォルダ作って〜、 コンパイルして〜、jarで固めて〜というのを、 新しいプロジェクトのたびに、 新たなスクリプトに記述する必要がある。 Mavenであればgenappした段階で、 そういった作業は完了する。
後は、プロジェクトに必要な情報を設定し、 設定ファイルを各担当者に配布し、 各自Mavenを実行するだけで、 全員の環境が同じように出来上がる。 環境を構築できないものや、 間違った構築をしてしまうものが発生することはまず無い。*6
近年のオープンソースプロダクトでは、 このMavenを利用したプロジェクトが非常に多い。 はじめて見たときは違和感を覚えたが、 慣れると非常に整理されていると感じる。
Mavenのやり方に一度慣れてしまえば、 ほとんどのJavaプロダクトで環境準備から、 配布物の生成までの工数を削減できるものと思われる。