SMART deploy
目次
「SMART deploy」とは、「Seasar2.4」の推奨の規約(Naming Convention)を守ることにより、プロジェクトの初期設定を行った後、開発による新たな設定ファイルを追記する必要なく、開発を進めることができるというものです。
推奨されるパッケージの構成を使うことによって、「SMART deploy」を使えるようになります。 また、プロジェクトメンバの情報共有の点においても パッケージ構成が既に決まっている事で、どのクラスがどのパッケージにあるか探す事が容易になります。 もちろん、推奨のパッケージ構成を使わずに自由に決めることもできます。その場合は、HOT deployは使えませんが、Seasar2.3の自動登録は、そのまま使うことができます。
- (例)パッケージ構成
- examples.aaaa
- examples.aaaa.logic
- examples.aaaa.dao
- examples.aaaa.web.xxxx
パッケージ構成には2つのルールがあります。一つはルートパッケージ+個別のパッケージといった構成を持つことです。 ここで云われているルートパッケージとは、examples.aaaaの事を示しています。 その配下にあるパッケージは、個別のパッケージの命名規約を持っています。それについては、個別パッケージの要素の処で説明いたします。
もう一つはwebパッケージ以下にサブアプリケーションを持つ構成です。ここで言うサブアプリケーションとは、一つのアプリケーションを幾つかの論理的な固まりに分割したものです。ユースケースと読み替えても良いでしょう。
- (例)パッケージ構成の2パターン
-
①ルートパッケージ+個別パッケージ
- examples.aaa.logic
- ⇒examples.aaa : ルートパッケージ
- ⇒logic : 個別パッケージ
-
②ルートパッケージ+Web+サブアプリケーション
- examples.aaaa.web.xxxx
- ⇒examples.aaaa : ルートパッケージ
- ⇒web : サブアプリケーションのルートパッケージ
- ⇒xxxx : サブアプリケーション
次にパッケージの要素をしていきます。
サブアプリケーション固有のものをサブアプリケーション配下に分類し サブアプリケーション共通のものを個別パッケージとして管理しています。
Web
サブアプリケーションのルートパッケージです。
-
★HTML、Page、RDBMSのテーブルの関係
- HTMLの入出力項目(のid属性) が Pageクラスのプロパティに対応し、Pageクラスのプロパティがテーブルのカラムに対応します。また、HTMLのアクション(ボタン等)(のid属性) が Pageクラスのメソッドに対応します。サブアプリケーション(ユースケース)固有のロジックは、Pageクラスに記述します。複数のサブアプリケーションで共通に使われるロジックは、Logicクラスに記述します。ドメインモデルを使う場合、もう少し複雑な構成になりますが、ここでは、最もシンプルなパターンについて説明します。
-
□Page
- Pageクラスとは、HTMLと1対1に対応するクラスで、画面の情報と、イベント処理のロジックで構成されています。
- 命名規約は、対応するHTMLの名前+Page となります。HTMLのファイル名の最初を大文字にして、拡張子を取り除き、後ろにPageをつけます。HTMLが格納されるディレクトリ名がパッケージ名になります。例えば、view(Viewのルートディレクトリ)/add/addInput.htmlは、examples.aaa.web.add.AddInputPageに対応します。
-
□dao
- pageクラスの固有のdaoです。
- 命名規約は、任意のクラス名の後ろにdaoをつけます。サブアプリケーション固有のDaoを作成するならば、サブアプリケーションの名前+Daoと命名します。
-
□dxo
- MapとJavaBeans、JavaBeansとJavaBeansといったオブジェクト間のデータの相互変換を定義するインターフェースです。インターフェースにメソッドを書いておくだけで、モデル変換のロジックは、アスペクトが自動生成します。 実装部分を作る必要はありません。
-
□Impl
- dao、dxoは通常、実装クラスは必要ありませんが、自動的に変換できないような複雑なロジックは、明示的に実装することもできます。その場合、抽象クラスとし、必要なメソッドだけを実装してください。
- 命名規約は、dao,dxoのインターフェース名+Implとなります。
- 例えば、AaaDxoの場合、AaaDxoImplになります。
-
ルートパッケージ直下の要素
- サブアプリケーションパッケージの中で共通に扱われる要素を個別パッケージとして管理します。
-
dao
- データベースにアクセスするためのインターフェースです。インターフェースにメソッドを書いておくだけで、データアクセスのロジックは、アスペクトが自動生成します。実装部分を作る必要はありません。
- Daoについての詳しい説明はS2Daoをご覧下さい。
- 命名規約は任意のクラス名+Daoとなります。
- □impl
- Daoは通常、実装クラスは必要ありませんが、自動的に変換できないような複雑なロジックは、明示的に実装することもできます。その場合、抽象クラスとし、必要なメソッドだけを実装してください。
- 命名規約は、任意のクラス名+Implとなります。
- 例えば、AaaDaoの実装クラスは、AaaDaoImplになります。
-
logic
- アプリケーションの業務処理を行うインターフェースです。実装クラスはLogic.Implに作成します。
- エンタープライズシステムの場合、Logicは複雑な構成になります。Pageクラスだけで管理出来ない処理やサブアプリケーション共通の処理を、個別パッケージで管理するために使用します。
- 命名規約は、任意の名前+Logicとなります。
- □impl
- Logicの実装クラスです。命名規約はAaaLogicの場合、AaaLogicImplになります。
-
validator
- アプリケーションで入力されるRDBMSへのデータを検証するクラスです。
- JSFのvalidatorと同じものです。独自実装が必要な場合に使用します。
- 命名規約は、任意の名前+Validatorとなります。
-
converter
- データ型の変換フォーマット等、入出力のフィルターを定義するクラスです。JSFのconverterと同じものです。独自実装が必要な場合に使用します。
- 命名規約は、任意の名前+Converterとなります。
-
interceptor
- アスペクトの振る舞いを記述するクラスです。独自のinterceptorを実装する場合に使用します。interceptorについての詳しい説明はS2Aopをご覧下さい。
- 命名規約は、任意の名前+Interceptorとなります。
-
dto
- プレゼンテーションのモデルとしてPageクラスの持つデータを保管して、オブジェクト層との相互変換を行う為のオブジェクトの入れ物です。基本モデルを選択した場合、Dtoは使いませんが、必要に応じて使用することは可能です。
- 命名規約は、任意の名前+Dtoとなります。
-
dxo
- サブアプリケーションの中のDxoとは別に、複数のサブアプリケーションで共通に使われるDxoです。
- 命名規約は、任意の名前+Dxoとなります。
-
helper
- アプリケーションで処理されない追加的な処理の集まりです。instanceメソッドの集まりです。
- 命名規約は、任意の名前+Helperとなります。
- □impl
- helperの実装クラスです。命名規約はAaaHelperの場合、AaaHelperImplになります。
Seasar2.4の開発を支援するためのツールとしてDolteng(どぅるてん)というeclipseプラグインが用意されています。 Doltengにはscaffoldというプロジェクトのテンプレートを作成する機能が実装されています。 これまでに説明しました、Seasar2.4の命名規約に沿ったパッケージ構成はDoltengによって簡単に作成することができます。
次の例では、Doltengのscaffoldを使って生成されたパッケージ構成を元に、CRUDアプリの解説を行います。 今回の例は、Teeda+Daoの構成で作成されています。 Doltengを使えば、データベースのテーブルから、CRUDアプリを自動生成してくれます。
-
命名規約
- サブアプリ名はテーブル名が小文字で入ります。サブアプリ内のクラス名の先頭にはサブアプリ名が入ります。Pageクラス名には、対応するHtmlファイル名が入ります。
-
Htmlファイルについて
A. empList.html
- EMPテーブルの一覧表示をする画面
-
B. empEdit.html
- EMPテーブルのレコード内容を追加、更新、削除を行う画面
-
C. empConfirm.html
- empEditページでレコード内容を変更したときに確認表示をする画面
-
クラスについて
- examples.aaaa.web.empパッケージ
-
A. AbstructEmpPage.java
- EMPテーブルの全カラムをフィールドに持っています。
-
B. EmpListPage.java
- empList.htmlに対応するPageクラス
-
C. EmpEditPage.java
- empEdit.htmlに対応するPageクラス
-
D. EmpConfirmPage.java
- EmpConform.htmlに対応するPageクラス
-
E. EmpDxo.java
- サブアプリケーション(EMP)固有のDxo
- examples.aaaa.webパッケージ
-
AbstractCrudPage.java
- ページにまたがる処理のうち、CRUDタイプの管理を行うクラス
-
CrudType.java
- ページにまたがる処理のうち、CRUDタイプの宣言クラス
- examples.aaaa.daoパッケージ
-
F. EmpDao.java
- EMPテーブルのカラムを関連付けるDaoインターフェース
- examples.aaaa.entityパッケージ
-
F. Emp.java
- EMPテーブルのbean
Seasar2.3ではXmlHellを解消する為の取り組みの一つとしてLessConfigrationに取り組んできました。 その機能として、AutoRegister等の自動登録が代表的なものです。 Seasar2.4では、Convention Over Configurationの考え方により、 LessConfigrationをさらに突き詰めて、設定ファイル自体を書く必要がほとんど無くなりました。
<include>~:~ファイルのインクルードをします
[ diconファイル ]:s2-frameworkのライブラリに同梱されているdiconファイル
app.dicon
(⇒プロジェクト任意の環境設定)
-<include>aop.dicon
-<include>convention.docon
-<include>j2ee.dicon
-<include>dao.dicon
-<include>dxo.dicon
s2container.dicon
(⇒s2containerの環境を読み込む為の設定)
-<include condition=”条件式”>[cooldeploy.dicon]
(⇒COOL deployの設定ファイル)
-<include condition=”条件式”>[hotdeploy.dicon]
(⇒HOT deployの設定ファイル)
-<include condition=”条件式”>[warmdeploy.dicon]
(⇒WARM deployの設定ファイル)
jdbc.dicon
(⇒データベース接続各種設定)
-<include>[j2ee.docon]
-<include>[jbtx.docon]
convention.dicon
(⇒初期設定としてルートパッケージを設定するファイル)
creator.dicon
(⇒初期設定不要)
customizer.dicon
(⇒初期設定不要)
S2.4では命名規約に沿っていれば、 開発当初に(convention.dicon)のrootPackageNameを指定する事とデータベース接続以外に 設定ファイルに追記する作業はありません。
SmartDeployにはデプロイするタイミングによってHOT、COOL、WARMの三種類が用意されています。次にそれぞれの説明をしていきます。
- 概要
-
A. HOT deployの概念
- HOT deployとは、プログラムソースの変更時にアプリケーションサーバーをRebootしなくてもコンポーネントをオンデマンドでデプロイ/リデプロイできる技術です。
-
B. HOT deployのメリット
- webシステムの開発を行う場合に発生するRebootによる無駄な待ち時間が無くなります。ソースの変更がダイレクトに結果として確認できる為、小刻みな反復による修正作業を行うことが出来ます。その結果、品質が向上します。
-
C. 注意点
- HOT deployを使用する為には、パッケージの構成に沿う必要があります。リクエストが来るたびにコンポーネントをコンテナに登録しなおすため、マルチスレッドでの利用は適していません。
- リファレンス
-
A. 作成ファイル
- HOT deployを使用する為には、s2container.dicon(ユーザー任意)にhotdeploy.diconを<include>する必要があります。
-
B. 設定ファイルの説明
- s2container.diconにhotdeploy.diconを<include>します。hotdeploy.diconはS2container内に含まれています。環境による条件付includeを使うと、後に設定ファイルを書き直す必要がなくなります。
-
例)s2container.diconにhotdeployを使う条件を記述します
<components>
<include condition="#ENV == 'ut'" path="hotdeploy.dicon"/>
<include condition="#ENV != 'ut'" path="cooldeploy.dicon"/>
</components>
同じ階層にenv.txtを作成することで,#ENVの値をenv.txt内から取りに行きます。
標準的な環境名としては、次のようなものを用意してありますが、名前は自由に設定することができます。
必ずしもこの環境名に沿う必要はありません。
ut :単体テスト用
ct :結合テスト用
it :総合テスト用
product :本番用
batch :バッチ用
C. 用意されている機能
- コンポーネントは自動で登録されます。
- リクエストが有る度に、コンテナに必要なコンポーネントを登録しなおします。よって、常に以前の登録内容は破棄されることになります。
- 概要
-
A. COOL deployの概念
- COOL deployとは、アプリケーションの起動とともにデプロイを完了する機能です。
-
B. COOL deployのメリット
- 初期化時にすべてのコンポーネントをコンテナに登録するため、初期化後のパフォーマンスが向上します。初期化後のパフォーマンスはSMART deployの中で最速となります。
-
C. 注意点
- COOL deployを使用する為には、パッケージの構成に沿う必要があります。全てのコンポーネントをコンテナに登録するため、登録するClassの数が膨大になると、初期化に必要な時間が長くなります。
- リファレンス
-
A. 作成ファイル
- COOL deployを使うには、s2container.diconにcooldeploy.diconを<include>する必要があります。
-
B. 設定ファイルの説明
- s2container.diconにcooldeploy.diconを<include>します。
- 環境による条件付includeを使うと、後に設定ファイルを書き直す必要がなくなります。
-
例)s2container.diconにcooldeployを使う条件を記述します
<components>
<include condition="#ENV == 'ut'" path="hotdeploy.dicon"/>
<include condition="#ENV != 'ut'" path="cooldeploy.dicon"/>
</components>
env.txtに設定を書き込むことで、環境を操作することができます。
C. 用意されている機能
- コンポーネントは自動で登録されます。
- S2ContainerのInit()のタイミングでコンテナに全てのコンポーネントを登録します。リクエストを受けても登録内容は破棄されません。
- (1) 概要
-
A. WARM deployの概念
- WARM deployは、COOL deployとHOT deployの丁度中間的な特性を持っています。HOT deployの様にオンデマンドでデプロイします。しかし、一度登録したものを破棄しません。登録後はCOOL deployと同じように登録内容を保持します。
-
B. WARM deployのメリット
- 登録するコンポーネントの量が膨大なシステムでCOOL deployを使った場合に発生するデメリット(初期化の時間)を押さえることができます。GUIアプリケーションの起動の場合など、最初から全てのコンポーネントを使う必要がない場合に威力を発揮します。
-
C. 注意点
- WARM deployを使用する為には、パッケージの構成に沿う必要があります。HOT deployの様にソースの変更をダイレクトに反映することは出来ません。
- (2) リファレンス
-
A. 作成ファイル
- WARM deployを使うには、s2container.diconにwarmdeploy.diconを<include>する必要があります。
-
B. 設定ファイルの説明
- s2container.diconにcooldeploy.diconを<include>します。
- 環境による条件付includeを使うと、後に設定ファイルを書き直す必要がなくなります。
-
例)s2container.diconにWARM deployを使用する設定をする
<components>
<include condition="#ENV == 'ut'" path="hotdeploy.dicon"/>
<include condition="#ENV != 'ut'" path="warmdeploy.dicon"/>
</components>
C. 用意されている機能
- コンポーネントは自動で登録されます。
- リクエストが有る度に、コンテナにコンポーネントを登録します。ただし、既に同じコンポーネントが登録されている場合には登録しません。
- 頻繁に Seasar 関連プロダクトを取り上げてくださる MYCOM ジャーナルを参照しています。
- http://journal.mycom.co.jp/articles/2006/11/16/seasar/
サンプルプログラムで作成するファイルは以下の通り
<ソースファイル>
org.example.service <-----------------パッケージ
MessageService.java <-----------------Javaソースファイル
PrintService.java
org.example.service.impl
MessageServiceImpl.java
PrintServiceImpl.java
test
Test.java
<設定ファイル>
convention.dicon
creator.dicon
customizer.dicon
s2container.dicon
app.dicon
上記作成する必要のあるファイルの内、設定ファイルは準備されているものをそのまま使うことが出来る。
MessageServiceImpl.java
package org.example.service.impl;
import org.example.service.MessageService;
public class MessageServiceImpl implements MessageService {
public String getMessage() {
return ("Hello HOT deploy");
}
}
MessageService.java
package org.example.service;
public interface MessageService {
public String getMessage();
}
PrintService.java
package org.example.service;
public interface PrintService {
public void print();
}
PrintServiceImpl.java
package org.example.service.impl;
import org.example.service.MessageService;
import org.example.service.PrintService;
public class PrintServiceImpl implements PrintService {
private MessageService messageService;
public void setMessageService(MessageService messageService) {
this.messageService = messageService;
}
public void print() {
System.out.println(messageService.getMessage());
}
}
Test.java
package test;
import org.example.service.PrintService;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.factory.SingletonS2ContainerFactory;
import org.seasar.framework.container.hotdeploy.HotdeployUtil;
public class Test {
public static void main(String[] args) throws Exception {
SingletonS2ContainerFactory.init();
S2Container container = SingletonS2ContainerFactory.getContainer();
Class.forName(PrintService.class.getName());
for (int i = 0; i < 3; ++i) {
HotdeployUtil.start();
PrintService printer = (PrintService) container
.getComponent("printService");
printer.print();
HotdeployUtil.stop();
}
}
}
- main()メソッドでコンテナを初期化。
- Class.forName()は 無くすとClassCastException が起こります。
- for()ループ内はHOT deployの効果を確認するための処理。
- HotdeployUtil#start() ~ stop() までがHOT deployのコンテキスト。
このコンテキスト内では HotdeployClassLoader がスレッドのコンテキストクラスローダーに設定され、新たなクラスはこのクラスローダーにロードされます。 このクラスローダーは HotdeployUtil#stop() で破棄されます。 次の繰り返しになると、また新たにクラスローダーが作成され、クラスも改めてロードされます。 簡単に言うと、これが HOT deploy の全てです。 Web アプリの場合は HotdeployServletFilter に HotdeployUtil#start() と stop() の役割を受け持ちます。 つまり、一つのリクエストが一つのコンテキストになります。
app.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
</components>
プロジェクト任意の環境を設定する
今回は特に設定する必要は無い。
s2container.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<include path="hotdeploy.dicon"/>
</components>
s2containerの環境を設定するdiconファイル
- S2container内hotdeploy.diconをincludeする。
- ここで SMART deploy を使用するための設定をする。
- (hot,cool,warm)deploy.dicon は s2-framework-2.4.x.jar の中に含まれています。
- 条件インクルードを使うと,env.txt の内容によってSMART deployを切り替えることができます。
convention.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<component class="org.seasar.framework.convention.impl.NamingConventionImpl">
<initMethod name="addRootPackageName">
<arg>"org.example"</arg>
</initMethod>
</component>
</components>
初期設定として、ルートパッケージを設定する。
creator.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<include path="convention.dicon"/>
<include path="customizer.dicon"/>
<component class="org.seasar.framework.container.creator.ServiceCreator"/>
</components>
コンポーネント定義を作成するコンポーネントクリエータを設定する。
今回のサンプルではサービスしか使用しないので,サービス用のクリエータのみを定義しています。
customizer.dicon
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE components PUBLIC "-//SEASAR//DTD S2Container 2.4//EN"
"http://www.seasar.org/dtd/components24.dtd">
<components>
<component
name="serviceCustomizer"
class="org.seasar.framework.container.customizer.CustomizerChain"/>
</components>
コンポーネント定義をカスタマイズする、コンポーネントカスタマイザを設定する。
今回のサンプルではサービスしか使用しないので,サービス用のカスタマイザのみを定義しています。
DEBUG 2006-11-21 17:16:17,050 [main] BEGIN org.example.service.impl.PrintServiceImpl#print()
DEBUG 2006-11-21 17:16:17,050 [main] BEGIN org.example.service.impl.MessageServiceImpl#getMessage()
DEBUG 2006-11-21 17:16:17,050 [main] END org.example.service.impl.MessageServiceImpl#getMessage()
: Hello HOT deploy
Hello HOT deploy
DEBUG 2006-11-21 17:16:17,050 [main] END org.example.service.impl.PrintServiceImpl#print() : null
//・・・for()ループの設定により3回繰り返される
testクラスのfor()ループの中にブレークポイントを仕掛けて、実行途中にMessageServiceImpl.java内のメッセージを変更した場合、 HOT deployによって、その変更が実行結果に反映されることを確認できる。
|