WebSphere Liberty で StaleConnectionException を利用する

WebSphere Liberty の heritageAPIs-1.1 フィーチャーは、WebSphere Application Server traditional (以下 tWAS)が提供する古い機能の一部を、WebSphere Liberty で利用可能にするものです。(WebSphere Liberty 22.0.0.1 以降で利用可能)

このフィーチャーが提供する機能は、「CommonJ Timer および Work Manager API」と「Java Database Connectivity (JDBC) の拡張」に大別されます。
後者の「Java Database Connectivity (JDBC) の拡張」には幾つかの機能が含まれていて、その１つが、JDBC 操作で発生した SQLException を、DB 製品に依存しない例外へマッピングする「例外マッピング」の機能です。
tWAS のアプリケーションでは、JDBC 接続が無効になったことを示す StaleConnectionException を利用していることがあったと思いますが、この機能が WebSphere Liberty でも利用可能になるわけです。
今回は、heritageAPIs-1.1 フィーチャーを有効にし、例外マッピングの動作を確認してみました。

:::note warn
この記事は、heritageAPIs-1.1 フィーチャーの利用を積極的にお勧めするものではありません。この機能は、既存アプリを WebSphere Liberty 環境へ移行する場合に利用するものです。
:::


# 例外マッピングを有効化
まず、heritageAPIs-1.1 フィーチャーを有効化します。他のフィーチャーと同様に `<featureManager>` に heritageAPIs-1.1 を追加するだけで完了です。

```xml:serve.xml で heritageAPIs-1.1 フィーチャーを有効化
    <featureManager>
    	<feature>webProfile-8.0</feature>
		<feature>heritageAPIs-1.1</feature>
	</featureManager>
```

次に、データソース定義に `<heritageSettings>` タグを追加し、以下の２つ指定します。
- `helperClass` (ヘルパー・クラス名): 対象 DB 用のヘルパー・クラスを指定
- `replaceExceptions` (例外の置き換えを行うか): "true" を指定

ヘルパー・クラスの名前は、下記 URL の WebSphere Liberty のドキュメントに記載されています。

- [Heritage プログラミング・モデルの有効化](https://www.ibm.com/docs/ja/was-liberty/base?topic=liberty-enabling-heritage-programming-models)

以下は、Db2 を使用する場合のデータソース定義の変更例です。

```xml:serve.xml 内のデータソース定義で例外マッピングを有効化
     <dataSource id="SampleDS" jndiName="jdbc/sample" jdbcDriverRef="SampleJD" containerAuthDataRef="SampleAD" >
        <properties.db2.jcc databaseName="sample" portNumber="50000" serverName="sampledb"/>
        <heritageSettings helperClass="com.ibm.websphere.rsadapter.DB2UniversalDataStoreHelper" replaceExceptions="true"/>
    </dataSource>
```


# 動作を確認
アプリケーションから DB へ接続した後に、DB との通信を切断し、再度、DB へのアクセスを試みると、以下の様に StaleConnectionException がスローされることが確認できます。

```java:例外マッピングを有効化した時
com.ibm.websphere.ce.cm.StaleConnectionException: [jcc][t4][2030][11211][4.19.26] 接続の基礎となるソケット、ソケット入力ストリーム、またはソケット出力ストリーム上での操作中に、 通信エラーが発生しました。 エラーのロケーション: Reply.fill() - socketInputStream.read (-1)。 メッセージ: Connection reset by peer。 ERRORCODE=-4499, SQLSTATE=08001
```

尚、例外マッピングを有効化していない状態では、以下の Db2 固有の例外がスローされます。

```java:例外マッピングを有効化していない時
com.ibm.db2.jcc.am.DisconnectNonTransientConnectionException: [jcc][t4][2030][11211][4.19.26] 接続の基礎となるソケット、ソケット入力ストリーム、またはソケット出力ストリーム上での操作中に、 通信エラーが発生しました。 エラーのロケーション: Reply.fill() - socketInputStream.read (-1)。 メッセージ: Connection reset by peer。 ERRORCODE=-4499, SQLSTATE=08001
```

StaleConnectionException にマップされる例外の情報は、ヘルパー・クラスの JavaDoc (下記 URL 参照)で確認できます。

- [com.ibm.websphere.rsadapter パッケージの JavaDoc](https://www.ibm.com/docs/en/was/9.0.5?topic=SSEQTP_9.0.5/com.ibm.websphere.javadoc.doc/web/apidocs/com/ibm/websphere/rsadapter/package-frame.htm)

例えば、先ほどの構成例で指定した DB2UniversalDataStoreHelper の場合は、以下の３つの JavaDoc で確認できることになります。

- DB2UniversalDataStoreHelper の JavaDoc
- その親クラスの DB2DataStoreHelper の JavaDoc
- さらに親クラスの GenericDataStoreHelper の JavaDoc

あまり利用することはないと思いますが、データソース定義に `<identifyException>` タグを追加することで、tWAS と同様に、例外のマッピングをカスタマイズすることも可能です。

ここでは、StaleConnectionException へのマッピングのみを説明・検証しましたが、マッピング先の例外は以下の４つになります。

- com.ibm.websphere.ce.cm.DuplicateKeyException
- com.ibm.websphere.ce.cm.ObjectClosedException
- com.ibm.websphere.ce.cm.StaleConnectionException
- com.ibm.websphere.ce.cm.StaleStatementException

# 終わりに
今回は、スローされた JDBC 例外を StaleConnectionException などにマッピングする動作を確認してみました。
あまり積極的に利用すべき機能ではありませんが、急ぎでアプリケーションを移行したい時に役に立つ機能と思います。