SAStruts + SQLite3 の組み合わせでハマる
ふと SAStruts を触ってみようかなと思い立ち、blank をダウンロード*1 して適当に動かしてみる。「Javaでサクサク感のある開発」がウリらしいですが、確かにサクサク作れますね。
のは大きいかも。
で、とりあえずDBなしの画面は簡単にできました。次にDBからデータを引っ張ってきて一覧表示するところで詰まる。
DBはSQLite。jdbcの設定は以下でOK。
<component name="xaDataSource" class="org.seasar.extension.dbcp.impl.XADataSourceImpl"> <property name="driverClassName"> "org.sqlite.JDBC" </property> <property name="URL"> "jdbc:sqlite:/" + @org.seasar.framework.util.ResourceUtil@getBuildDir('app.dicon').getCanonicalPath() + "/data/sastruts.db" </property> <property name="user">"sa"</property> <property name="password">""</property> </component>
で、SAStruts側から呼び出す。
public class UserAction { @IntegerType public String id; public String userName; public String email; public String description; public List<Users> userList; public JdbcManager jdbcManager; @Execute(validator = false) public String index() { userList = jdbcManager .from(Users.class) .orderBy("id") .getResultList(); return "list.jsp"; } }
すると、ServletException が発生。
javax.servlet.ServletException: [ESSR0072]SQLで例外(SQL=[], Message=[not yet implemented], ErrorCode=0, SQLState=null)が発生しました ... (中略) 原因: java.sql.SQLException: not yet implemented org.sqlite.Conn.setReadOnly(Conn.java:140) org.seasar.extension.dbcp.impl.ConnectionWrapperImpl.setReadOnly(ConnectionWrapperImpl.java:214) org.seasar.extension.dbcp.impl.ConnectionPoolImpl.checkOut(ConnectionPoolImpl.java:322) ... (以下略)
どうやら SQLite3 の JDBC ドライバ*2が setReadOnly メソッドを実装していないらしい。念のためソースで確認したところ、確かに実装してないね。
(sqlitejdbc-v043\src\org\sqlite\Conn.java - Line 139) public void setReadOnly(boolean ro) throws SQLException { throw new SQLException("not yet implemented"); }
AOPで無理やり ConnectionWrapperImpl#setReadOnly を無効化しようかとも考えたんだが、ConnectionWrapperImpl が直接 new されており S2 の管理下ではないので S2 上で Aspect を差し込むのは難しそうだという結論に。
ConnectionPoolImpl#checkOut を sqlite 用にいじれば*3動くんだろうけど、それはそれで泥臭いなぁ...などと考えていたら1日が終わっていました。本題とは関係ないところで時間を使ってしまった。
ちなみに、ソースコードを追う過程で S2 の dicon の書き方はなんとなく分かったような気がする。Spring 経験という下地があったためか、それほど苦労なく追えた。
*1:http://sastruts.seasar.org/download.html
*2:http://www.zentus.com/sqlitejdbc/
*3:要はsetReadOnlyを呼ばなければいい