2007-05-30

すぐに始める Struts2 (Spring編)

前回の続き。
(Struts2単独のクイックスタートについては前回のエントリを参照のこと)

Struts2はSpringプラグインを使用することで Spring Framework 2.0と協調して動作できる。Springプラグインがクラスパスに追加されると、Struts2はアクションクラスのオブジェクトをインスタンス化するとき、そのファクトリとして Springの WebApplicationContextを使用するようになる。

これにより Struts2のアクションクラスは Springの管理下に置かれ、Springの作法で組み立てられたコンポーネントセットを利用できる。

/WEB-INF/libに入れるもの

struts2-spring-plugin-2.0.6.jar
spring.jar
cglib-nodep-2.1_3.jar

/WEB-INF/web.xmlに書くこと

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
</listener-class>
</listener>

Spring用のBean定義ファイル

/WEB-INF/applicationContext.xmlとして作成する。

アクションクラスを Springに登録

(追記:実はアクションクラスの定義は必ずしも applicationContext.xmlに書かなくても良いことが後に判明、ただし依存関係の構築をautowireに頼らず明示的に行いたければ書く必要がある)

applicationContext.xmlの中で、アクションクラスを bean定義すれば良い。
前回の例で使ったアクションクラスを例に取ると下記のようになる。
<bean class="your.action.package.here.SimpleAction" scope="request">
<!-- この中で好きにDependency Injectionを行う -->
</bean>
このように書けばアクションクラスと Beanはクラス名でマッチング(autowire)されるようだ。なおアクションクラスのスコープには request(Spring2.0から導入された新スコープ)を指定しておくこと。Springではscope指定を省略すると singletonになるため、忘れるとひどい問題を引き起こすだろう。

(追記:アクションクラスの定義を applicationContext.xmlに書かなかった場合、依存性注入はプロパティ名とbean idの一致により自動的に行われるようだ)

関係するBeanについての注意

(追記:アクションクラスの定義をapplicationContext.xmlに書かずに autowireに任せた場合は、自動的に不思議な力が働くようで、このことは気にしなくても良いようだ)

アクションクラスへ注入して使う他のBeanに requestや sessionといった Web特有のスコープを適用したい場合、そのままscope属性をつけるだけでは実行時にスレッドが関連づけられていないといった趣旨のエラーが発生しまう。そのようなBeanに対しては <aop:scoped-proxy/> を埋め込んでやればAOPの力で問題が解決される。詳しくはScoped beans as dependenciesを参照のこと。

最後に

お気づきかも知れないが、ここまで来てもまだ struts.xmlなしで動作する。
あと、アクションクラス内で xworkの Injectアノテーションを使って Spring管理下のBeanを注入できないかと思いやってみたのだが出来なかった。これが出来るといちいち applicationContext.xml内にアクションクラスをBean定義しなくても良いと思うのだが。

すぐに始める Struts2

これは、Struts2を動かす最短の動作をメモしたもの。
スターターパッケージのようなものを使わず、最小限の構成を手で作ることによってStruts2を理解することを目標にしている。
Struts2の設定は CLASSPATH上のstruts.xmlに書くことになっているが、下記の例では無くても一応動作する。
物事の関連がわかりやすいよう、各所に色を付けておいた。

/WEB-INF/libに入れるもの

freemarker-2.3.8.jar
ognl-2.6.11.jar
struts2-core-2.0.6.jar
xwork-2.0.1.jar

/WEB-INF/web.xmlに書くこと

<filter>
<filter-name>struts</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
<init-param>
<param-name>actionPackages</param-name>
<param-value>your.action.package.here</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>struts</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

作るクラス

/WEB-INF/classes/your/action/package/here/SimpleAction.class

(ソース)
package your.action.package.here;

import org.apache.struts2.config.Result;
import org.apache.struts2.config.Results;

@Results({
@Result(name="success",value="simple.jsp"),
})
public class SimpleAction {
private String myProperty = "My Property String";
public String getMyProperty()
{
return myProperty;
}
public String execute() throws Exception
{
return "success";
}
}

作るJSPファイル

/simple.jsp

(ソース)
<%@ taglib prefix="s" uri="/struts-tags" %>
<html>
<body>
<h1>Simple</h1>
<s:property value="myProperty" />
</body>
</html>

コールするURL

http://yourhost:port/appname/simple.action

表示されるHTML

<html>
<body>
<h1>Simple</h1>
My Property String
</body>
</html>

解説

