[S2Dao] 1.0.43の大きな変更点

今回のリリースから検索処理の戻り値にBeanアノテーションに指定したクラス以外のDTOやMapの利用が可能になっております。詳細は、以下のドキュメントをご覧ください。

http://s2dao.seasar.org/ja/s2dao.html#DefMethod

また、SQLファイルのファイル名が間違っていても気が付きにくいという問題に対応するため、SQL_FILEアノテーションが追加されました。このアノテーションを指定すると、命名規則に従ったSQLファイルが存在しない時に例外がスローされます。詳細は、以下のドキュメントをご覧ください。

http://s2dao.seasar.org/ja/s2dao.html#SqlFileAnnotation

[S2Dao] S2Dao 1.0.43リリース

S2Dao 1.0.43をリリースしました。

http://s2dao.seasar.org/ja/

S2Dao 1.0.42からの変更点は、以下の通りです。

Bug
  • PagerS2DaoInterceptorWrapperでpushに失敗した場合でもpopされてしまう問題に対応しました。[DAO-61][Seasar-user:5851]
New Feature
Improvement
  • select系の戻り値で複数のDTO、Mapをサポートしました。[DAO-91][DAO-92]
  • SqlFileアノテーションを導入し、SQLファイル名が誤っている場合に早期検出できるようにしました。[DAO-90]
  • S2PagerのgetCountメソッドで、order by句を削除して実行可能にしました。[DAO-88][Seasar-user:7549]
  • DBを特定する処理を改善し、DatabaseMetaData#getDatabaseProductName()が"DB2"ではじまっていればDB2と判定するようにしました。[DAO-85]
  • Tableに関連付いていないEntityでINSERTした際のエラーメッセージをわかりやすくしました。[DAO-89]

Seasar2のAOPを使ったときのデバッグで疑問

 AOPを使ったコードをステップ実行する場合、ステップインでエンハンスされたコード(クラス名に$$とかついたやつ)の中に入ってしまうため、どうしても迷子になった感じがしてしまいます。ブレイクポイントもエンハンスされたクラスでは効かない(ことが多い?)みたいですし。

 私の場合、とりあえずデバッグパースペクティブの左上のところ(コールスタック?)を見ながら、頭の中でエンハンスされたクラスをイメージして元々のコードまでたどり着くようにしていますが、これってもっと効率的なほうほうってないのでしょうか? この辺が解決できないと自分で使うだけならともかく、プロジェクトで大人数で使うのって、ちょっと不安です。

 というわけで、どなたか良いアイディアがあったら教えてください!

[Seasar][DBFlute] DBFluteで複数データベース接続

 複数のデータベース(あるいはユーザ)がある状態で、それぞれを使いたいときはDBFluteの設定を2つ作って、パッケージを分ければいけそうです。ただ、データソースを使い分けるために、jdbc.diconを2つ作って使い分けるのですが、現状のDBFluteの機能ではj2ee.diconよりも前にincludeを追加する方法がないっぽいですね。これだけ対応していただければ複数データベースを1度に使うのも、お手軽に出来そうです。

 そんなわけで、データソースを使い分けるとき用にj2ee.diconよりも前の行にincludeを出力するための設定をpropertiesファイルで指定できる用にしていただけないでしょうか。

 それにしても、単一データベースで複数ユーザが存在し、それぞれがテーブルを持っているときには、接続用のユーザに色々と他のユーザのテーブルがいじれるように権限を渡していじれるようにするのと、接続ユーザ自体を切り替えてテーブル毎のオーナーで操作するようにするのと、どっちが一般的なのでしょうね。個人的には、オーナーでやったほうがシンプルな気はするのですが。

あれ? 同じデータベースに複数のユーザでログインしたら、それってXAが必要になるのかな???

HOT deployのS2StrutsとDBFluteでエラー(泣)

 原因が全然分からないのですが、DBFluteで生成したコードがある状態で、S2StrutsをHOT deployで動かすとTomcatの起動時にエラーが出て動かないのです。詳細な環境は、以下の通り。

で、発生するエラーは以下のような感じです。ここでは、packageがSMART deployのルートパッケージです。

