DiAndAopOnSeasar2
寺島と申します。 artonさんの 「Seasar2で学ぶ DIとAOP アスペクト指向によるJava開発」 を購入して勉強しています。 ここで、データベースをhsqldbからNetBeans内蔵のderbyに切り替えられないかと試行していますが、エラーが出ます。table作成に問題がありそうですが、正解例を教えていただけませんか? エラー内容: java.sql.Connection.close() requested while a transaction is in progress on the connection.The transaction remains active, and the connection cannot be closed.
stera@myrealbox.com
「close()はコネクションの進行中のトランザクションに要求されました。このトランザクションはまだ生きているのでコネクションを閉じることができません。」と言っているようなので、トランザクションを破棄するなり確定するなりして明示的に終了させてからコネクションを閉じる必要があるのではないでしょうか。 私はその本も持ってませんし、さらに言えばarton氏でもないので、これ以上のことは、あなたが何を試行したのか書いていないのでわかりません。
寺島さん、今読みました(こっちのコンテンツはどちらかというと書き込み専用で、あまり読みに行くことはないので、書き込まれたら日記のほうにツッコンでいただければ幸いです。
それはそれとして、どのあたりのコードを試すと出るのか示していただけますか?
(arton)
ツッコミから転載 _ 寺島 (2006-08-29 21:29)
>それはそれとして、どのあたりのコードを試すと出るのか示していただけますか?
プロジェクトの開始時からエラーです。したがって正常な画面は1つも出ていません。 今回はテーブルを作り直したので違うメッセージが出ています。
例外 javax.servlet.ServletException: [ESSR0071]SQLで例外が発生しました。理由はorg.apache.derby.client.am.SqlException: A lock could not be obtained within the time requested javax.faces.webapp.FacesServlet.service(FacesServlet.java:125) org.apache.myfaces.component.html.util.ExtensionsFilter.doFilter(ExtensionsFilter.java:112) org.seasar.extension.filter.EncodingFilter.doFilter(EncodingFilter.java:62) org.seasar.framework.container.filter.S2ContainerFilter.doFilter(S2ContainerFilter.java:60)
原因 org.seasar.framework.exception.SQLRuntimeException: [ESSR0071]SQLで例外が発生しました。理由はorg.apache.derby.client.am.SqlException: A lock could not be obtained within the time requested org.seasar.extension.jdbc.impl.BasicSelectHandler.execute(BasicSelectHandler.java:124) org.seasar.dao.impl.SelectDynamicCommand.execute(SelectDynamicCommand.java:55) org.seasar.dao.interceptors.S2DaoInterceptor.invoke(S2DaoInterceptor.java:51)
ちなみに今回のsqlは次のとおりです。
- CREATE TABLE "HTMLCACHE"(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL ,PAGEID INTEGER NOT NULL ,HTML VARCHAR(256), CONSTRAINT SYS_IDX_49 PRIMARY KEY (ID) )
- CREATE TABLE "PAGES"(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL ,NAME VARCHAR(64) NOT NULL , CONSTRAINT SYS_IDX_46 PRIMARY KEY (ID) )
- CREATE TABLE "REVERSELINKS"(PAGEID INTEGER NOT NULL ,LINK INTEGER NOT NULL )
- CREATE TABLE "SOURCES"(ID INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL ,TIMESTAMP TIMESTAMP,REVISION SMALLINT,PAGEID INTEGER NOT NULL ,SOURCETEXT VARCHAR(128), CONSTRAINT SYS_IDX_53 PRIMARY KEY (ID) )
確信はありませんが、http://ml.seasar.org/archives/seasar-user/2006-March/005271.html を試されたらいかがでしょうか。
(arton)
artonさんも私と同様の現象を確認されたのでしょうか?
http://ml.seasar.org/archives/seasar-user/2006-March/005271.html を試そうにも、
どこのどのコードをどう変更すべきかわかりません。
(stera)
1.0.29(メモ)
ここで言っているのは'org.seasar.extension.dbcp.impl.DataSourceImpl?'ではないでしょうか。 むしろhttp://www02.so-net.ne.jp/~kikuta/jdbcnote/jdbc5_3.htmlも見た方が良い気がします。 Aspectの方法についてはhttp://s2container.seasar.org/ja/aop.htmlをどうぞ(と言うか手元の本を読んだらいいかも)。
MLの話は、要はAspectを一個作って、'org.seasar.extension.dbcp.impl.DataSourceImpl?'のgetConnectionにくっつけて
<components> <component name="changeIsolationInterceptor" class= "my.test.package.ChangeIsolationInterceptor" /> <component name="dataSourceImpl" class="org.seasar.extension.dbcp.impl.DataSourceImpl"> <aspect pointcut="getConnection">changeIsolationInterceptor</aspect> </component> </components>
返値のIsolationLevelを変更しろ
package my.test.package; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.seasar.framework.aop.interceptors.AbstractInterceptor; import java.sql.Connection; public class ChangeIsolationInterceptor extends AbstractInterceptor { public Object invoke( MethodInvocation mi ) throws Throwable { Object result = mi.proceed(); // ポイントカットのメソッドを実行する Connection con = (Connection)result; con.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED); return con; // proceedメソッドの実行結果を返す } }
と言っているんだと思います。但しそれで対処可能なのか、そもそもその対処が妥当かはわかりません。それはロジックに依存するからです。あと私は未テストです。
上の人、フォローどうもありがとうございます。実際には、最初の投稿者が書かれているように、DataSourceImplクラスがfinalなのでメソッドをポイントカットするアスペクトの適用はできません。したがって、元のDataSourceImplを内包しすべてのメソッドをデリゲートするDataSource実装クラスを作り、getConnectionではデリゲート結果のConnectionオブジェクトにアイソレーションレベルを設定するようにするのが良いでしょう(もし、これが問題ならば)。
しかし、そもそもの問題として、S2DAOのDerbyサポートが1.0.29からで、こちらで動作を検証(HSQLDBで。ある意味当然ですが)してダウンロードサイトに置いてあるのが1.0.28なので、そこから変える必要があるように思えます。
次に、こちらでも例外が出ることは確認しました。ただし、最初の報告のcloseの問題です。
ERROR 2006-09-05 19:13:57,319 [http-8084-Processor12] java.sql.Connection.close() requested while a transaction is in progress on the connection.The transaction remains active, and the connection cannot be closed. org.apache.derby.client.am.SqlException: java.sql.Connection.close() requested while a transaction is in progress on the connection.The transaction remains active, and the connection cannot be closed. at org.apache.derby.client.am.Connection.checkForTransactionInProgress(Unknown Source)
ここで疑問があります。寺島さんは、本書では大して説明していない(S2を利用した設計の本であって、S2の設定のハウツー本じゃないのでこれもある意味当然ですが)diconファイルの設定を変更したりしていると思うのですが(そうでなければjdbcドライバーを変えることすらできない)、最初の報告の問題が出なくなっていて、かつこちらで動かすと出るということは、Derby JDBCのプロパティ設定などについてよくご存知なのではないかということです。
それに対して、こちらは9/3の日曜にAppサーバーバンドルを落として2時間程度触っただけで、Derbyのドキュメントすら見ていません(jarの場所はわかったのでとりあえず入れたのと、sampleデータベースが用意されていたのでそれに乗せた)。
ということは、どう考えても寺島さんがご自身で解決するほうが良いのではないかと思います。HSQLDBで動作するということとから、直接ソースに書かれたSQLがHSQLDBに特化している可能性もゼロではないでしょうし、同様にDerbyに特化したSQLが必要だとしたら、こちらにその知識はまったくありません。
とりあえず、S2Daoのバージョンを上げる(多分、それに付随してExtensionや各種dionの変更も必要になると思います)ことから試してください。で、もしよろしければ、何を変えると動作するのかご教示いただければ幸いです。
お役に立てなくて申し訳ありません。 (arton)
Keyword(s):
References: