2004-05-16 ダイコン白書
■ [S2]S2Containerのinclude
S2.0.8からネストしたincludeがサポートされなくなりました。
これは、app.diconで個別の定義をincludeし、
個別の定義の中では他の定義をincludeしないという方針のためですが
アナウンスが漏れてました。
申し訳ありません。心より恥じる。
S2TestCaseではapp.diconのかわりに、必要な定義を
個別にincludeするようお願いします。
■ [S2]S2TapestryV1.0.0, S2TapestryExampleV1.0.0リリース
ダウンロードはこちら
http://sourceforge.jp/projects/seasar/files/?release_id=9522#9522
これで、プレゼンテーションフレームワークとの連携も
かなり充実してきました。
次は、S2Daoに取り組みます。
マニュアルはこちら
S2Tapestry
S2Tapestryを使うと、S2とTapestryが簡単に連動するようになります。ページクラスにサービスコンポーネントが自動的に設定されるので、ページクラスの役割は適切なサービスコンポーネントを呼び出すだけになり、プレゼンテーション層とサービス層の役割分担も明確になります。
セットアップ
S2と同様にJDK1.4以上が必要です。サンプルは、Tomcat、Tomcat Plugin、Spindleを使うことを前提にしています。あらかじめインストールして置いてください。S2TapestryVx.x.x.jarを解凍してできたs2tapestryディレクトリをEclipseのJavaプロジェクトとして丸ごとインポートしてください。.classpathを上書きするか聞かれるので、すべてはいのボタンをクリックして、すべてを取り込みます。 これで、私と全く同じ環境になります。サンプルはS2TapestryExamleVx.x.x.jarとして別途用意されているので、ダウンロードして解凍してください。Eclipseでs2tapestry-exampleという名前でJavaプロジェクトを作成します。Tomcatプロジェクトではないので気をつけてください。解凍してできたs2tapestry-exampleディレクトリを丸ごとインポートしてください。.classpathを上書きするか聞かれるので、すべてはいのボタンをクリックして、すべてを取り込みます。s2tapestry-exampleプロジェクトを右クリックしてプロパティ->Tomcatを選びます。Tomcatプロジェクトであるをチェックし、アプリケーションURIを/s2tapestry-exampleとします。これで、Tomcatを再起動して、ブラウザからhttp://localhost:8080/s2tapestry-example/appにアクセスすると足し算のサンプルを見ることができます。
使い方
S2Containerを起動するためにS2ContainerServletをweb.xmlに登録します。。
web.xml
<web-app>
<display-name>s2tapestry-example</display-name>
<servlet>
<servlet-name>s2container</servlet-name>
<servlet-class>org.seasar.framework.container.servlet.S2ContainerServlet</servlet-class>
<load-on-startup/>
</servlet>
<servlet>
<servlet-name>s2tapestry-example</servlet-name>
<servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>s2container</servlet-name>
<url-pattern>/s2container</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>s2tapestry-example</servlet-name>
<url-pattern>/app</url-pattern>
</servlet-mapping>
</web-app>
S2とTapestryを連動させるためには、S2用のEngineをアプリケーション仕様書に登録する必要があります。
s2tapestry-example.application
<application name="s2tapestry-example" engine-class="org.seasar.tapestry.S2Engine" > <page name="Home" specification-path="Home.page"/> </application>
必要なコンポーネントをコンポーネント定義に登録します。ページコンポーネントはTapestryが管理するので、登録する必要はありません。また、この定義ファイルは、アプリケーション全体の定義であるapp.diconに登録する必要があります。
Add.dicon
<components>
<component name="addService" class="examples.tapestry.AddServiceImpl"/>
</components>
app.dicon
<components>
<include path="examples/tapestry/Add.dicon"/>
</components>
サービスコンポーネントを受け取るためにページ仕様にプロパティ仕様を定義します。TapestryからS2のコンポーネントを参照するには、global.コンポーネント名、あるいは名前空間が指定されている場合には、global.名前空間.コンポーネント名で参照します。
Home.page
<page-specification class="examples.tapestry.Home"> <component id="arg1" type="TextField"> <binding name="value" expression="arg1"/> </component>
<component id="arg2" type="TextField"> <binding name="value" expression="arg2"/> </component>
<property-specification name="addService" type="examples.tapestry.AddService">
global.addService </property-specification> </page-specification>
Home.html
<form jwcid="@Form" listener="ognl:listeners.calculate">
<input jwcid="arg1" type="text"/> +
<input jwcid="arg2" type="text"/>
<input type="submit" value="calculate"/>
</form>
Pageクラスはコンポーネントを受け取るためのプロパティを定義しておきます。プレゼンテーション層は、サービス層に処理を依頼し、プレゼンテーション層本来の役割に徹していることが分かると思います。
Home.java
package examples.tapestry; import org.apache.tapestry.IRequestCycle; import org.apache.tapestry.html.BasePage; public class Home extends BasePage { private Integer arg1_; private Integer arg2_; private AddService addService_; public Integer getArg1() { return arg1_; } public void setArg1(Integer arg1) { arg1_ = arg1; } public Integer getArg2() { return arg1_; } public void setArg2(Integer arg2) { arg2_ = arg2; } public AddService getAddService() { return addService_; } public void setAddService(AddService addService) { addService_ = addService; } public void calculate(IRequestCycle cycle) { int result = addService_.add(arg1_.intValue(), arg2_.intValue()); AddResult next = (AddResult) cycle.getPage("AddResult"); next.setResult(new Integer(result)); cycle.activate(next); } }
■ [S2][Spring]Struts対応
springのstruts対応だとactionを管理させたりするみたいだけど、それとは違うんですね。
はてなダイアリー - tpircs(ターンスクリプト)の日記
Springはなぜか直接にはStrutsに対応してないんですよね。
あれだけ、普段つかわねーだろこんなの(失言)ってのを
Fatにサポートしているのに。
http://struts.sourceforge.net/struts-spring/
struts-config.xmlのアクションを専用のアクションに置き換えて、pathをJavaBeanの名前に置き換えて、BeanFactoryから取得してるんですよね。
ちょっと分かりづらい。
S2Strutsはここ
■ [ダイコン]アーキテクチャ
ダイコン時代のアーキテクチャは次のようになると思っています。
- UI層、サービス層、永続化層、エンティティ層(ドメインオブジェクト)で構成される。
- UI層はUIのフレームワーク(Struts, Tapestry等)に依存する。
- 永続化層の実装はO/Rマッピングのフレームワーク(Hibernate等)に依存する。しかし、永続化層の仕様(interface)は特定のフレームワークに依存してはいけない。JDBC等のAPIも永続化層以外で用いるべきではない。
- サービス層、エンティティ層は特定のAPI(フレームワーク)に依存しないPOJOである。
- サービス層、永続化層は仕様(interface)と実装が明確に分離され、利用者側は仕様だけを知っていれば良い。
- UI層はサービス層とエンティティ層だけに依存する。サービス層は永続化層とエンティティ層だけに依存する。永続化層はエンティティ層だけに依存する。UI層、サービス層、永続化層をエンティティ層のオブジェクトが流れることによって情報が伝達される。
- UI層は必要があれば状態を持つ。サービス層、永続化層は状態を持たない。エンティティ層は状態そのものである。
- サービス層、永続化層はダイコンで管理される。UI層はダイコンで管理される場合(StrutsのAction)もあれば、そうでない場合(Tapestry)もある。どちらにせよ、サービス層との依存関係はダイコンに依存せずに解決されなければならない。
- トランザクション、リモート呼び出し、セキュリティはサービス層で解決される。しかし、サービス層のコンポーネントがそれを意識することはない。AOPによって透過的に処理される。
# n-t 『エンタープライズアプリケーションの分野に関していえば、おおいにagreeです。あとは、サービス層でトランザクションやセキュリティは実現されるが、サービス層のPOJOがそれを意識することはない。を追加きぼん。』
# ozacc 『Springは1.0.1からStrutsをサポートしてます(struts-springを取り入れたような形)。確かにちょっと分かりにくいですが、個人的にはSpringのやり方の方が好みです。というのも、パスに対するActionクラスをSpringの定義ファイルを変えるだけで変更できるので。S2Strutsの場合は、struts-config.xmlとcomponent定義の両方を変えなければいけませんよね? Spring 1.0.2では、struts-config.xmlで専用のアクションを指定しなくてもいいようなRequestProcessorが付属するようです。』
# higayasuo 『Actionを変えることはあまりないきがしますが、Springの良いところは学んで、使う側が最も使いやすいものを提供したいと思います。』