ERROR 2007-02-04 19:33:29,671 [main] Unable to initialize Struts ActionServlet due to an unexpected exception or error thrown, so marking the servlet as unavailable.  Most likely, this is due to an incorrect or missing library dependency.
java.lang.LinkageError: Class package/db/allcommon/cbean/sqlclause/OrderByClause violates loader constraints
	at java.lang.ClassLoader.defineClass1(Native Method)
	at java.lang.ClassLoader.defineClass(ClassLoader.java:620)
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124)
	at org.apache.catalina.loader.WebappClassLoader.findClassInternal(WebappClassLoader.java:1786)
	at org.apache.catalina.loader.WebappClassLoader.findClass(WebappClassLoader.java:1048)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1506)
	at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1385)
	at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
	at java.lang.Class.getDeclaredMethods0(Native Method)
	at java.lang.Class.privateGetDeclaredMethods(Class.java:2365)
	at java.lang.Class.privateGetPublicMethods(Class.java:2488)
	at java.lang.Class.getMethods(Class.java:1406)
	at org.seasar.framework.beans.impl.BeanDescImpl.setupPropertyDescs(BeanDescImpl.java:517)
	at org.seasar.framework.beans.impl.BeanDescImpl.<init>(BeanDescImpl.java:102)
	at org.seasar.framework.beans.factory.BeanDescFactory.getBeanDesc(BeanDescFactory.java:51)
	at org.seasar.struts.lessconfig.factory.ConstantStrutsConfigAnnotationHandler.createStrutsActionFormConfig(ConstantStrutsConfigAnnotationHandler.java:201)
	at org.seasar.struts.lessconfig.autoregister.ClassComparator.compare(ClassComparator.java:36)
	at java.util.Arrays.mergeSort(Arrays.java:1284)
	at java.util.Arrays.mergeSort(Arrays.java:1295)
	at java.util.Arrays.mergeSort(Arrays.java:1296)
	at java.util.Arrays.mergeSort(Arrays.java:1295)
	at java.util.Arrays.mergeSort(Arrays.java:1295)
	at java.util.Arrays.mergeSort(Arrays.java:1295)
	at java.util.Arrays.sort(Arrays.java:1223)
	at org.seasar.struts.lessconfig.autoregister.ClassComparator.sort(ClassComparator.java:57)
	at org.seasar.struts.lessconfig.autoregister.impl.StrutsConfigRegisterImpl.register(StrutsConfigRegisterImpl.java:73)
	at org.seasar.struts.lessconfig.plugin.AutoStrutsConfigRegisterPlugIn.register(AutoStrutsConfigRegisterPlugIn.java:101)
	at org.seasar.struts.lessconfig.plugin.AutoStrutsConfigRegisterPlugIn.init(AutoStrutsConfigRegisterPlugIn.java:80)
	at org.apache.struts.action.ActionServlet.initModulePlugIns(ActionServlet.java:884)
	at org.apache.struts.action.ActionServlet.init(ActionServlet.java:356)
	at javax.servlet.GenericServlet.init(GenericServlet.java:212)
	at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:879)
	at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:767)
	at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3483)
	at org.apache.catalina.core.StandardContext.start(StandardContext.java:3709)
	at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:776)
	at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:759)
	at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:537)
	at org.apache.catalina.core.StandardHostDeployer.addChild(StandardHostDeployer.java:662)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils.java:216)
	at org.apache.commons.digester.SetNextRule.end(SetNextRule.java:216)
	at org.apache.commons.digester.Rule.end(Rule.java:230)
	at org.apache.commons.digester.Digester.endElement(Digester.java:1130)
	at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl$FragmentContentDispatcher.dispatch(Unknown Source)
	at org.apache.xerces.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XML11Configuration.parse(Unknown Source)
	at org.apache.xerces.parsers.XMLParser.parse(Unknown Source)
	at org.apache.xerces.parsers.AbstractSAXParser.parse(Unknown Source)
	at org.apache.xerces.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
	at org.apache.commons.digester.Digester.parse(Digester.java:1666)
	at org.apache.catalina.core.StandardHostDeployer.install(StandardHostDeployer.java:338)
	at org.apache.catalina.core.StandardHost.install(StandardHost.java:761)
	at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:438)
	at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:372)
	at org.apache.catalina.startup.HostConfig.start(HostConfig.java:784)
	at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:330)
	at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1155)
	at org.apache.catalina.core.StandardHost.start(StandardHost.java:696)
	at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1147)
	at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:310)
	at org.apache.catalina.core.StandardService.start(StandardService.java:449)
	at org.apache.catalina.core.StandardServer.start(StandardServer.java:2212)
	at org.apache.catalina.startup.Catalina.start(Catalina.java:458)
	at org.apache.catalina.startup.Catalina.execute(Catalina.java:345)
	at org.apache.catalina.startup.Catalina.process(Catalina.java:129)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:150)

COOL deployだとエラー出ませんし、DBFluteのdiconファイルを読み込まなければ、やっぱりエラー出ないので、クラスローダがらみの『混ぜるな、キケン!』なのは、何となく予想がつきますが。

