はじめに
マルチモジュールプロジェクトでwebモジュールと環境設定モジュールを別にし環境に依存しないwarファイルを作ってTomcatで実行できるか試してみました。
- 環境設定とは今回はDBの接続先に限定します。つまり、開発時や検証環境、本番環境と用途ごとに接続先は解れるが、warファイルは同じものを利用できるようにすることが目標です。
- 考え方はTerasoluna 3.5. 開発プロジェクトのビルドの『envモジュールのjarファイルをwarファイルに含めないビルド方法』をベースにしています。
- ただし検証に利用するプロジェクトがレガシー過ぎるので、このプロジェクトで対応できる方法で考えました。
- "xxx"はwebアプリのartifactidです。またversionは0.0.1-SNAPSHOTなので生成されるjarも
xxx-env-0.0.1-SNAPSHOT.jar
となりますがVersion表記は省略しています。
目標
- webモジュール内の環境設定ファイルを別モジュールに分ける
- DBの接続先ごとに設定ファイルを作りprofileを利用してjarを作成する
- Webモジュールに環境設定ファイルのpathを通す
- webモジュールをTomcatにデプロイする
動作環境
- Windows7
- Maven 3.3.9
- JDK 1.7
- Tomcat 7
- Oracle 12.1.0.1
- IDE:Eclipse 4.7.0
※Tomcatのインストール先は、開発環境(IDEと同じPC)です。
1. webモジュール内の環境設定ファイルを別モジュールに分ける
環境設定ファイルwebapp/WEB-INF/applicationContext.xml
をsrc/main/resources/META-INF
に移動しても動作することを確認するため、struts-config.xmlのプラグイン「org.springframework.web.struts.ContextLoaderPlugIn」の設定ファイルのパラメータで指定していた/WEB-INF/applicationContext.xml
をclasspath*:/META-INF/applicationContext.xml
に変更したところ問題無く動作しました。
そこでマルチモジュールプロジェクト配下に、環境設定用のモジュールxxx-envを作成しapplicationContext.xmlをsrc/main/resources/META-INF
に移動し、webモジュール側のdependencyにxxx-env.jarを追加し動作を確認しました。
これによりアプリケーションの環境依存部分を別モジュールに切り分けることができました。
2. DBの接続先ごとに設定ファイルを作りprofileを利用してjarを作成する
xxx-envモジュールに、local(開発)/staging(検証)/prod(本番)の3つを作成し異なるDB接続先を定義したapplicationContext.xmlを用意しました。
- local・・・・
src/main/resources/META-INF/applicationContext.xml
- staging・・・
configs/staging/resources/META-INF/applicationContext.xml
- prod・・・・
configs/prod/resources/META-INF/applicationContext.xml
xxx-envモジュールのpom.xmlで以下のようなprofilesを定義しました。
・・・
<build>
<finalName>${buildFinalName}</finalName>
<resources>
<resource>
<directory>${resource.directory}</directory>
</resource>
</resources>
</build>
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<resource.directory>src/main/resources</resource.directory>
<buildFinalName>${project.artifactId}-${project.version}-dev</buildFinalName>
</properties>
</profile>
<profile>
<id>staging</id>
<properties>
<resource.directory>${basedir}/configs/staging/resources</resource.directory>
<buildFinalName>${project.artifactId}-${project.version}-staging</buildFinalName>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<resource.directory>${basedir}/configs/prod/resources</resource.directory>
<buildFinalName>${project.artifactId}-${project.version}</buildFinalName>
</properties>
</profile>
</profiles>
・・・
mvnコマンドで、PackageやInstallフェーズを実行時に、-PオプションでprofileのIDを指定すると対象のresourceでjarファイルが作成されます。
上記の設定の場合、-P prod
なら本番環境用のxxx-env.jar、-P staging
なら検証環境用のxxx-env-staging.jar、何も指定しない(デフォルト)は開発用のxxx-env-dev.jarが実行されます。
3. Webモジュールに環境設定ファイルのpathを通す
Tomcat7のディレクトリopt/environment/app
にxxx-env.jarを置き、webappsのモジュールから参照できるようにします。
今回はWebモジュールのsrc/main/webapp/META-INF/context.xmlに、VirtualWebappLoaderを設定し、WebモジュールのClasspathにxxx-env.jarを含めるようにします。
<?xml version='1.0' encoding='utf-8'?>
<Context>
<Loader className="org.apache.catalina.loader.VirtualWebappLoader" virtualClasspath="/opt/environment/logtime/prod/*.jar"/>
<JarScanner scanAllDirectories="true"/>
</Context>
maven-war-pluginを実行してcontext.xmlをWARファイルに含めるように設定します。
・・・
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.5</version>
<configuration>
<containerConfigXML>src/main/webapp/META-INF/context.xml</containerConfigXML>
</configuration>
</plugin>
・・・
4. webモジュールをTomcatにデプロイする
環境設定を排除したWARファイルを作成し、Tomcatにデプロイします。
dependencyからxxxx-envを削除し、profilesでWAR作成時はxxxx-envを含めないように設定します。
・・・
<profiles>
<profile>
<id>local</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xxxx-env</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>warpack</id>
</profile>
</profiles>
・・・
上記により、'-P warpack'を指定した時だけ、xxx-envから依存性を排除します。
つまり、mvn -P warpack clean package
とすると、xxx-env.jarが含まれないWARが作成されます。
※デフォルトでは、xxx-envへの依存性が定義されているので開発時などIDEで実行するときは参照します。
作成したWARをTomcatのwebappsに配備します。
動作確認とまとめ
Tomcatを起動しWebアプリケーションにアクセスすると、本番環境用のDBへアクセスすることが確認できました。
opt/environment/app
のjarを-P staging
で作成した、検証環境用のxxx-env-staging.jarに置き換え、Tomcatを再起動すると今度は検証環境用のDBにアクセスすることが確認できました。
こうすることで、例えば検証用と本番用でWARファイルが使いまわせるため、モジュールの同一性が保証でき、リリース間違いが減らせるようになります。
参考
Terasoluna 3.5. 開発プロジェクトのビルド
War ファイルにコンテキスト固有の情報を設定する
Apache Maven WAR Plugin
[Maven] Maven2 で Apache Tomcat の context.xml を WAR に追加する方法
コンテキスト情報の記述場所