struts2はサーブレットフィルタとして動作する。フィルタのinit-paramに actionPackagesというパラメータをセットすると、そこで指定されたパッケージ以下にある *Action.classを探し出して全てをアクションクラスとして登録してくれる(*の部分がアクション名になる)。これは「設定より規約」のムーブメントを意識した機能だと思われるが、現在の所Experimentalな機能という扱いのようだ。

Struts2のアクションクラスは何らかの基底クラスを継承することを義務づけられていない(が、ActionSupportなどのサポートクラスを継承しても良い)。Struts2は、アクションに対応するURLがリクエストされるとアクションクラスをインスタンス化し、setterメソッドを使用して入力パラメータをセットしたのちに execute()メソッドをコールする。Spring-MVCのControllerクラスは基本的にシングルトンで、パラメータは関連づけられたCommandクラスのオブジェクトによって渡されるのに対し、Struts2ではアクションクラスのオブジェクトがリクエスト毎に Instantiateされるため、いわゆるフォームBeanの役割を兼ねることが出来る。(このあたりのモデルはS2Strutsに近い、どちらが先なのかは知らないが)

execute()メソッドの返す結果文字列に対応するビューの名前は Resultアノテーションを使ってセット出来る。従来なら外部の設定ファイルで別に定義されていたものが、Struts2ではソースコードの中に統合できることになる。アクションクラスのモジュール独立性を考慮するならこれは無条件に賛成を得られる方式ではないが、どうせWebアプリケーションのControllerなど作り捨てで再利用などしようはずもないという現実主義に基づくのであれば有用である。
(誤解のないように言っておくと、ここではControllerとModelを的確に分離するように設計ができていることが前提になっているのであって、コンポーネントの再利用自体を諦めているわけではない)

JSPファイル中では /struts-tags タグライブラリを用いることでコントローラ(アクション)オブジェクトの持つプロパティにアクセスすることが出来る。

ラベル:

2007-05-29

玄人志向 GbE-PCI2

Xen 3.0.2で Intel PRO/1000の動作がおかしい件の続報。

Xen 3.0.4に更新しても直らず。別のマシンでは同じ組み合わせで特に問題ないので、ハードの故障も考えたのだが、同じハードを買ってきて問題が解消しなかったらあまりにも空しいので別の GbE NICを買ってくることにした。

とはいえ、Linuxで安定動作する GbE NICなど Intel以外にあったろうか。Realtek RTL8169あたりは枯れているのだろうが、過去に性能を計測してみたらそれはひどいものだった記憶があり(今は改善されているのかもしれないが)手出しする気にならない。

調べていたら、VIA VT6122なるチップを搭載した玄人志向の GbE-PCI2という NICが価格の割に高性能とのことで好評らしいので買ってきた。

ドライバは via-velocity で、今のところ特に問題なく使用できている。性能評価はまだだが、噂通りにそこそこ良いのであれば価格が PRO/1000の 1/6〜1/7ということを考えてかなり強力なオルタナティブといえよう。

不思議なのは、玄人志向以外のメーカーがこのチップを採用したNICを発売していないこと。Realtekよりチップ単価が高いのだろうか。

2007-05-27

はぶられたか、Gentoo(Xen 3.0.4)

Xen 3.0.2→3.0.4への移行をやったときに、network-bridgeスクリプトがそのままでは正常に動かないためやむを得ず 3.0.2のものをコピーして使っていたのだが、もっとよく調べてみた。

手がかりになったのは、下記ファイルにおける Xen3.0.2から3.0.4への差分。
/etc/xen/scripts/xen-network-common.sh

旧バージョンでは、ifup/ifdownコマンドを持たないGentooのために、/etc/init.d/net.* start/stopを呼び出すようなifdown/ifupへのブリッジとなるシェル関数が書かれていたのに対し、新しいバージョンではさっくり消されていた。

Xen-develメーリングリストをちらっと確認したところ、どうやらそういう個別対応はしない方針でスクリプト類をクリーンナップした模様。こういった類の問題に対しては ebuildによるパッチで対応してくれることを期待していたのだが、そうはなっていないみたいだ。

私は xen-network-common.shを一部旧バージョンの内容に書き換えることで対応したが、/sbin/ifupと /sbin/ifdownを手で作るという方法の方がスマートかもしれない。

ラベル: ,

MTUを4だけ減らせ

仮想マシンを使って仕事をしていると、ネットワークセグメントも色々分けたくなる。
一台の実機で動作させているうちはダミーインターフェイスを使って分ければいいのだが、実機が複数台あって相互に通信したい場合はそうもいかない。かといって作りたいセグメントごとにイーサネットアダプタを差すのでは不経済すぎる。
しょうがないのでタグVLAN(802.1Q)について色々調べている今日この頃。