はたして、どう対処したらいいんだろう。DBFlute用のcreatorでも作るしかないのでしょうか。。。

2007/02/05追記:
解決しました。コメントでkoichikさんに教えて頂いたのを元に試しにconvention.diconのルートパッケージを変更してみたところ、エラーが出なくなるのを確認しました。

というわけで、私の中ではトラブルを避けるためにルートパッケージ配下にはSMART deployに関係ないファイルを含めないようにすることにしました。

std-customizer.diconのdxoCustomizer

 Seasar2 2.4.6で追加されたstd-customizer.diconですが、dxoCustomizerの定義が問題のような気がします。いつも通り、私の勘違いの可能性もありますが。。。

 Doltengを使ってTeeda+S2Daoのプロジェクトを新規作成し、customizer.diconをSVN上の最新のもので上書きします。そして、コメントアウトされているdxoCustomizerの定義を有効にして、適当なDxoインターフェースを作って実行すると、スタックオーバーフローします。

 見た感じ、CustomizerChainに同じCustomizerChainが登録されているように見えます。dxo.intercepterのカスタマイザとカスタマイザチェインが同じ名前なのが問題のような気がします。ためしに、std-customizer.diconからDxoコンポーネント定義をcustomizer.diconにコピーしてきて、名称をかぶらないように修正すると正常に動作しました。本当に試すにはjarの中のstd-customizer.diconを書き換えるべきなのですが、ちょっと手が回っていません。。。

 最後に、実際に発生した例外のスタックトレースを張っておきます。id:koichikさん、私の勘違いでしょうか?(^^;

java.lang.StackOverflowError
	java.lang.Exception.<init>(Exception.java:29)
	java.io.IOException.<init>(IOException.java:28)
	ognl.JavaCharStream.FillBuff(JavaCharStream.java:139)
	ognl.JavaCharStream.ReadByte(JavaCharStream.java:163)
	ognl.JavaCharStream.readChar(JavaCharStream.java:264)
	ognl.OgnlParserTokenManager.jjMoveNfa_0(OgnlParserTokenManager.java:907)
	ognl.OgnlParserTokenManager.jjStartNfa_0(OgnlParserTokenManager.java:181)
	ognl.OgnlParserTokenManager.jjMoveStringLiteralDfa2_0(OgnlParserTokenManager.java:440)
	ognl.OgnlParserTokenManager.jjMoveStringLiteralDfa1_0(OgnlParserTokenManager.java:352)
	ognl.OgnlParserTokenManager.jjMoveStringLiteralDfa0_0(OgnlParserTokenManager.java:278)
	ognl.OgnlParserTokenManager.getNextToken(OgnlParserTokenManager.java:1494)
	ognl.OgnlParser.jj_ntk(OgnlParser.java:3079)
	ognl.OgnlParser.navigationChain(OgnlParser.java:1266)
	ognl.OgnlParser.unaryExpression(OgnlParser.java:1198)
	ognl.OgnlParser.multiplicativeExpression(OgnlParser.java:973)
	ognl.OgnlParser.additiveExpression(OgnlParser.java:896)
	ognl.OgnlParser.shiftExpression(OgnlParser.java:752)
	ognl.OgnlParser.relationalExpression(OgnlParser.java:510)
	ognl.OgnlParser.equalityExpression(OgnlParser.java:407)
	ognl.OgnlParser.andExpression(OgnlParser.java:354)
	ognl.OgnlParser.exclusiveOrExpression(OgnlParser.java:301)
	ognl.OgnlParser.inclusiveOrExpression(OgnlParser.java:248)
	ognl.OgnlParser.logicalAndExpression(OgnlParser.java:195)
	ognl.OgnlParser.logicalOrExpression(OgnlParser.java:142)
	ognl.OgnlParser.conditionalTestExpression(OgnlParser.java:103)
	ognl.OgnlParser.assignmentExpression(OgnlParser.java:66)
	ognl.OgnlParser.expression(OgnlParser.java:25)
	ognl.OgnlParser.topLevelExpression(OgnlParser.java:17)
	ognl.Ognl.parseExpression(Ognl.java:113)
	org.seasar.framework.util.OgnlUtil.parseExpression(OgnlUtil.java:73)
	org.seasar.framework.container.ognl.OgnlExpression.<init>(OgnlExpression.java:42)
	org.seasar.framework.container.ognl.OgnlExpression.<init>(OgnlExpression.java:34)
	org.seasar.framework.container.factory.AspectDefFactory.createAspectDef(AspectDefFactory.java:43)
	org.seasar.framework.container.factory.AspectDefFactory.createAspectDef(AspectDefFactory.java:50)
	org.seasar.framework.container.customizer.AspectCustomizer.customize(AspectCustomizer.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)
	org.seasar.framework.container.customizer.CustomizerChain.customize(CustomizerChain.java:51)

(以下、延々と同じ。。。)

Seasar Conference 2006 Autumnに行ってきました。

 春のカンファレンスには参加できず、Seasarのイベントは久しぶりに行ってきました。以下、自分が参加したセッションについて忘れる前にメモしてみます。

Seasar 2.4

 まずは定番のSeasar2本体のセッションです。実は、個人的には余りサプライズがありませんでした(^^; 一応、ちょくちょく2.4周りを追っていたので、把握している範囲のお話でしたので。

 ただ、やっぱり3分でマスタメンテ系の画面が作れるというのは面白いですね。実際、セッション中では2分ちょっとで作成完了していました。ちょっと気になったのは、会場の反応がなぜか薄かったこと。これは、ひがさんも寂しかったのではないでしょうか(T−T)

 HOT deployやDoltengて、実際に使った方が感動が大きいと思うのですよね。なので、もし今日のセッションをご覧になった方で、今ひとつ良さが分からなかったという方は、是非ご自分で手を動かして頂きたいと思います。

DI時代のTDD入門

 TDDのテストは、品質保証のためのテストではないというのに、なるほどって思いました。私はTDDの開発なんて全くやったこと無いのですが、和田さんの説明は、すごく納得できました。

 Eclipseのショートカットについても、知らない物をいっぱい紹介して頂き、これは開発効率が上がりそうだと思いましたね。ちょっと自分でも調べてみたいという気になりました。もう、見ているだけで「出来る開発者」って感じになれそうな気が、すごくしてきました。

 ん?、こう書くと和田さんがすごくないって書いてるみたいですが、決してそんなことはないです。というか、今日聞いた中では、和田さんのプレゼンが一番面白くて、時間が経つのを忘れてしまいました。

商用製品から生まれたOSSフレームワークとimOSSC

 今日私が聞いたのセッションの中では、ちょっと異色の存在でした。たぶん、あの1トラック全体が、そういう雰囲気だったのだと思いますが。商用製品のオープンソース化って海外ではIBMWebLogicがやっているので有名ですが、日本では珍しいですよね。

 説明本編ではプロダクトの紹介だけでしたが、余った時間に栗原さん、羽生さんが乱入して行われたディスカッション形式のやりとりを通じて、寄贈した企業とコミュニティとの双方にメリットのある関係だということがよく分かりました。

 今まで、あの手の寄贈って大きな企業がコミュニティの開発力を利用しているというイメージだったのですが、今日のセッションで、そのイメージは払拭されました。今後は、狙った効果がしっかり出て、後に続く企業、コミュニティが増えることに期待します。

GUIアプリケーション開発フレームワークS2JFace」-なぜ、あなたはWebアプリケーションを作り続けるのか-

 個人的に、結構気になるテーマです。2年ほど前からWebアプリケーションにこだわるのをやめたいと思っていましたが決定的な代替策が打ち出せず、ずるずると来ているというのが私の実感です。

 S2JFaceは、JavaGUIを簡単に作るためのフレームワークを目指しているようですね。画面定義がXMLなのは、ステキです。ソースコード管理に組み込みやすいですし、一括置換とかも必要なら出来そうです。

 まだ未完成のプロダクトですが、今から今後が非常に楽しみです。私はWebアプリケーション嫌いでC/S大好きなので、是非とも頑張って頂きたいと思います。やっぱり、社内業務システムくらい、ユーザに使いやすいインタフェースを提供したいじゃないですか。

パネルディスカッション

 モデレータに栗原さん、パネラーにひがさん、和田さん、Tuigwaaの西岡さんという構成で、ビール片手にラフな感じで行われました。栗原さんのツッコミが面白かったです。

懇親会

 部屋の片隅でJavadocチームで固まってました(^^; ふたがわさんとお話できて良かったです。とってもやさしそうな方でした。サーバ管理は大変だと思いますが、これからもよろしくお願いいたします。

まとめ

 本当は2次会(3次会?)もあったようなのですが、ちょっと用事があったので渋々帰ってきました。イベント全体の感想としては、大きくなったなぁというところでしょうか。何となく、もうちょっとこぢんまりとしたイベントも、いろんな人と話ができていいのかもしれないなと思ってしまいました。