Apache Wicket 6.0.0 をビルドした

Wicket 6 がリリースされてから,jarファイルの配布が無くなった様なので,mvnでビルドしたときの経過をメモ.

追記1(2012-09-10)


@ 先輩からのツッコミ。ありがとうございます。

追記2(2012-09-10)

Wicket-Usersによると、
http://www.apache.org/dyn/closer.cgi/wicket/6.0.0/bin
からもjarファイルがダウンロードできるみたいです。

環境

OSX Lion,Java SE 7u7, maven-3.0.3.

ソースコードのダウンロード

Apache Wicket のダウンロードページから,から apache-wicket-6.0.0.tar.gz をダウンロード.

ビルド

展開して、mvn packeage を実行.

$ tar -xvzf apache-wicket-6.0.0.tar.gz
$ cd apache-wicket-6.0.0
$ mvn package

完了

問題がなければ、各ディレクトリの target 以下にjarファイルがビルドされている。

[INFO] Reactor Summary:
[INFO] 
[INFO] Wicket Parent ..................................... SUCCESS [1.917s]
[INFO] Wicket Util ....................................... SUCCESS [18.271s]
[INFO] Wicket Request .................................... SUCCESS [6.281s]
[INFO] Wicket Core ....................................... SUCCESS [1:55.553s]
[INFO] Wicket ............................................ SUCCESS [0.170s]
[INFO] Wicket Date/Time .................................. SUCCESS [7.543s]
[INFO] Wicket Extensions ................................. SUCCESS [29.266s]
[INFO] Wicket Development Utilities ...................... SUCCESS [6.645s]
[INFO] Wicket IoC common code ............................ SUCCESS [5.244s]
[INFO] Wicket Spring Integration ......................... SUCCESS [6.509s]
[INFO] Wicket Velocity ................................... SUCCESS [4.567s]
[INFO] Wicket Auth Roles ................................. SUCCESS [4.985s]
[INFO] Wicket Guice Integration .......................... SUCCESS [6.018s]
[INFO] Wicket JMX ........................................ SUCCESS [3.359s]
[INFO] Wicket Objects Sizeof Agent ....................... SUCCESS [1.990s]
[INFO] Wicket-Experimental ............................... SUCCESS [0.046s]
[INFO] Wicket-Atmosphere ................................. SUCCESS [7.426s]
[INFO] Wicket Examples ................................... SUCCESS [26.289s]
[INFO] Wicket Native WebSocket Parent .................... SUCCESS [0.035s]
[INFO] Wicket Native WebSocket Core ...................... SUCCESS [6.729s]
[INFO] Wicket Native WebSocket Jetty ..................... SUCCESS [4.653s]
[INFO] Wicket Native WebSocket Tomcat 7.x ................ SUCCESS [4.487s]
[INFO] Wicket Bootstrap .................................. SUCCESS [2.600s]
[INFO] Wicket Examples Parent ............................ SUCCESS [0.034s]
[INFO] Wicket Examples Jar ............................... SUCCESS [4.007s]
[INFO] Wicket Examples War ............................... SUCCESS [0.701s]
[INFO] Wicket Quickstart Archetype ....................... SUCCESS [7.221s]
[INFO] Wicket Common Tests ............................... SUCCESS [0.791s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4:44.009s
[INFO] Finished at: Fri Sep 07 01:41:57 JST 2012
[INFO] Final Memory: 82M/484M
[INFO] ------------------------------------------------------------------------

備考

[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1:16.889s
[INFO] Finished at: Fri Sep 07 01:32:50 JST 2012
[INFO] Final Memory: 26M/102M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-javadoc-plugin:2.8.1:jar (attach-javadocs) on project wicket-util: MavenReportException: Error while creating archive: Unable to find javadoc command: The environment variable JAVA_HOME is not correctly set. -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR] 
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :wicket-util

みたいなエラーが出る場合は、クラスパスにJAVA_HOMEを設定し忘れているので、パスを通して再実行.

$ export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.7.0_07.jdk/Contents/Home"
$ echo $JAVA_HOME
	※パスが通っている事を確認
$ mvn package

Tuning Java SE for Throughput and Latency に参加しました

Tuning Java SE for Throughput and Latency に参加しました。

セミナーは、

Java Performance (Java Series)

Java Performance (Java Series)

を書かれた Charlie Hunt 氏のテキストに基づいて進められました。

要約は toggeterにもまとめられています ので、セミナーの中でチューニング心得として印象に残っている点をピックアップします。

JVMオプションは特性を把握して使う。

JVMのオプションをWeb検索すると、ここ10年弱の間に作られた日本語の記事もたくさん見つかるのですが、過去のJVMを前提に書かれたものや、必ずしも個々の運用環境にマッチするものではないので、鵜呑みしないように注意しましょうということ。

セミナーを受けた上で今まで参考にしたことがあるサイトを見返すと、確かに古いJVMや特定の環境を想定して書かれたままの情報もいくつかありました。例えば、MaxTenuringThresholdとか(OSやJVMのバージョンによって、設定できる値が異なる)、CMSIncrementalModeとか(server(マルチコア)環境には適していない)。

JREJVM)は最新版を使う。

