SAStrutsでUnsupportedOperationException

Seasar2のサポートはずいぶんと前に終了しましたが、SAStrutsのライブラリを使う機会があり、そこで表題のエラーに遭遇したので記事を書くことにしました。

アクセス解析を見てると、古い技術の記事もたまにアクセスがあったりするので、もしかしたら1,2人くらいには役に立つ情報かもしれません。

 

UnsupportedOperationException

この例外自体はJavaの標準的なExceptionの1つであり、「サポートされていない操作が行われた」という例外です。

多くの場合、意図的にThrowされるExceptionでしょう。非推奨だったAPIがバージョンアップでついに廃止APIになったときとか。

 

今回発生したエラーは以下でした。

java.lang.UnsupportedOperationException: [ESSR0746]エンティティ(XXXX)の検索にFOR UPDATEが指定されましたが、DBMS(hsql)ではサポートされていません。
	at org.seasar.extension.jdbc.query.AutoSelectImpl.forUpdate(AutoSelectImpl.java:1370)

AutoSelectImplはS2JDBCの機能の1つにある「SQLを自動生成するクラス」です。

そこでこのエラーが発生するということは、なんとなく設定の問題なのかなと思いました。

ライブラリである以上、ソースのバグであるなら既に誰かが報告しているでしょう。

 

今回の根本的な原因は「s2jdbc.dicon」のダイアレクトに関する設定の漏れでした。

Seasar2 - S2JDBC - セットアップ

 

使用しているDBに応じて、dialectプロパティを書いてあげる必要がありました。

追記したことで、エラーが発生した処理も正常に動作するようになりました。

 

 

UnsupportedOperationException自体は数多くのライブラリで発生する可能性があるでしょう。

発生した場合は、その次に書かれているであろうThrowしたクラスを見て、そいつがどんなものか調査してみましょう。

 

 

ちなみに、念のため該当箇所のソースを見てみたら、まさにという記述でした。

public AutoSelect forUpdate() {
    final DbmsDialect dialect = getJdbcManager().getDialect();
    if (!dialect.supportsForUpdate(SelectForUpdateType.NORMAL, false)) {
        final EntityMeta entityMeta = getJdbcManager()
                .getEntityMetaFactory().getEntityMeta(baseClass);
        throw new UnsupportedOperationException(MessageFormatter
                .getMessage("ESSR0746", new Object[] {
                        entityMeta.getName(), dialect.getName() }));
    }

    forUpdateType = SelectForUpdateType.NORMAL;
    return this;
}

JDBCManagerからdialectを取得して、DBがfor update文をサポートしているかを判定しています。

ここら辺から、JDBC関連の特にdialectに関する問題であることが推測できます。