これはJavaEE Advent Calendar 2012の22日目のエントリです。

ぼやぼやしているうちにラスト3とかになってしまい、大変恐縮です。
昨日は@javaflavorさんの「Java EE環境でjava.util.loggingとうまく付き合う方法」でした。

22日目の今日は、mvnプロジェクトとしてSpringフレームワークを使用したフロントアプリを開発した際、profile毎にpropertiesの値を切り替えることで、環境毎に異なる設定ファイルを適用する方法について書きます。

プロジェクト概要

プロジェクト全体、個別のモジュールをmvnプロジェクトとして管理している割と大きなアプリケーションです。

application
|_pom.xml
|_common application
 |_pom.xml
|_service application
 |_pom.xml
|_database access application
 |_pom.xml
|_fromt web application <<- これ!
 |_pom.xml

考慮すべき環境としては以下がありました。

  • development(Windows)
  • development(Linux)
  • integration
  • stating
  • production

環境に応じて設定ファイルを自動読込する必要性

今回は、以下の3設定ファイルを環境ごとに個別に設定する必要がありました。

  • applicationContext.xml
  • ログ設定
  • DB接続設定

(DB接続先や設定ファイルのパス、ログレベル、ミドルウェアの設定等が全ての環境で微妙に異なる・・・。)

もちろん、設定ファイルのディレクトリを固定して、環境ごとにファイルを差し替えれば動くことは動くのですが、人為的なミスを誘発しますし、筋が悪い。
ということで、mvnの設定(pom.xml)で、自動的に環境に応じた設定ファイルを読み込むようにしました。
もとい、自分のチームのの設定が自動的に環境に応じた設定ファイルを読み込むようになっていました。
「へえ!」と思ったので、方法を共有しようというのがこの記事です。

設定方法

親プロジェクトでprofilesを設定する

環境毎にprofileを作ります。
プロファイルとは、ビルド環境やリリース環境などの環境に依存する設定を記述するためのものです。>> 参考(とても詳しい!)

$ mvn [goal] -P [profile]

と記述してビルドetc.を行うことで、有効化するプロファイルを決定することができます。
また、pom.xmlのactivationにjdkのバージョン、osの種類、システムプロパティ値や指定ファイルの有無を指定することにより、明示的に指定をしなくても環境によってプロファイルを切り替えることもできます。(今回の設定だと[development-linux]にosの種類により自動的にプロファイルを適用するための記述があります。)

今回は、pom.xmlに以下のような記述をしました。

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
[略]
  <profiles>
    <profile>
      <id>development-win</id>
      <activation>
        <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
        <conf.dir>development-win</conf.dir>
      </properties>
    </profile>
    <profile>
      <id>development-linux</id>
      <activation>
        <os>
          <name>linux</name>
        </os>
      </activation>
      <properties>
        <conf.dir>development-linux</conf.dir>
      </properties>
    </profile>
    <profile>
      <id>integration</id>
      <properties>
        <conf.dir>integration</conf.dir>
      </properties>
    </profile>
    [残りも同じ感じ]
  </profiles>
[略]
</project>

maven-war-pluginの設定

親プロジェクトで設定します。webResourceに追加する設定ファイルのパスを設定します。
profile毎に定義した変数 ${conf.dir} を参照するので、どの子プロジェクトでも、warファイルを作成する際、基本的に環境ごとに異なるパスが読み込まれることになります。

        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-war-plugin</artifactId>
          <version>2.1.1</version>
          <configuration>
            <webResources>
              <resource>
                <directory>src/conf/${conf.dir}/webapp</directory>
              </resource>
            </webResources>
          </configuration>
        </plugin>

フロントアプリ側の設定

フロントアプリとなるpom.xmlでは以下の設定をすればOK。

  • packagindタイプをwarにする
  • (フロントアプリ独自に必要な maven-war-plugin の設定をする。urlとか)
[略]
  <name>Front Web Application</name>
  <packaging>war</packaging>
[略]

フロントアプリのディレクトリ構成

上記の設定の場合、以下のようなファイル構成になります。

root
|_src
  |_conf
    |_development-linux
      |_etc
        |_ログ設定ファイルやDB接続情報
      |_webapp
        |_WEB-INF
          |_applicationContext.xml
    |_development-win
    |_integration

eclipseでglassfishを動作させている場合の注意点

eclipseのGlassFishプラグインを使用している場合、画面から直接プロジェクトをデプロイ(Add and Removeからwarファイルを指定
)することができます。
これをすると、編集内容がビルドなしですぐにサーバーに反映されるという便利さがあるのですが、プロファイルの切り替えが適用されないようです。
デフォルトの配置位置である src/main/webapp/WEB-INF/applicationContext.xmlが読み込まれます。
profileプラグインの設定でデフォルト(activeByDefault)を設定しても適用されず。
mvnのwarプラグインにだけ適用される値だからeclipseのGlassFishプラグインからは無視されるのかな。
回避する方法がわかりません・・・

JavaEEのAdvent Calenderの記事だったのですが「mvn使いこなすとほんとにいろんなことが出来るよ!」という記事になってしまいました。
しかし、JavaEEとmvn、どちらも大きなアプリケーションを作るときには外せないものだと思います。
pom.xmlと仲良くして、自分の手間を減らしていきたいですね!

明日は@zephiransasさんが担当です。