「Apache Maven WAR Plugin」で環境ごとの設定ファイルを変更する方法とシクハクしたところまとめてみました[文字化け]

Tips

約1年ほどの新規開発がアプリケーションとして落ち着いてきた……。
保守開発やリリースがやりやすいようにするため、Mavenで環境ごとの設定ファイルを置換したりすることをやることになりました。
ちょっとシクハクしたことにも出くわした……ので、メモ。

War作成プラグイン「Apache Maven WAR Plugin」(maven-war-plugin)

warファイルが作成できるプラグインです。このプラグインに設定ファイルなどのファイルを置換や追加・除外することが可能です。

うまいこと設定できると、Mavenのプロファイルの切り替えだけでWarファイル作成時に、設定ファイルを入れ替えることが可能なんですね。

Apache Maven WAR Plugin – Introduction

The WAR Plugin is responsible for collecting all artifact dependencies, classes and resources of the web application and packaging them into a web application archive. war:war is the default goal invoked during the package phase for projects with a packaging type of war. It builds a WAR file.

「Apache Maven WAR Plugin」とプロファイルの設定で環境ごとの設定ファイルを変更する

リリースする環境が増えてきて、手作業で切り替えがややこしくなってきたので、うまいことMavenの設定でできないかなぁ、と。
やりたいことが以下の3つ。

  • resourcesディレクトリーごとファイルを入れ替える
  • web.xmlを入れ替える
  • WEB-INFの一部のファイルだけを入れ替える

サンプルになるフォルダ構成をつくってみました。
フォルダが以下のようになっているとき、developmentプロファイルを設定し、Mavenプロジェクト更新すると、developmentのフォルダ内のファイルが置換されるようにしてみました。

<プロジェクト>
|-- pom.xml
|
|-- development
|   |-- resources
|   |    |-- base.properties
|   |    `-- sample.xml
|   `-- webapp 
|		`-- WEB-INF	 
|			|-- web.xml
|			`-- spring
|				|-- root-context.xml
|					`-- appServlet
|						`-- servlet-context.xml
|
`-- src
  `-- main
    |-- java
    |-- resources
	|    |-- base.properties
	|    `-- sample.xml
	`-- webapp
		`-- WEB-INF	 
		 	|-- web.xml
			 `-- spring
				|-- root-context.xml
				`-- appServlet
					`-- servlet-context.xml

resourcesディレクトリーごとファイルを入れ替える

こちらはプロファイルの設定のみで可能です。
pom.xmlの抜粋を。

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
	・・・	 
<build>
<sourceDirectory>src/main/java</sourceDirectory>
</build>
・・・
<profiles>
	<profile>
		<id>development</id>
		<build>
			<resources>
				<resource><!-- developmentフォルダを先に指定することで、base.propertiesやsample.xmlが優先(上書き)される -->
					<directory>src/development/resources</directory>
				</resource>
				<resource>
					<directory>src/main/resources</directory>
				</resource>
			</resources>
		</build>
	</profile>
</profiles>
</project>

web.xmlを入れ替える

「Apache Maven WAR Plugin」を使って、webXmlタグにパスを指定すると上書きされます。
通常ビルドとプロファイルのpropertiesタグにそれぞれweb.xmlのパスを記載することで動的に変更することができます。

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
	・・・	 
	<properties>
		<webxml.path>src/main/webapp/WEB-INF/web.xml</webxml.path>
	</properties>
	<build>
		<sourceDirectory>src/main/java</sourceDirectory>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.0.0</version>
				<configuration>
					<webXml>${webxml.path}</webXml>
				</configuration>
			</plugin>
		</plugins>
	</build>
	・・・
	<profiles>
		<profile>
			<id>development</id>
			<properties><!-- developmentフォルダ内のweb.xmlを指定する -->
				<webxml.path>src/development/webapp/WEB-INF/web.xml</webxml.path>
			</properties>
		</profile>
	</profiles>
</project>

WEB-INFの一部のファイルだけを入れ替える

targetPathタグでWEB-INFを指定し、springフォルダ内のxmlファイル(root-context.xml、servlet-context.xml)をフィルター機能で置換することにしました。

<?xml version="1.0" encoding="UTF-8"?>
<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/maven-v4_0_0.xsd">
	・・・	 
	<properties><!-- エンコードの設定がなければ、必要。なぜ必要なのかは後述。 -->
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<spring.path>src/main/webapp/WEB-INF</spring.path><!-- プロファイルなしのときのパスの設定をしておく -->
	</properties>
	<build>
		<sourceDirectory>src/main/java</sourceDirectory>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-war-plugin</artifactId>
				<version>3.0.0</version>
				<configuration>
					<webResources>
						<resource>
							<directory>${spring.path}</directory>
							<targetPath>WEB-INF</targetPath>
							<filtering>true</filtering>
							<includes>
								<include>**/spring/**/*.xml</include>
							</includes>
						</resource>
					</webResources>
				</configuration>
			</plugin>
		</plugins>
	</build>
	・・・
	<profiles>
		<profile>
			<id>development</id>
			<properties>
				<spring.path>src/development/webapp/WEB-INF</spring.path>
			</properties>
		</profile>
	</profiles>
</project>

maven-war-pluginが正常稼働していたのに、パス指定したときに間違っているとき、以下のようなエラーが出ていました。
propertiesに書いたパスを疑ってみるといいかも。

Execution default-cli of goal org.apache.maven.plugins:maven-resources-plugin:2.6:copy-resources failed. (org.apache.maven.plugins:maven-war-plugin:3.0.0:war:default-war:package)

なぜか置換したファイルの一部の文字だけ文字化けする

んで、今回のでシクハクしたところ。
上の「WEB-INFの一部のファイルだけを入れ替える」を行ったとき、以下のようなエラーが発生しました。

Error occured processing XML ‘Invalid byte 3 of 3-byte UTF-8 sequence.’. 詳細についてはエラー・ログを参照してください servlet-context.xml /<プロジェクト名>/target/m2e-wtp/web-resources/WEB-INF/spring/appServlet

上のファイルのファイルを確認すると、コメントで書かれている日本語の「言」という文字だけ「�?」になって文字化けしてました。(ファイル内に3つあったから3-byteのエラーになってる。)

ファイルはUTF-8だし、コピーする前は正常に動いていたので、コピーしたときに文字化けしている……。しかも一文字だけってのが怖い。

Mavenのデフォルト設定の確認

アプリケーションだけでは文字化けは発生していなかったので、Mavenを疑って、とりあえずデフォルト設定を確認してみる。

	C:\Users\[ユーザー名]>mvn -version
	Apache Maven 3.3.9 (bb52d8502b132ec0a5a3f4c09453c07478323dc5; 2015-11-11T01:41:4
	7+09:00)
	Maven home: C:\Program Files\Apache\maven-3.3.9
	Java version: 1.8.0_111, vendor: Oracle Corporation
	Java home: C:\Program Files\Java\jdk1.8.0_111\jre
	Default locale: ja_JP, platform encoding: MS932
	OS name: "windows 7", version: "6.1", arch: "amd64", family: "dos"

platform encoding: MS932 おまえかー!

対処法

pom.xmlのpropertiesタグに以下のようなエンコードの設定を追加することで、文字化けせず、ファイルが置換されるようになりました。
(上の設定方法の紹介では、この設定は織り込み済みです。)

		<properties>
			<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
			<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		</properties>

Maven:エンコーディング設定 – 開発メモ

Maven の pom. xml で、ソースやレポート出力の エンコーディング を設定したいときがあります。設定方法はいくつかありますが、良さそうな設定方法を調査してみました。 次のように、pom. xml の プロパティで設定するのが良さそうでした。 UTF-8 UTF-8 プロパティで設定をしておけば、 プラグインの エンコーディング 設定(下のような設定)を省略できるからです。 org.apache.maven.plugins maven-resources-plugin 3.0.2 UTF-8 maven-resources-plugin, maven-compiler-plugin などの プラグインは、プロパティの エンコーディング 設定を参照するみたいです。 エンコーディング設定をしていないと、 Maven 実行時に次のような警告が出てきたりします。 ・・・ [INFO] — maven-resources-plugin:2.6:resources (default-resources) @ poml — [WARNING] Using platform encoding (MS932 actually) to copy filtered resources, i.e.

おそらくなんですけど「maven resources plugin」(maven-resources-plugin)がコピーするときのエンコードがデフォルトのMS932を使っていて、UTF-8の「言」の一部が消えてしまったんじゃないかなぁと思っています。

まとめ

今回、リリースする環境が複数になってきていて、手作業が面倒だなぁということから始まったMaven設定方法がんばってみました。
自分たちの手作業を減らして、アプリがよりよくなるような時間を割くことができるといいですよね!ぜひ参考にしていただければうれしいです。

参考資料

先人の方々のサイトやブログで作ることができました。リンクを持って感謝!かんしゃ!

6. プロファイル

2009.04.03 シナジーマーケティング株式会社 鈴木 圭 今回は、環境依存の設定を記述するためのプロファイルという機能について解説します。プロファイル機能を活用することで、プロジェクトのビルドをより安全かつポータブルにすることができます。 プロファイルとは、ビルド環境やリリース環境などの環境に依存する設定を記述するためのものです。環境に依存する設定には、次の二種類が考えられます。 リリース環境によって異なる設定(接続先データベースやログファイルの出力先) ビルド環境によって異なる設定(OS の種類やアプリケーションサーバのインストール先) 環境依存の設定を上手く扱えない場合、以下のような問題が発生します。 複数人が参加するプロジェクトにおいて、開発者はそれぞれの環境に合うように設定ファイルを修正しなければならない。 普段は開発用にビルドしているから問題無いが、本番用にビルドする場合は設定ファイルを本番環境用に修正しなければならない。 このような問題に対応するために Maven に用意されている機能がプロファイルです。 プロファイルは以下のファイルに記述することができます。 pom.xml プロジェクトの pom.xml に記述されたプロファイルは、そのプロジェクトだけで利用可能となります。 profiles.xml profiles.xml は pom.xml からプロファイルの設定だけを抜き出したファイルです。profiles.xml に記述されたプロファイルは、そのプロジェクトだけで利用可能となります。注意として、本章執筆時点では profiles.xml に記述したプロファイルがデフォルトで有効になってしまうという不具合があります( http://jira.codehaus.org/browse/MNG-2605 )。回避策としては、後述する activation/activeByDefault 要素に明示的に false を指定するなどが考えられます。 %USER_HOME%/.m2/settings.xml %USER_HOME%/.m2/settings.xml に記述されたプロファイルは、そのユーザだけで利用可能となります。 %M2_HOME%/conf/settings.xml %M2_HOME%/conf/settings.xml に記述されたプロファイルは、Maven を利用する全ユーザで利用可能となります。 プロファイルをどのファイルに記述するかについてですが、「なるべく pom.xml に記述する」「無理な場合は settings.xml に記述する」というスタンスが良いと考えます。settings.xml に記述するということは、プロジェクトに新しく参加する人も同様に settings.xml にプロファイルを記述しなければならないためです。プロジェクトのビルドをよりポータブルにするという観点では、pom.xml に記述する方が良いでしょう。 プロファイルは、settings.xml に記述する場合は settings/profiles/profile 要素内に、pom.xml の場合は project/profiles/profile 要素内に記述します。profile 要素は必要な数だけ記述します。以下に pom.xml への記述例を示します。 …

Maven2で環境に合わせて設定ファイルを切り替える方法(改訂版) – TrinityT’s BLOG

新案件でpom. xmlの設定を見直したら、 以前のエントリの方法が冗長だったので書き直し。 各環境で共通の設定部分をprojectタグ直下のbuildタグ内にまとめたことで、よりDRYな構成となった。 1.resourcesフォルダ以下のように分け、上書き変更したいファイルを置く。 src/main/resources/config.properties (開発) src/integration/resources/config.properties (結合テスト環境) src/production/resources/config.properties (本番) 2.pom. xml を以下のように記述 (※2008/5/21 一部修正) 3.本設定を行ったプロジェクトで、 Mavenコマンドの-Pオプションを変更することで設定変更可能となる ※例:warファイルのクリーンパッケージング


http://kikutaro777.hatenablog.com/entry/2013/06/03/204753

Mavenビルド時に開発用とリリース用でリソースを入れ替える。 – Develop with pleasure!

アプリケーションの開発中、開発用のモジュールとリリース用のモジュールで、設定ファイル等を書き換えたいというケースは多いと思う。代表的な例だとDBへの接続。開発中はJDBCのDriverManagerで接続し、リリース時はJNDIからDataSourceを取得とか。Maven2ではそういった環境に依存する設定をProfileという概念で環境毎に定義できる。pom.xmlに release …

Maven:エンコーディング設定 – 開発メモ

Maven の pom. xml で、ソースやレポート出力の エンコーディング を設定したいときがあります。設定方法はいくつかありますが、良さそうな設定方法を調査してみました。 次のように、pom. xml の プロパティで設定するのが良さそうでした。 UTF-8 UTF-8 プロパティで設定をしておけば、 プラグインの エンコーディング 設定(下のような設定)を省略できるからです。 org.apache.maven.plugins maven-resources-plugin 3.0.2 UTF-8 maven-resources-plugin, maven-compiler-plugin などの プラグインは、プロパティの エンコーディング 設定を参照するみたいです。 エンコーディング設定をしていないと、 Maven 実行時に次のような警告が出てきたりします。 ・・・ [INFO] — maven-resources-plugin:2.6:resources (default-resources) @ poml — [WARNING] Using platform encoding (MS932 actually) to copy filtered resources, i.e.

蛇足:上の指定を全部入りするとこんな感じ

		<?xml version="1.0" encoding="UTF-8"?>
		<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/maven-v4_0_0.xsd">
			・・・
			<properties>
				<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
				<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
				<webxml.path>src/main/webapp/WEB-INF/web.xml</webxml.path>
				<spring.path>src/main/webapp/WEB-INF</spring.path>
			</properties>
			・・・
			<build>
				<sourceDirectory>src/main/java</sourceDirectory>
				<plugins>
					<plugin>
						<groupId>org.apache.maven.plugins</groupId>
						<artifactId>maven-war-plugin</artifactId>
						<version>3.0.0</version>
						<configuration>
							<webXml>${webxml.path}</webXml>
							<webResources>
								<resource>
									<directory>${spring.path}</directory>
									<targetPath>WEB-INF</targetPath>
									<filtering>true</filtering>
									<includes>
										<include>**/spring/**/*.xml</include>
									</includes>
								</resource>
							</webResources>
						</configuration>
					</plugin>
				</plugins>
			</build>
			<profiles>
				<profile>
					<id>development</id>
					<build>
						<resources>
							<resource>
								<directory>src/development/resources</directory>
							</resource>
							<resource>
								<directory>src/main/resources</directory>
							</resource>
						</resources>
					</build>
					<properties>
						<webxml.path>src/development/webapp/WEB-INF/web.xml</webxml.path>
						<spring.path>src/development/webapp/WEB-INF</spring.path>
					</properties>
				</profile>
			</profiles>
		</project>