講師の方も会場の反応も、「なかなか難しいよねえ」という反応が印象的でしたが、起動オプションによる挙動や初期値にもデバッグや改善があるので、マイナーバージョンアップであっても(可能なら)しっかりやっておきたい、ということ。

私の職場の環境は極力最新版にしていくルールなので幸せなんですが、そうではない現場も多いのですね。

GCのタイミングの変更も手段の一つとして考える。

CMS-GCを使っていてFullGCが避けられない時は、ヒープメモリ配分だけではなく、GCのタイミングが変更するのも手段の一つとして有効だよ、ということ。

マイナーGCが動作するメモリ利用率の閾値を設定できるオプションがある(例:CMSInitiatingOccupancyFraction)ので、たとえばyoung領域がめいっぱいになる前に早めにGCが走る様に設定するのも効果敵な場合がある。ただしメモリの効率的な利用とはトレードオフになるので、これも実際にチューニングしながら最適な所を見つけていく。

最終手段

ヒャッハッハッ メモリだぁ〜!

ということで、チューニングにも限界はあって、64bit環境にしてヒープ領域もシステム領域もたくさんメモリを確保することも考えましょうということ。

NPE

ぬるぽ

PostgreSQL勉強会@札幌に参加してきた

開催から2週間近くも経ってしまいましたが、PostgreSQL勉強会@札幌に参加させていただきました。

以下、私的まとめ等です。