Linuxで802.1Qを使うには(既に組み込まれてなければ)カーネルにそれを組み込んで、vconfigというユーティリティをインストールする。また、Gentooの場合 /etc/conf.d/net の中でVLAN設定を書けるので自分で直接 vconfigを呼ぶ必要はないようだ。

下記はvconfigをemergeしたときに現れたメッセージ(当然元は英語)。
「多くのイーサネットドライバにはMTU問題があります。回避するにはをMTU1496に減らしてください」

タグで4オクテット増える分MTUを減らしておかないとダメなドライバがあるってことのようで。
今もそんなドライバがあるということだろうか。このメッセージがいつ書かれたのか気になる。

結局VLANで作ったインターフェイスをXenで使えるかどうかというところについては、Xenのnetwork-bridgeスクリプトが VLANを考慮していないためそのままではだめなようである。

2007-05-26

Xen 3.0.2 dom0 e1000 problem

Xen3.0.2で動作させているホストのメモリを4GBに増設したら、なんだか通信が不安定に。

e1000_clean_tx_irq: Detected Tx Unit Hang

Xenのせいか e1000ドライバのせいかメモリのせいか板のせいか。

同じエラーに対し、ethtool -K ethX tso off で解決するといった過去事例はあったようだが(Xenと関係なく)、どうやらそれでもないっぽい。別の時期にXenのメーリングリストでもこのエラーが報告されているので、Xenの絡んだ別の問題と思われる。

ラベル:

2007-05-14

XenのFullvirtualizationとAcronis True Image

パラバーチャリゼーション(準仮想化)と比べてフルバーチャリゼーション(完全仮想化, HVM)は VMWareや VirtualPCのようにハードウェアを完全に仮想化できるため WindowsなどをゲストOSとして利用できるのが利点だが、完全仮想のドメインUに割り当てられたブロックデバイスはパーティションではなく一台の仮想ハードディスクになってしまう(ハードウェアを完全に仮想化するわけだから当然)ので、これだとそう簡単にサイズの拡張ができない。
いっぽう準仮想化の場合はパーティション単位での割当が出来るため、lvextendで論理ボリュームのリサイズをして xfs_growfsするといった短い操作で拡張が出来るという利点があるのだ。しかも運が良ければ無停止で。


少しのお金で解決できる問題なら支払って楽をしよう。というわけで、Acronis TrueImageというソフトを購入し HVM Domainで使ってみた。このソフトを使えば、小さいハードディスクから大きいハードディスクへ(又はその逆)OS環境をまるごとコピーすることが出来る。無停止でのマイグレーションというわけにはいかないが、容量拡張のソリューションとして実マシン・仮想マシン問わず役に立つ一品である。

このソフトはブータブルCDで提供されているので、ディスクイメージを作ってドメインUに対してCD-ROMとして割り当ててやれば仮想マシン上で動かすことが出来る。

画面は、仮想ハードディスクにインストールされた Windows 2000をAcronis TrueImageで別の仮想ハードディスクにコピーしている図(この例では拡張ではなく縮小をしている)。
これで Windows系の OSも気軽に Xenでまずは小さくセットアップして、必要に応じて容量を拡張するという柔軟な運用が可能になるのだった。


おまけ:仮想マシン上にインストールした Windows2000で CrystalMarkの HDDベンチマークを実行してみた図。なんかメーター振り切ってます。実機はAthlon64X2 5200+, Gentoo Linux, HighPoint RocketRAID2322でRAID5の8台構成。

ラベル:

2007-05-13

Xen 3.0.4と via_rhine

Xenを3.0.2から3.0.4へアップグレードしたら、なぜか VIAのRhineチップを使ったNICにブリッジを設定するとハングするようになった。
いろいろやってみたら、いつのまにか直ったのだがいまいち釈然とせず。
カーネル設定で、"VIA Rghine support"→"Use MMIO instead of PIO(CONFIG_VIA_RHINE_MMIO)"をYにしたから直ったのかな。

ラベル:

2007-05-07

Xen 3.0.2→3.0.4

Portageの Xenが 3.0.2から 3.0.4になっていたので入れ替えてみた。
今まであきらめていた HVM Domainが動く。

以前に書いた「Xenで複数のネットワークインターフェイスを domUに提供する」で作成したスクリプトを使用するためには、network-bridgeスクリプトを 3.0.2のものに置き換える必要があった。なんでだろう。

メモ。HVM DomainのVNCで他のホストから接続できるようにするには、xend-config.sxpの
(vnc-listen '127.0.0.1')
というところを
(vnc-listen '0.0.0.0')
にする。

ラベル: