SAFluteのプロジェクト構成
SAFluteを使ったアプリのプロジェクト構成やDBFluteのリソースについて。
とりあえずこんな感じです
架空のプロジェクトである、Maihamaプロジェクトの Dockside ドメイン (webアプリ) を想定して説明します。これらは、SAFlute の Example 実装として公開されています。
Maihamaプロジェクトのプロジェクト構成
e.g. Maihamaプロジェクトのプロジェクト構成 @Directory
saflute // SAFlute本体 (ソースコード)
|-src/main/java // SAFluteのソース
|-src/main/resources // saflute.dicon など
|-...
maihama-base // ベースプロジェクト (親pomやドキュメントなど)
|-document // ドキュメント置き場 (モデルやERDなど)
| |-concept // 概念モデルの画像など (アーキテクチャ図など)
| |-erd // ERDのファイル (Maihama では ERMaster-b を利用)
|-environment // 環境ファイル置き場
| |-eclipse // Eclipse関連ファイル置き場
| | |-dropins // 自作のEclipseプラグイン置き場
| | |-code-formatter-profile.xml // コードフォーマッター設定 (最初の一人が設定)
| | |-java-editor-templates.xml // エディタテンプレート設定 (みんなでimport)
|-...
|-pom.xml // プロジェクト全体の共通pom
maihama-common // commonプロジェクト (DBFluteも含む)
|-src/main/java // Maihamaプロジェクト共通クラス
|-src/main/resources // convention.dicon, dbflute.dicon など
|-...
|-dbflute_maihamadb // いわずとしれたDBFluteクライアント
| |-dfprop // DBFluteプロパティ (設定ファイルたち)
| | |-...
| | |-freeGenDefinitionMap.dfprop // SAFluteでとっても重要、FreeGenの設定
| | |-documentDefinitionMap.dfprop // 同じく重要、PropertiesHTMLの設定
| | |-...
| |-freegen // FreeGenのテンプレートファイル置き場
| | |-ControlFreeGen.vm // FreeGenのコントロールvmファイル
| | |-JspPath.vm // JSPのパス定義のvmファイル
| | |-...
| |-playsql // ReplaceSchemaのリソース置き場 (SQLやエクセルデータなど)
| | |-data // ReplaceSchemaで登録するデータ置き場
| | | |-common // 共通のデータ
| | | |-ut // ut環境(デフォルト)におけるデータ (つまりテストデータ)
| | | | |-reversexls // LoadDataReverseの出力先 (循環テストデータ運用で重要)
| | |-...
| |-...
| |-manage.bat // 同じく重要、FreeGenを叩くためのバッチ (12番がFreeGen)
| |-manage.sh // それのシェル版 (Mac, Linux用)
| |-...
|-mydbflute // DBFluteモジュール
|-...
|-pom.xml // commonプロジェクトのpom (baseのpomを継承)
maihama-dockside // ドメインプロジェクト (webアプリ)
|-src/main/java // Docksideドメインのクラス
|-src/main/resources // app.dicon, saflute_assist++.dicon など
|-...
|-pom.xml // docksideプロジェクトのpom (baseのpomを継承, common参照)
Maihamaプロジェクトのパッケージ構成
src/main/java や src/main/resources などのパッケージ構成は、別ページにて紹介しています。
Mavenの構成
Mavenの継承関係
Mavenの設定、pom.xml が継承関係になっています。(maihamaで例えます)
- saflute
- 独立したpom.xml
- maihama-base
- アプリのすべてのプロジェクトの親pom
- maihama-common
- maihama-baseを継承
- maihama-dockside
- maihama-baseを継承して、maihama-commonに依存
Mavenでのテプロイ
よって、Mavenでデプロイするときは...
- saflute で mvn -e clean install
- maihama-base で mvn -e clean install
- maihama-common で mvn -e clean install (profileの切り替えが必要なら -P オプション)
- maihama-dockside で mvn -e clean package (profileの切り替えが必要なら -P オプション)
という手順で、warファイルを作ることができます。
環境切り替えの構成
リソースの環境切り替え
環境ごとに設定を切り替えるための構成が用意されています。
Mavenでビルド (パッケージング) をするときに profile を指定することで切り替えます。
- src/main/resources
- ローカル用 (デフォルト) (環境切り替えがなければこれ)
- src/allpackage/resources
- パッケージングするすべての環境用 (次に優先)
- src/integration/resources
- 結合環境用 (最優先)
- src/production/resources
- 本番環境用 (最優先)
例えば、ローカル用に sea.properties があっても、productionの方にも sea.properties があった場合、本番環境では production の sea.properties が利用されます。一方で、ローカル用に land.properties があって、他の環境で同じファイルが一切なければ、どの環境でもローカル用のものが利用されます。
allpackageは、結合環境や本番環境など、パッケージングされてデプロイされる環境における共通の領域です。 例えば、log4j.properties などは結合環境でも本番環境でも設定が変わらないのであれば、allpackageに置くとよいでしょう。
Mavenの profile 設定は、common, webプロジェクトそれぞれの pom.xml にあります。baseに入れていないのは、webとcommonで設定が変わる可能性があるだろうということで、あえて共通化していません。 もし、webプロジェクトを増やすときに、webの共通pomを作った場合は、webのprofile設定はそちらで一元管理するとよいでしょう。
ちなみに、Seasar の env.txt は、デフォルトでは allpackage に入っています。パッケージングした環境ではすべて CoolDeploy になるようになっています。
環境切り替え用のproperties
ファイル単位で切り替えるため、一つのファイルで環境ごとのものと環境で変わらないものが混在していると重複の原因になります。 なので、なんでもかんでも切り替えるのではなく、環境切り替え用のpropertiesを用意しています。
デフォルトでは、commonの下に xxx_env.properties が用意されています。 こちらに、DBの接続情報や、メールサーバーの情報などを入れて切り替えるとよいでしょう。
e.g. リファレンス実装のMaihamaプロジェクトでの環境ごとのProperties @Directory
maihama-common
|-src/main/resources
| |-maihama_config.properties // 環境依存しないコンフィグ
| |-maihama_env.properties // ローカル環境用のコンフィグ (環境ごとにコピーされる)
|
|-src/main/integration
| |-maihama_env.properties // 結合環境用のコンフィグ
|
|-src/main/production
| |-maihama_env.properties // 本番環境用のコンフィグ
こちらの properties は、プログラム上でタイプセーフに get することができます。
もし、webプロジェクトごとの環境切り替え properties を作りたい場合は、FreeGen や PropertiesHtml の設定や、AssistantDirector のプログラムを修正する必要があります。 (ただ、複雑になるので、よほどたくさんあるとかでなければcommonで一元管理でもいいかもです)
プログラム上で環境切り替え分岐
基本的に、プロパティ値の切り替えだけで環境切り替えを実現するのが理想です。プログラム上で "ローカルだから本番だから" という分岐を入れるのは、あまりオススメではありません。
ですが、どうしてもというときにある程度できるようにしています。
e.g. isDevelopmentHere()による分岐 @Java
if (maihamaConfig.isDevelopmentHere()) { // 開発環境(ローカル)だったら
...
}
もしくは、EnvDispatchアノテーションで Logic をまるごと切り替えます。
e.g. EnvDispatchによるロジックの切り替え @Java
@EnvDispatch(dev = SeaLogicDev.class, real = SeaLogicReal.class)
public interface SeaLogic {
...
}
// SeaLogicDev と SeaLogicReal は SeaLogic インターフェースをimplements
結合と本番でプログラムを分岐させる方法はデフォルトでは用意していません。 結合はできるだけ本番に近いプログラムで動いて欲しいものだからです。プロパティの値だけで切り替えたいところです。 ですが、どうしてもというときは、isDevelopmentHere()の仕組みを応用すれば、できなくはないので必要になったら修正を。
ログの設定 (log4j.properties)
少なくともリリース時点では、結合環境は本番のログレベルは INFO (DEBUGは出さない) にすると想定されるので、webプロジェクトの src/allpackage/resources 配下の log4j.properties の log.logger.loglevel を INFO にします。
また、SAFlute Template でプロジェクトを作成した時点では、結合や本番ではコンソールにはアプリログを出力しません。 これは、catalina.outが肥大化してしまう可能性があるためと同時に、catalina.outは Tomcat のログに徹したものにしたいというところから、アプリログは専用のログファイルに出力されます。 ただ、もし catalina.out に出力したい場合は、consoleを追加すれば出力できます。
新しいデプロイ環境をつくるなら
新しい環境 (profile) をつくる場合は、いくつかの設定ファイルを修正していく必要があります。
ReplaceSchemaの環境切り替え
もし、結合環境のDBを ReplaceSchema で管理するときのために、DB接続先などを切り替えることができます。 ちなみに、本番では ReplaceSchema は絶対にやりませんので、結合とか検証環境においてのみの話です。
DBFluteの環境ごとのdfpropの切り替えを使って実現します。
例えば、integration だったら...
e.g. 結合DB(integration)のためのReplaceSchemaのdfprop構成 @Directory
DBFluteクライアント // dbflute_maihamadb とか
|-dfprop
| |-integration
| | |-databaseInfoMap+.dfprop // 結合DBへの接続先を設定
| | |-replaceSchemaDefinitionMap+.dfprop // 結合でのReplaceSchemaの微調整
| |
| |-...dfprop
| |-databaseInfoMap.dfprop
| |-replaceSchemaDefinitionMap.dfprop
| |-...dfprop
|
|-log
|-output
|-...
|-_integration_
databaseInfoMap+.dfpropには、結合DB用の接続情報を差分で設定します。
e.g. 結合用の databaseInfoMap+.dfprop の設定 @databaseInfoMap.dfprop
map:{
; url = jdbc:mysql://integration.maihamadb.org:3306/maihamadb
; schema =
; user = maihamadb
; password = maihamadb
}
replaceSchemaDefinitionMap+.dfpropには、結合DBに登録するテストデータの選択、システムユーザーによるスキーマの自動作成をするかどうかなどの微調整を設定します。
例えば、特に結合DB専用のテストデータを用意していないのであれば、repsEnvType は ut で。もし、用意する場合は、repsEnvType を integaration に修正。 (テストデータをローカル用と結合用と分けて管理するのは、なかなかリソース的に難しい可能性があるので、とりあえずはutでもOKかと)
また、システムユーザーによるスキーマの自動作成をしないのであれば、additionalUserMapは空っぽで上書き。 使いたい場合は本体のdfpropを真似て設定しましょう。 (結合に関しては、そこまで自動化しなくても手間はあまりかからないので、ここでは空っぽで紹介しています)
e.g. 結合用の replaceSchemaDefinitionMap+.dfprop の設定 @replaceSchemaDefinitionMap.dfprop
map:{
# same as UT for now
; repsEnvType = ut
# no system user here
; additionalUserMap = map:{
}
}