@syachiさんの「削除フラグのはなし」(スライド

はじめに

論理削除でおこりがちなケースとして……

  • 削除フラグがあるのだから、リレーションは使わない、レコードも消さない。プログラム側で何とかするから、不整合は起こらない!
    • 将来的に、データ構造と蓄積されたレコードの整合性・正当性・有効性が不明瞭になりやすい。
    • データの矛盾や誤データをカバーするためのコードが増えていく。

データベースの基本は「矛盾を排除すること」。データベース側で削除フラグを利用するときに想定されそうな矛盾を極力排除し、付き合いやすいデータベースを維持するためにはどうするか。

生きているレコードは1件のみ。死んだレコードは複数件許可。こんなときは?

ユーザIDなどの本来一意なカラムに対して、有効な削除フラグが1件になるような部分インデックスが有効。

論理削除を伝播させたい時(例:削除されたユーザにひもづくレコードも削除としたい)は?

削除フラグを、bool値ではなく、「キー値が負のもの」などというルールにしてしまう。
削除動作として主キーに-1をかければ、外部キーで関連するものを変更できる。

いっそ削除テーブルに入れてしまいたい時は?

各テーブルのレコードが削除された事をトリガにして、関連するテーブルのレコードを削除テーブルに移動してしまう様なFUNCTIONを用意する。
テーブル名を一貫したルール(delete_xxx)にしておけば、類推も楽。

削除フラグは我々の中でも一番の小物……

業務分析や設計を怠ると、下書きフラグ・一時停止フラグなど、次なる強敵も。

@iakioさんの「XIDを周回させてみよう」(スライド

はじめに
  • PostgreSQLを長く使ってると、データが見えなくなってしまうXIDの周回問題が発生する仕様らしい
    • じゃあ発生する瞬間を見てみよう!
トランザクションIDとは

トランザクションごとに発行されるID。
このIDの大きさで、データベースに要求された各トランザクションの実行順番の整合性管理している。トランザクションIDは各テーブルに Xmin, Xmax という隠し属性的なカラムで管理されていて、SELECT文で閲覧可能。

ある環境化でXmin, Xmaxの値がオーバーラップすると、トランザクションが無効になる≒データが消失する。

PostgreSQLの自衛手段

トランザクションIDの逆転防止の為に、PostgreSQLには自衛手段が組み込まれている。

このため、通常利用などにおいては、周回問題を発生させるのは難しい。(逆に言えば安全)

周回問題を防ぐ為に運用側で意識することは?
  • PostgreSQLの自衛手段が動作するために,VACUUM FREEZEをきちんと行う様にしておくのがベター。

質疑やフリートークで出た話。

  • 論理削除について
    • トリガは多用すると、コストが高かったり、全容を隠蔽してしまう可能性もあるので、ここぞというポイントで利用するのがベターかも。
    • トリガを使ったときのテストには、PG_TAPみたいな応用出来そうなツールもある
    • 削除テーブル方式は、元テーブルのレコード件数も少なく保っておけるので、(生きているデータを相手にするデータアクセスには)より良いかも。
    • 削除テーブルの実現には継承、パフォーマンスの悪化にはWAL無しテーブル(9.1から)っていう方向性もあるよね!
    • 最近はORMで論理削除をサポートしようとする動きも若干ある。(そもそも論理削除は日本ではニーズが高いけど、諸外国はそうでもないらしい)
  • その他
    • みんなデータベースのmigrationってどうやってるんだろう?→ツールやサポートを行うORMが幾つかあるものの、大規模な変更時の物も含めてベターな手段はなかなか難しい模様。
    • Macユーザー多いですね!(林檎マークの背面パネルで埋め尽くされた机を見ながら)
    • 次回は10月頃?

感想

論理削除について。私もプロジェクトのデータベースで論理削除を使っているんですが、削除フラグを伝播しなくても良かったり、矛盾が発生するような要求が(まだ)無いので、比較的救われてるんだなと実感しました。
ただ「削除はされてないけど基本的には不要になったデータ」はどうしても出てしまうわけで、紹介していただいた手法はそういったデータにも使えそう。特に「削除フラグはbool値じゃなくてキー値が負数でも良いよね」っていう考え方は、普段エラーコードなどを使っていながら、目から鱗でした。大変勉強になりました。

周回問題について。PostgreSQLについて検索したときに単語は良く見かけていて、漠然と怖いなーと思っていたんですが、どういう仕組みなのか、現在のPostgreSQLがどういった対策をとっているのかを学べて一歩理解が深まりました。「運用で役に立つかどうかは別として」みたいな前置きもされていましたが、Xidの様な仕組みはアルゴリズム的な視点からも非常に興味深かったです。

時間が押していたので自重してしまったんですが、実は聞いてみたかった(リクエストしたかった)ネタとして、PostgreSQLには、複数のデータベースから固有のテーブルだけをレプリケーションする仕組みってあるのでしょうか。
例えば,Aデータベースからはfooテーブル、Bデータベースからはbar, bazテーブルだけをレプリケーションするCデータベースといった感じのものは実現できるのかなあと。やっぱり同期ツール的なプログラムをアプリケーション側で書くしか無いのでしょうか。

Wicketで新しいウィンドウ(タブ)での表示を抑制するための試行錯誤(中)

どうしても画面を新しいタブ・ウィンドウでの表示を抑制したいというニーズがあり、Wicketで実現可能かどうか、試行錯誤中。

いまのところ、Wicketの複数ウィンドウサポート機能をオンにした上で、ページマップの数や名前でウィンドウ(タブ)をcloseする案をチームで検討していて、一見行けそうな気がしているものの、まだまだ隠れた問題がありそう。

Applicationのinitメソッド

protected void init() {
	super.init();
	getPageSettings().setAutomaticMultiWindowSupport(true);
}

全てのページの親となるWebPageクラス

public class HeaderPage extends WebPage {
	public HeaderPage() {
		// PortalSession.get().getPageMaps().size() > 1 などの条件の方が良い?
		if(getPageMap().getName() < null) {
			/* ウィンドウを閉じる処理や、不要になったPageMapを
         removeする処理をここに書く */
		 }
	}
}

上記のソースで現在の問題点として解っているのは、ModalWindowやPopupWindowの表示も阻害してしまうこと。
ModalWindowやPopupWindowを阻害せずに、意図したURLの新しいタブ・ウィンドウでの表示だけを抑制できる方法は無いものかなあ。

もし、良い意見をお持ちの方がいらっしゃいましたらよろしくお願いします……

Wicket 1.5(rc3) でURLのファイルパスを暗号化する

Wicket 1.4 では、WebApplication クラスのサブクラスで、 newRequestCycleProcessor() メソッドをオーバライドして、

@Override
protected IRequestCycleProcessor newRequestCycleProcessor() {
	return new WebRequestCycleProcessor() {
		@Override
		protected IRequestCodingStrategy newRequestCodingStrategy() {
			return new CryptedUrlWebRequestCodingStrategy(
					new WebRequestCodingStrategy());
		}
	};
}

と書いていたが、Wicket 1.5 では、同じくWebApplication クラスのサブクラスで、init() メソッドの中で、

protected void init() {
	super.init();
	setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));
}

と書く。
詳しくは ここ に記載してある。

Wicket 1.5(rc3) でCSVをダウンロードするLinkコンポーネントを作る

importとコンストラクタは省略している。

public class CSVDownloadLink<T> extends Link<T> {

	@Override
	public final void onClick() {
		//getCsvData()はcsvの内容をString型で取得する。
		String csvData = getCsvData();

		StringResourceStream stream = 
			new StringResourceStream(csvData, "application/octet-stream;");
		stream.setCharset(Charset.forName("Windows-31J"));

		getRequestCycle().replaceAllRequestHandlers(
				new ResourceStreamRequestHandler(stream, "filename.csv");
	}

}

WicketとSessionについてのまとめ

Wicket 1.4.13にアップグレードしてから、StackOverflowError()が頻発する現象が発生。
いろいろ試してみたけれどもどうにも原因がわからず、途方にくれていたところ、id:mdgw 先輩と id:t_yano さんに助けていただきました。
お二方とも、重ね重ねありがとうございました。いつもご助言をいただきまして恐縮です。

ご助言の内容も含めて、簡単にまとめておきたいと思います。

続きを読む