データ・アクセスに関する例外
Enterprise JavaBeans (EJB) 2.x 仕様に基づくすべてのエンタープライズ Bean のコンテナー管理パーシスタンス (CMP) Bean は、オペレーションが失敗すると標準の EJB 例外を受け取ります。Java™ Database Connectivity (JDBC) アプリケーションは、JDBC オペレーションが失敗すると標準の SQL 例外を受け取ります。この製品は、リレーショナル・リソース・アダプター (RRA) に 現在保持されている接続が既に無効であることを示す、特別な例外を提供します。
- 接続待ちタイムアウト例外は、アプリケーションが、接続タイムアウト設定に指定されている秒数を待機して、接続を受け取らなかったことを意味します。
この状態は、プールが最大サイズに達し、
その待機中に、すべての接続が他のアプリケーションによって使用中である場合に発生する可能性があります。
さらに、接続プロパティーが一致しないか、
または異なるトランザクションにあるために、
現在使用中の接続の中に、アプリケーションで共有できるものがありません。
バージョン 4.0 のデータ・ソースでは、ConnectionWaitTimeout オブジェクトは com.ibm.ejs.cm.pool.ConnectionWaitTimeoutException クラスからインスタンス化された例外を作成します。
Java 2 Connector (J2C) 接続ファクトリーの場合、ConnectionWaitTimeout オブジェクトは com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException クラスのリソース例外を生成します。
エラー検出モデルが例外マッピングを実行するように構成されている場合、新しいバージョンのデータ・ソースでは com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException サブクラスの SQL 例外が発行されます。エラー検出モデルが例外チェックを実行するように構成されている場合、新しいバージョンのデータ・ソースでは java.sql.SQLTransientConnectionException クラスの SQL 例外と com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException クラスのチェーン例外が発行されます。
- エラー検出モデルが例外マッピングを実行するように構成されている場合、失効した接続の例外は、接続が無効になったことを示します。エラー検出モデルが例外チェックを実行するように構成されている場合は、JDBC ドライバーが、JDBC 4.0 例外 (java.sql.SQLRecoverableException または java.sql.SQLNonTransientConnectionException など) を起こすか、接続が無効になったことを示す適切な SQLState を指定します。このタイプの例外について詳しくは、『失効した接続』をお読みください。
- 項目は、セミコロン (;) で区切られます。
- 各項目は、1 つのキーと値で構成されます。この場合、キーは、引用符で囲まれたテキストのエラー・コード (数値) または SQLState です。
- キーと値は、等号 (=) で区切られます。
"S1000"=;1062=com.ibm.websphere.ce.cm.DuplicateKeyException;"08004"=
com.ibm.websphere.ce.cm.StaleConnectionException
userDefinedErrorMap は、データ・ソースを選択し、カスタム・プロパティーを構成することによって、管理コンソールに置くことができます。- 失効した接続
- 例: データ・アクセス例外の処理 - 失効した接続
- Linux システムでの不整合な接続
- 例: サーブレット JDBC 接続例外の処理
- 例: コンテナー管理データベース・トランザクションのセッ ション Bean 用の接続例外の処理
- 例: Bean 管理データベース・トランザクシ ョンのセッション Bean 用の接続例外の処理
- 例: コンテナー管理データベース・トランザクションの BMP Bean 用の接続例外の処理
- 例: データ・アクセス例外の処理 - ConnectionWaitTimeoutException (JDBC API 用)
- 例: データ・アクセス例外の処理 - ConnectionWaitTimeoutException (Java EE コネクター・アーキテクチャー用)
- 例: データ・アクセス例外の処理 - DataStoreHelper でのエラー・マッピング
- データベースのデッドロックおよび外部キーの競合
失効した接続
この製品では、接続プールを使用してリレーショナル・データベースにアクセスするための java.sql.SQLException クラスの特別なサブクラスが提供されています。 この com.ibm.websphere.ce.cm.StaleConnectionException サブクラスは、WebSphere® 4.0 データ・ソースと、リレーショナル・リソース・アダプターを使用する最新バージョンのデータ・ソースの両方に存在します。 このクラスは、現在保持されている接続が無効であることを示します。
- データベースが始動されない場合のように、 アプリケーションが接続を取得しようとして失敗した。
- データベースの障害により、接続をこれ以上使用できない。 アプリケーションが以前に取得した接続を使用しようとすると、接続は既に無効になっています。 この場合、現在アプリケーションによって使用中のすべての接続が、 接続を使用しようとしたときにこのエラーを受け取る可能性があります。
- 接続が孤立した状態で (アプリケーションが、未使用タイムアウト設定値の最大 2 倍の時間の間この接続を使用しなかったため)、その孤立した接続を使用しようとしている。 この場合は、バージョン 4.0 データ・ソースにのみ適用されます。
- アプリケーションが、 失効した接続で取得されたステートメントのような JDBC リソースを使用しようとしている。
- 接続がバージョン 4.0 データ・ソースの自動接続クリーンアップ機能によってクローズされていて使用できない。
自動接続クリーンアップは、接続管理が操作する標準モードです。
このモードでは、
トランザクションが終了すると、トランザクション・マネージャーは、
そのトランザクションで確保されていた接続をすべて閉じます。
これにより、トランザクション・マネージャーは、
接続が長時間保留状態に置かれることがなく、
またプールが早期に最大接続数に到達しないようにすることができます。
ただし、トランザクションの終了後に、トランザクション・マネージャーが接続を閉じ、その接続をフリー・プールに戻すことによって、マイナスの効果が生じます。アプリケーションは、あるトランザクションで接続を取得し、それを別のトランザクションで使用することを試行できなくなります。アプリケーションがそれを試行すると、接続が既に閉じられているため ObjectClosedException が発生し、それにより StaleConnectionException が発生します。
- 最小接続プール・サイズを 0 に設定することにより、アプリケーション・サーバーが長時間非アクティブの場合、接続プールは空の状態に保たれます。これは、データベース・サイドでのメンテナンス・アクティビティーにより接続が失効するのを避けるのに役立ちます。
- 接続プールの未使用タイムアウトは、ファイアウォールのタイムアウト用に構成されている値より小さい値に設定してください。これにより、未使用タイムアウトまでは接続が失効しないようにでき、接続は再使用のための空きプールにとどまることができます。
- 接続プールのリープ時間は、未使用タイムアウトより小さい値に設定します。この値が小さいほど、プールのメンテナンス・スレッドのチェック頻度が増し、未使用タイマーがより正確になります。ただし、頻繁にプールのメンテナンス・スレッドが実行されると、パフォーマンスが低下する可能性があります。
孤立した接続または自動接続クリーンアップによって使用不可にされた接続を使用しようとすると、失効した接続の例外が発生し、アプリケーションが既に接続プールに戻された接続を使用しようとしたことを示します。 これは、実際に接続に関する問題があることを示しているわけではありません。 ただし、その他の失効した接続の例外では、データベースへの接続が失敗したか、または失効したことを示します。 接続は、一度失効するとリカバリーできないので、 プールには戻さず、完全に閉じる必要があります。
失効した接続の検出データベースへの接続が失効すると、その接続での操作の結果、JDBC Driver から SQL 例外が出されます。 SQL 例外は、どちらかと言えば一般的な例外であるため、これには、例外の意味の判別に使用できる状態およびエラー・コードの値が含まれています。 しかし、これらの状態およびエラー・コードの意味は、 データベースのベンダーによって異なります。 この接続プール・ランタイムは、サポートされるデータベース・ベンダーごとの失効した接続の例外を示す、SQL 状態とエラー・コードのマッピングを管理します。 接続プール・ランタイムは、SQL 例外をキャッチすると、この SQL 例外が、使用中のデータベース・サーバーに対する失効した接続の例外であるかどうかをチェックします。
失効した接続からのリカバリー- エラー検出モデルが例外マッピングを実行するように構成されている場合、アプリケーション・サーバーは JDBC ドライバーで発生した例外を StaleConnectionException に置き換えます。この場合、アプリケーションが、失効した接続の例外をトラップすることがあります。
- エラー検出モデルが例外検査を実行するように構成されている場合、アプリケーション・サーバーは接続プールを管理するためにエラー・マップを調査しますが、例外の置き換えは行いません。この場合、アプリケーションは失効した接続の例外をトラップしません。
エラー検出モデルの間に違いがあるため、アプリケーション・サーバーは、失効した接続をどのようなモデルでも識別できる API を提供しています。この API は com.ibm.websphere.rsadapter.WSCallHelper.getDataStoreHelper(datasource).isConnectionError(sqlexception) です。
アプリケーション・サーバーでは、失効した接続の例外を明示的に識別する必要はありません。アプリケーション・サーバーは既に java.sql.SQLException をキャッチしている必要があり、かつ、失効した接続の例外または JDBC ドライバーで発生した例外は、常に java.sql.SQLException からデータを継承しています。失効した接続の例外は SQLException を発生させるように宣言されたメソッドのすべてから発生する可能性があり、通常の catch ブロックで自動的にキャッチされます。ただし、失効した接続の例外を明示的に識別すると、アプリケーションの接続不良をリカバリーすることができます。 失効した接続の例外を、アプリケーション・コードによって識別する場合、 明示的なリカバリー・ステップを実行する必要があります。例えば、新規トランザクションや新規接続での操作の再試行などです。
例: データ・アクセス例外の処理 - 不整合な接続
次のコード・サンプルを使用して、異なるトランザクション・シナリオで異なるタイプのデータ・アクセス・クライアントの不整合な接続例外をプログラマチックに処理する方法について説明します。
アプリケーションがデータベース操作で不整合な接続例外を受け取る場合、 これは現在保留されている接続が有効ではなくなったことを示しています。 どのデータベース操作においても不整合な接続に関する例外を受け取る可能性はあ りますが、発行された不整合な接続例外を最もよく目にするのは、 接続を最初に検索した直後です。 接続がプールされているため、プールからの検索直後の操作、 すなわちデータベースとの最初の通信が試行されるまで、データベースの障害は検出されません。 接続の失効がマークされるのは、障害が検出されたときだけです。 データベースにアクセスする各メソッドがプールから新しい接続を取得するときは、不整合な接続例外の発生頻度は低くなります。

アプリケーションが操作を再試行するために新規接続を取得する場合は、 その前に元の接続が関係していたトランザクションをロールバックして、 新しいトランザクションを開始してください。 このアクションに関する詳細は、次の 2 つのカテゴリーに分類できます。
- データベース・アクセスと同じメソッドで開始される Bean 管理のグローバル・トランザクション・コンテキストで作動するオブジェクト
- サーブレットあるいは Bean 管理トランザクション (BMT) を持つセッション Bean は、
ネーミング・オブジェクトまたは Bean の EJBContext オブジェクトから検索可能な javax.transaction.UserTransaction オブジェクトの begin() を呼び出すことによって、
グローバル・トランザクションを明示的に開始できます。
Bean 管理トランザクションをコミットする場合、
アプリケーションは UserTransaction オブジェクトの commit() を呼び出します。
トランザクションをロールバックする場合、アプリケーションは rollback() を呼び出します。
エンティティー Bean および BMT を持たないセッション Bean の場合は、
明示的にグローバル・トランザクションを開始することができません。
Bean 管理トランザクションを明示 的に開始したオブジェクトが、データベース操作で不整合な接続例外を受け取る場合は、 接続を閉じ、トランザクションをロールバックしてください。この時点で、アプリケーション開発者は、 新規のトランザクションを開始して、新規の接続を取得し、操作を再試行することを決定することができます。
以下のコード・フラグメントは、 このシナリオにおける不整合な接続例外の処理例を示しています。//get a userTransaction javax.transaction.UserTransaction tran = getSessionContext().getUserTransaction(); //retry indicates whether to retry or not //numOfRetries states how many retries have // been attempted boolean retry = false; int numOfRetries = 0; java.sql.Connection conn = null; java.sql.Statement stmt = null; do { try { //begin a transaction tran.begin(); //Assumes that a datasource has already been obtained //from JNDI conn = ds.getConnection(); conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.execute("INSERT INTO EMPLOYEES VALUES (0101, 'Bill', 'R', 'Smith')"); tran.commit(); retry = false; } catch(java.sql.SQLException sqlX) { // If the error indicates the connection is stale, then // rollback and retry the action if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { try { tran.rollback(); } catch (java.lang.Exception e) { //deal with exception //in most cases, this can be ignored } if (numOfRetries < 2) { retry = true; numOfRetries++; } else { retry = false; } } else { //deal with other database exception retry = false } } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } while (retry) ;
- グローバル・トランザクション・コンテキストおよびトランザクションで作動するオブジェクトが、 データベース・アクセスと同じメソッドで開始されない
- コンテナー管理トランザクションの場合のように、不整合な接続例外
を受け取るオブジェクトが、トランザクションに対して直接制御を行わない
場合、そのオブジェクトはトランザクションにロールバックをマークし、続
いてその呼び出し元にトランザクションを再試行するように指示します。
ほとんどの場合、これは、その操作を再試行するように指示するアプリケ
ーション例外を作成することによって実行できます。
ただし、このアクションがいつも可能なわけではありません。
多くの場合は、メソッドは特定の例外を作成するようにしか定義されていません。
エンタープライズ Bean 上の ejbLoad() および ejbStore() メソッドの場合がこれに該当します。
次の 2 つの例で、上記のシナリオをそれぞれ説明します。
- 例 1: データベース・アクセス・メソッドがアプリケーション例外を作成します
- データベースにアクセスするメソッドが、必要な例外をどれでも自由に作成できる場合、
不整合な接続例外をキャッチして、
メソッドの再試行を示すアプリケーション例外を作成することが最適な方法です。
次の例は、トランザクション境界 TX_REQUIRED を用いてエンティティー Bean のメソッドを呼び出す EJB クライアントを示したものです。
TX_REQUIRED は、insertValue() を呼び出したときに、
グローバル・トランザクションがコンテナーによって開始されるということを示します。
public class MyEJBClient { //... other methods here ... public void myEJBClientMethod() { MyEJB myEJB = myEJBHome.findByPrimaryKey("myEJB"); boolean retry = false; do { try { retry = false; myEJB.insertValue(); } catch(RetryableConnectionException retryable) { retry = true; } catch(Exception e) { /* handle some other problem */ } } while (retry); } } //end MyEJBClient public class MyEJB implements javax.ejb.EntityBean { //... other methods here ... public void insertValue() throws RetryableConnectionException, java.rmi.EJBException { try { conn = ds.getConnection(); stmt = conn.createStatement(); stmt.execute("INSERT INTO my_table VALUES (1)"); } catch(java.sql.SQLException sqlX) { // Find out if the error indicates the connection is stale if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { getSessionContext().setRollbackOnly(); throw new RetryableConnectionException(); } else { //handle other database problem } } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } } //end MyEJB
MyEJBClient は最初に MyEJB Bean を、それがあらかじめ Java Naming and Directory Interface (JNDI) から取得されているものと想定して、ホーム・ インターフェースから取得します。 次に MyEJB Bean は、Bean 上の insertValue() を呼び出します。Bean 上のこのメソッドは、接続を取得し、値を表に挿入しようとします。 これらのメソッドのいずれかが失敗して不整合な接続例外を発生した場合、 そのメソッドはトランザクションに rollbackOnly のマークを付けて (呼び出し元に、 このトランザクションのロールバックを強制します)、新たに 再試行可能接続例外を作成し、 例外がスローされる前にリソースをクリーンアップします。 再試行可能接続例外は、アプリケーション定義の例外にすぎず、 メソッドの再試行を呼び出し元に知らせます。 呼び出し元は、再試行接続例外をモニターして、 これをキャッチした場合にはメソッドを再試行します。 この例では、コンテナーがトランザクションの開始および終了を行うため、 クライアントまたはサーバーでのトランザクション管理は必要ありません。 もちろん、クライアントがトランザクションのコミットあるいはロールバックも実行していれば、 クライアントによって Bean 管理トランザクションが開始され、動作はこの後も同じとなります。
- 例 2: データベース・アクセス・メソッドが onlyRemote 例外または EJB 例外を作成します。
- アプリケーションで定義した例外をスローすることが、すべてのメソッドに許可されているわけではありません。
Bean 管理パーシスタンス (BMP) を使用している場合は、
ejbLoad() および ejbStore() メソッドを使用して Bean の状態を保管します。こ
れらのメソッドから発行される例外は java.rmi.Remote 例外または
javax.ejb.EJB 例外のみであり、前述の例と同じような例外は使用できません。
コンテナー管理パーシスタンス (CMP) を使用している場合は、コンテ ナーが Bean パーシスタンスを管理します。不整合な接続例外を認識するのもコンテナーです。 不整合な接続が検出された場合、例外はクライアントに戻されるまでリモート例外であるため、 単純な catch ブロック 1 つのみでは不十分です。 リモート例外の根本的原因が不整合な接続例外かどうかを判別する方法があります。リモート例外が作成されて別 の例外をラップすると、元の例外は通常は保存されます。 すべてのリモート例外インスタンスには詳細プロパティーがあり、その型は java.lang.Throwable です。 この詳細を使用すれば、元の例外までトレースバックでき、それが不整合 な接続例外であれば、トランザクションを再試行できます。 実際には、これらのリモート例外のいずれかが、 Java 仮想マシン API から次の Java 仮想マシン API に 流れるときに詳細が失われるため、トランザクションは、データベース・アクセスが 行われるのと同じサーバーで開始する方が適切です。 この理由から、 以下の例では Bean 管理トランザクション境界を持つセッション Bean がアクセスするエンティティー Bean を示します。
public class MySessionBean extends javax.ejb.SessionBean { ... other methods here ... public void mySessionBMTMethod() throws java.rmi.EJBException { javax.transaction.UserTransaction tran = getSessionContext().getUserTransaction(); boolean retry = false; do { try { retry = false; tran.begin(); // causes ejbLoad() to be invoked myBMPBean.myMethod(); // causes ejbStore() to be invoked tran.commit(); } catch(java.rmi.EJBException re) { try { tran.rollback(); } catch(Exception e) { //can ignore } if (causedByStaleConnection(re)) retry = true; else throw re; } catch(Exception e) { // handle some other problem } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } while (retry); } public boolean causedByStaleConnection(java.rmi.EJBException re) { // Search the exception chain for errors // indicating a stale connection for (Throwable t = re; t != null; t = t.getCause()) if (t instanceof RetryableConnectionException) return true; // Not found to be stale return false; } } public class MyEntityBean extends javax.ejb.EntityBean { ... other methods here ... public void ejbStore() throws java.rmi.EJBException { try { conn = ds.getConnection(); stmt = conn.createStatement(); stmt.execute("UPDATE my_table SET value=1 WHERE primaryKey=" + myPrimaryKey); } catch(java.sql.SQLException sqlX) { // Find out if the error indicates the connection is stale if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { // rollback the tran when method returns getEntityContext().setRollbackOnly(); throw new java.rmi.EJBException( "Exception occurred in ejbStore", new RetryableConnectionException(sqlX)); } else { // handle some other problem } } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } }
前の例の mySessionBMTMethod() では、以下のとおりです。- セッション Bean は最初に UserTransaction オブジェクトをセッション・コンテキストから検索し、続いてグローバル・トランザクションを開始します。
- 次に、エンティティー Bean 上のメソッドを呼び出します。ここでは、ejbLoad() メソッドを呼び出します。ejbLoad() が正常に実行されると、クライアントがそのトランザクションをコミットするため、 ejbStore() メソッドが呼び出されます。
- ejbStore() では、エンティティー Bean が接続を取得し、接続の状態を データベースに書き込みます。取得した接続が不整合である場合、トランザクション には rollbackOnly のマークが付けられ、RetryableConnectionException を ラップする新規の EJBException がスローされます。 そして、その例外をクライアントがキャッチすると、JDBC リソースをクリーンアップし、 トランザクションをロールバックして、causedByStaleConnection() を呼び出します。 これにより、不整合な接続例外がその例外に埋め込まれているかどうかを判別しま す。
- このメソッドが true を戻した場合、retry フラグが設定されてトランザクションが再試行されます。 そうではない場合、例外を呼び出し元に再発行します。
- causedByStaleConnection() メソッドは、detail 属性のチェーンを調べて、元の例外を検索します。 例外が最後にクライアントに戻されるまでには、例外が多重ラッピングされている可能性も あるため、メソッドは、不整合な接続例外が検出されて true が戻されるまで検索を続けます。それ以外の場合では、リストに不整合な接続例外はないということで、false が戻されます。
- ここで BMP Bean ではなく CMP Bean と通信する場合も、セッション Bean は同じです。 CMP Bean の ejbStore() メソッドは空であることがほとんどで、 コンテナーはこのメソッドを呼び出した後、生成済みコードを持つ Bean を持続させます。
- 不整合な接続例外がパーシスタンス中に発生した場合、この例外はリモート例外にラップされ、 呼び出し元に戻されます。 causedByStaleConnection() メソッドはもう一度例外チェーン全体を調べて、 ルートの例外すなわち不整合な接続例外を検索します。
- ローカル・トランザクション・コンテキストで作動するオブジェクト
- データベース操作がグローバル・トランザクション・コンテキストの外部で行われると、
コンテナーは暗黙的にローカル・トランザクションを開始します。
このオブジェクトには、指定されていないトランザクション・コンテキス
トで稼働するエンタープライズ Bean に加えて、トランザクションを開始する際に
UserTransaction インターフェースを使用しないサーブレットまたは JSP も組み込まれています。
グローバル・トランザクションの場合と同様、ローカル・トランザクションもロールバックしてからでなければ操作を再試行することはできません。
上記の場合、ローカル・トランザクション内包は、通常、ビジネス・メソッドの終了時に終了します。
アクティビティー・セッションを使用している場合は例外です。
この場合、アクティビティー・セッションは、新規の接続を取得する前に終了しなければなりません。
ローカル・トランザクションが未指定のトランザクション・コンテキスト内で稼働するエンタープライズ Bean で発生すると、エンタープライズ Bean クライアント・オブジェクトは、ローカル・トランザクション内包の外側で、直前の黒丸で説明したメソッドを使用して、トランザクションを再試行します。ただし、ローカル・トランザクショ ン内包がサーブレットまたは JSP ファイルの一部として実行される場合に、操作を再試行できるクライアント・オブジェクトはありません。 このため、ユーザー・トランザクションに含まれる場合を除き、 サーブレットや JSP ファイルではデータベースの操作を実行しないほうがよいでしょう。
Linux システムでの不整合な接続
Linux プラットフォーム上でアプリケーション・サーバーから DB2® データベースにアクセスするときに、ループバックの設定が必要になる場合があります。
- DB2 Universal JDBC タイプ 2 ドライバーを使用した ローカル DB2 データベースへの接続
- DB2 Universal JDBC タイプ 2 ドライバーを使用した、アプリケーション・サーバーと同じマシン上 にインストールされた DB2 Connect™ を介して の DB2 for z/OS® へのアクセス。この問題は、DB2 Connect によって、 ローカル・クライアントがエージェント内での実行を制限されている場合にのみ 発生します。(つまり、DB2_IN_APP_PROCESS 設定がデフォルト値ではない場合か、設定が「Yes」の場合に発生します。この値を「No」に設定して問題をフィックスし、次の手順を実行しないようにしてください。)
'71' -SQLCC_ERR_CONN_CLOSED_BY_PARTNER and SQLCODE -XXXX
db2 catalog TCPIP node RHOST remote LHOST server 50000 db2 uncatalog db WAS db2 catalog db WAS as WASAlias at node loop authentication server //If you connect to WASAlias, it is connect through loopback; //If you connect to WAS, it is "normal" connect. db2 catalog db WASAlias as WAS at node RHOST
例: サーブレット JDBC 接続例外の処理
以下のコード例は、トランザクション管理と接続管理プロパテ ィー (オペレーション再試行など) を設定し、サーブレット JDBC トランザ クション内の不整合接続例外に対応する方法を示しています。
- サーブレットの初期化
- データ・ソースの検索
- エラー・メッセージ、接続再試行、およびトランザクション・ロールバック要件の指定
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
// Import JDBC packages and naming service packages. import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import javax.transaction.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;
public class EmployeeListTran extends HttpServlet {
private static DataSource ds = null;
private UserTransaction ut = null;
private static String title = "Employee List";
// ****************************************************************
// * Initialize servlet when it is first loaded. *
// * Get information from the properties file, and look up the *
// * DataSource object from JNDI to improve performance of the *
// * the servlet's service methods. *
// ****************************************************************
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
getDS();
}
// ****************************************************************
// * Perform the JNDI lookup for the DataSource and *
// * User Transaction objects. *
// * This method is invoked from init(), and from the service *
// * method of the DataSource is null *
// ****************************************************************
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
} catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
// ****************************************************************
// * Respond to user GET request *
// ****************************************************************
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
// Set retryCount to the number of times you would like to retry after a
// stale connection exception
int retryCount = 5;
// If the Database code processes successfully, we will set error = false
boolean error = true;
do
{
try
{
//Start a new Transaction
ut.begin();
// Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
stmt = conn.createStatement();
String query = "Select FirstNme, MidInit, LastName " +
"from Employee ORDER BY LastName";
rs = stmt.executeQuery(query);
while (rs.next()) {
employeeList.addElement(rs.getString(3) + ", "+ rs.getString(1)" + " + rs.getString(2));
}
//Set error to false to indicate successful completion of the database work
error=false;
}
catch (SQLException sqlX)
{
// Determine if the connection request timed out.
// This code works regardless of which error detection
// model is used. If exception mapping is enabled, then
// we need to look for ConnectionWaitTimeoutException.
// If exception checking is enabled, then look for
// SQLTransientConnectionException with a chained
// ConnectionWaitTimeoutException.
if ( sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time. Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool
System.out.println("Connection Wait Timeout Exception during get connection or
process SQL: " + c.getMessage());
//In general, we do not want to retry after this exception, so set retry count to 0
//and roll back the transaction
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
else if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// This exception indicates that the connection to the database is no longer valid.
//Roll back the transaction, then retry several times to attempt to obtain a valid
//connection, display an error message if the connection still can not be obtained.
System.out.println("Connection is stale: " + sc.getMessage());
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
if (--retryCount == 0) {
System.out.println("Five stale connection exceptions, displaying error page.");
}
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " + sq.getMessage());
//In general, we do not want to retry after this exception, so set retry count to 0
//and rollback the transaction
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
}
catch (NotSupportedException nse) {
//Thrown by UserTransaction begin method if the thread is already associated with a
//transaction and the Transaction Manager implementation does not support nested //transactions.
System.out.println("NotSupportedException on User Transaction begin: " + nse.getMessage());
}
catch (SystemException se) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("SystemException in User Transaction:" +se.getMessage());
}
catch (Exception e)
{
System.out.println("Exception in get connection or process SQL: " + e.getMessage());
//In general, we do not want to retry after this exception, so set retry count to 5
//and roll back the transaction
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close and
// actual connection, but releases it back to the pool for reuse.
if (rs != null)
{
try
{
rs.close();
}
catch (Exception e)
{
System.out.println("Close Resultset Exception: " + e.getMessage());
}
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " + e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close();
}
catch (Exception e)
{
System.out.println("Close connection exception: " + e.getMessage());
}
}
try
{
ut.commit();
}
catch (RollbackException re) {
//Thrown to indicate that the transaction has been rolled back rather than committed.
System.out.println("User Transaction Rolled back!" + re.getMessage());
}
catch (SecurityException se) {
//Thrown to indicate that the thread is not allowed to commit the transaction.
System.out.println("Security Exception thrown on transaction commit: " + se.getMessage());
}
catch (IllegalStateException ise) {
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception thrown on transaction commit: " + ise.getMessage());
}
catch (SystemException sye) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception thrown on transaction commit: " + sye.getMessage());
}
catch (Exception e)
{
System.out.println("Exception thrown on transaction commit: " + e.getMessage());
}
}
}
while ( error==true && retryCount > 0 );
// Prepare and return HTML response, prevent dynamic content from being cached
// on browsers.
res.setContentType("text/html");
res.setHeader("Pragma", "no-cache");
res.setHeader("Cache-Control", "no-cache");
res.setDateHeader("Expires", 0);
try
{
ServletOutputStream out = res.getOutputStream();
out.println("<HTML>");
out.println("<HEAD><TITLE>" + title + "</TITLE></HEAD>");
out.println("<BODY>");
if (error==true) {
out.println("<H1>There was an error processing this request.</H1>" +
"Please try the request again, or contact " +
" the <a href='mailto:sysadmin@my.com'>System Administrator</a>");
}
else if (employeeList.isEmpty()) {
out.println("<H1>Employee List is Empty</H1>");
}
else
{
out.println("<H1>Employee List </H1>");
for (int i = 0; i < employeeList.size(); i++) {
out.println(employeeList.elementAt(i) + "<BR>");
}
}
out.println("</BODY></HTML>");
out.close();
}
catch (IOException e) {
System.out.println("HTML response exception: " + e.getMessage());
}
}
}
例: コンテナー管理データベース・トランザクションのセッ ション Bean 用の接続例外の処理
以下のコード例は、トランザクションをロールバックし、 不整合接続例外の場合に Bean クライアントに例外を発行する方法を示して います。
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.util.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;
/*************************************************************************************
* This bean is designed to demonstrate Database Connections in a
* Container Managed Transaction Session Bean. Its transaction attribute *
* should be set to TX_REQUIRED or TX_REQUIRES_NEW. *
**************************************************************************************
*/
public class ShowEmployeesCMTBean implements SessionBean {
private javax.ejb.SessionContext mySessionCtx = null;
final static long serialVersionUID = 3206093459760846163L;
private javax.sql.DataSource ds;
//************************************************************************************
//* ejbActivate calls the getDS method, which does the JNDI lookup for the DataSource.
//* Because the DataSource lookup is in a separate method, we can also invoke it from
//* the getEmployees method in the case where the DataSource field is null.
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
getDS();
}
/**
* ejbCreate method
* @exception javax.ejb.CreateException
* @exception java.rmi.EJBException
*/
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
* ejbPassivate method
* @exception java.rmi.EJBException
*/
public void ejbPassivate() throws java.rmi.EJBException {}
/**
* ejbRemove method
* @exception java.rmi.EJBException
*/
public void ejbRemove() throws java.rmi.EJBException {}
//************************************************************************************
//* The getEmployees method runs the database query to retrieve the employees.
//* The getDS method is only called if the DataSource variable is null.
//* Because this session bean uses Container Managed Transactions, it cannot retry the
//* transaction on a StaleConnectionException. However, it can throw an exception to
//* its client indicating that the operation is retriable.
//************************************************************************************
public Vector getEmployees() throws ConnectionWaitTimeoutException, SQLException,
RetryableConnectionException
{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
if (ds == null) getDS();
try
{
// Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
stmt = conn.createStatement();
String query = "Select FirstNme, MidInit, LastName " +
"from Employee ORDER BY LastName;"
rs = stmt.executeQuery(query);
while (rs.next()) {
employeeList.addElement(rs.getString(3) + ", "+ rs.getString(1)" + " + rs.getString(2));
}
}
catch (SQLException sqlX)
{
// Determine if the connection is stale
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// This exception indicates that the connection to the database is no longer valid.
// Roll back the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Connection is stale: " + sqlX.getMessage());
System.out.println("Rolling back transaction and throwing RetryableConnectionException");
mySessionCtx.setRollbackOnly();
throw new RetryableConnectionException(sqlX.toString());
}
// Determine if the connection request timed out.
else if ( sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time. Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool
System.out.println("Connection Wait Timeout Exception during get connection or process SQL: " +
sqlX.getMessage());
throw sqlX instanceof ConnectionWaitTimeoutException ?
sqlX :
(ConnectionWaitTimeoutException) sqlX.getCause();
}
else
{
//Throwing a remote exception will automatically roll back the container managed
//transaction
System.out.println("SQL Exception during get connection or process SQL: " +
sqlX.getMessage());
throw sqlX;
}
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close and
// actual connection, but releases it back to the pool for reuse.
if (rs != null)
{
try
{
rs.close();
}
catch (Exception e)
{
System.out.println("Close Resultset Exception: " +
e.getMessage());
}
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close();
}
catch (Exception e)
{
System.out.println("Close connection exception: " + e.getMessage());
}
}
}
return employeeList;
}
/**
* getSessionContext method
* @return javax.ejb.SessionContext
*/
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
//************************************************************************************
//* The getDS method performs the JNDI lookup for the data source.
//* This method is called from ejbActivate, and from getEmployees if the data source
//* object is null.
//************************************************************************************
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
}
catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
* setSessionContext method
* @param ctx javax.ejb.SessionContext
* @exception java.rmi.EJBException
*/
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.EJBException {
mySessionCtx = ctx;
}
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is a Home interface for the Session Bean
*/
public interface ShowEmployeesCMTHome extends javax.ejb.EJBHome {
/**
* create method for a session bean
* @return WebSphereSamples.ConnPool.ShowEmployeesCMT
* @exception javax.ejb.CreateException
* @exception java.rmi.RemoteException
*/
WebSphereSamples.ConnPool.ShowEmployeesCMT create() throws javax.ejb.CreateException,
java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is an Enterprise Java Bean Remote Interface
*/
public interface ShowEmployeesCMT extends javax.ejb.EJBObject {
/**
*
* @return java.util.Vector
*/
java.util.Vector getEmployees() throws java.sql.SQLException, java.rmi.RemoteException,
ConnectionWaitTimeoutException, WebSphereSamples.ConnPool.RetryableConnectionException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Exception indicating that the operation can be retried
* Creation date: (4/2/2001 10:48:08 AM)
* @author: Administrator
*/
public class RetryableConnectionException extends Exception {
/**
* RetryableConnectionException constructor.
*/
public RetryableConnectionException() {
super();
}
/**
* RetryableConnectionException constructor.
* @param s java.lang.String
*/
public RetryableConnectionException(String s) {
super(s);
}
}
例: Bean 管理データベース・トランザクシ ョンのセッション Bean 用の接続例外の処理
以下のコード例は、不整合接続例外に対応するためのオプシ ョンを示しています。 異なるトランザクション管理と接続管理パラメーター (オペレ ーション再試行の回数と接続タイムアウト間隔など) を設定しできます。
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.util.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import javax.transaction.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;
/**********************************************************************************
* This bean is designed to demonstrate Database Connections in a *
* Bean-Managed Transaction Session Bean. Its transaction attribute *
* should be set to TX_BEANMANAGED. **********************************************************************************/
public class ShowEmployeesBMTBean implements SessionBean {
private javax.ejb.SessionContext mySessionCtx = null;
final static long serialVersionUID = 3206093459760846163L;
private javax.sql.DataSource ds;
private javax.transaction.UserTransaction userTran;
//************************************************************************************
//* ejbActivate calls the getDS method, which makes the JNDI lookup for the DataSource
//* Because the DataSource lookup is in a separate method, we can also invoke it from
//* the getEmployees method in the case where the DataSource field is null.
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
getDS();
}
/**
* ejbCreate method
* @exception javax.ejb.CreateException
* @exception java.rmi.EJBException
*/
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
* ejbPassivate method
* @exception java.rmi.EJBException
*/
public void ejbPassivate() throws java.rmi.EJBException {}
/**
* ejbRemove method
* @exception java.rmi.EJBException
*/
public void ejbRemove() throws java.rmi.EJBException {}
//************************************************************************************
//* The getEmployees method runs the database query to retrieve the employees.
//* The getDS method is only called if the DataSource or userTran variables are null.
//* If a stale connection occurs, the bean retries the transaction 5 times,
//* then throws an EJBException.
//************************************************************************************
public Vector getEmployees() throws EJBException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
// Set retryCount to the number of times you would like to retry after a
// stale connection
int retryCount = 5;
// If the Database code processes successfully, we will set error = false
boolean error = true;
if (ds == null || userTran == null) getDS();
do
{
try
{
//try/catch block for UserTransaction work
//Begin the transaction
userTran.begin();
try
{
//try/catch block for database work
//Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
stmt = conn.createStatement();
String query = "Select FirstNme, MidInit, LastName " +
"from Employee ORDER BY LastName";
rs = stmt.executeQuery(query);
while (rs.next()) {
employeeList.addElement(rs.getString(3) + ", " + rs.getString(1) + " " + rs.getString(2));
}
//Set error to false, as all database operations are successfully completed
error = false;
}
catch (SQLException sqlX)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Stale connection: " +
se.getMessage());
userTran.rollback();
if (--retryCount == 0) {
//If we have already retried the requested number of times, throw an EJBException.
throw new EJBException("Transaction Failure: " + sqlX.toString());
}
else
{
System.out.println("Retrying transaction, retryCount = " + retryCount);
}
}
else if (sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time. Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool
System.out.println("Connection request timed out: " +
sqlX.getMessage());
userTran.rollback();
throw new EJBException("Transaction failure: " + sqlX.getMessage());
}
else
{
// This catch handles all other SQL Exceptions
System.out.println("SQL Exception during get connection or process SQL: " +
sqlX.getMessage());
userTran.rollback();
throw new EJBException("Transaction failure: " + sqlX.getMessage());
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close and
// actual connection, but releases it back to the pool for reuse.
if (rs != null) {
try {
rs.close();
}
catch (Exception e) {
System.out.println("Close Resultset Exception: " + e.getMessage());
}
}
if (stmt != null) {
try {
stmt.close();
}
catch (Exception e) {
System.out.println("Close Statement Exception: " + e.getMessage());
}
}
if (conn != null) {
try {
conn.close();
}
catch (Exception e) {
System.out.println("Close connection exception: " + e.getMessage());
}
}
}
if (!error) {
//Database work completed successfully, commit the transaction
userTran.commit();
}
//Catch UserTransaction exceptions
}
catch (NotSupportedException nse) {
//Thrown by UserTransaction begin method if the thread is already associated with a
//transaction and the Transaction Manager implementation does not support nested transactions.
System.out.println("NotSupportedException on User Transaction begin: " +
nse.getMessage());
throw new EJBException("Transaction failure: " + nse.getMessage());
}
catch (RollbackException re) {
//Thrown to indicate that the transaction has been rolled back rather than committed.
System.out.println("User Transaction Rolled back!" + re.getMessage());
throw new EJBException("Transaction failure: " + re.getMessage());
}
catch (SystemException se) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("SystemException in User Transaction:" + se.getMessage());
throw new EJBException("Transaction failure: " + se.getMessage());
}
catch (Exception e) {
//Handle any generic or unexpected Exceptions
System.out.println("Exception in User Transaction: " + e.getMessage());
throw new EJBException("Transaction failure: " + e.getMessage());
}
}
while (error);
return employeeList;
}
/**
* getSessionContext method comment
* @return javax.ejb.SessionContext
*/
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
//************************************************************************************
//* The getDS method performs the JNDI lookup for the DataSource.
//* This method is called from ejbActivate, and from getEmployees if the DataSource
//* object is null.
//************************************************************************************
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
//Create the UserTransaction object
userTran = mySessionCtx.getUserTransaction();
}
catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
* setSessionContext method
* @param ctx javax.ejb.SessionContext
* @exception java.rmi.EJBException
*/
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.EJBException {
mySessionCtx = ctx;
}
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is a Home interface for the Session Bean
*/
public interface ShowEmployeesBMTHome extends javax.ejb.EJBHome {
/**
* create method for a session bean
* @return WebSphereSamples.ConnPool.ShowEmployeesBMT
* @exception javax.ejb.CreateException
* @exception java.rmi.RemoteException
*/
WebSphereSamples.ConnPool.ShowEmployeesBMT create() throws javax.ejb.CreateException,
java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is an Enterprise Java Bean Remote Interface
*/
public interface ShowEmployeesBMT extends javax.ejb.EJBObject {
/**
*
* @return java.util.Vector
*/
java.util.Vector getEmployees() throws java.rmi.RemoteException, javax.ejb.EJBException;
}
例: コンテナー管理データベース・トランザクションの BMP Bean 用の接続例外の処理
以下のコード例は、トランザクションをロールバックし、 不整合接続例外の場合に Bean クライアントに例外を発行する方法を示して います。
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2005,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.util.*;
import javax.ejb.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.websphere.rsadapter.WSCallHelper;
/**
* This is an Entity Bean class with five BMP fields
* String firstName, String lastName, String middleInit
* String empNo, int edLevel
*/
public class EmployeeBMPBean implements EntityBean {
private javax.ejb.EntityContext entityContext = null;
final static long serialVersionUID = 3206093459760846163L;
private java.lang.String firstName;
private java.lang.String lastName;
private String middleInit;
private javax.sql.DataSource ds;
private java.lang.String empNo;
private int edLevel;
/**
* ejbActivate method
* ejbActivate calls getDS(), which performs the
* JNDI lookup for the datasource.
*/
public void ejbActivate() {
getDS();
}
/**
* ejbCreate method for a BMP entity bean
* @return WebSphereSamples.ConnPool.EmployeeBMPKey
* @param key WebSphereSamples.ConnPool.EmployeeBMPKey
* @exception javax.ejb.CreateException
*/
public WebSphereSamples.ConnPool.EmployeeBMPKey ejbCreate(String empNo,
String firstName, String lastName, String middleInit, int edLevel) throws
javax.ejb.CreateException {
Connection conn = null;
PreparedStatement ps = null;
if (ds == null) getDS();
this.empNo = empNo;
this.firstName = firstName;
this.lastName = lastName;
this.middleInit = middleInit;
this.edLevel = edLevel;
String sql = "insert into Employee (empNo, firstnme, midinit, lastname, edlevel) values (?,?,?,?,?)";
try {
conn = ds.getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, empNo);
ps.setString(2, firstName);
ps.setString(3, middleInit);
ps.setString(4, lastName);
ps.setInt(5, edLevel);
if (ps.executeUpdate() != 1){
System.out.println("ejbCreate Failed to add user.");
throw new CreateException("Failed to add user.");
}
}
catch (SQLException se)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
{
// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Connection is stale: " + se.getMessage());
throw new CreateException(se.getMessage());
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " +
se.getMessage());
throw new CreateException(se.getMessage());
}
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close an
// actual connection, but releases it back to the pool for reuse.
if (ps != null)
{
try
{
ps.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " + e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close();
}
catch (Exception e)
{
System.out.println("Close connection exception: " + e.getMessage());
}
}
}
return new EmployeeBMPKey(this.empNo);
}
/**
* ejbFindByPrimaryKey method
* @return WebSphereSamples.ConnPool.EmployeeBMPKey
* @param primaryKey WebSphereSamples.ConnPool.EmployeeBMPKey
* @exception javax.ejb.FinderException
*/
public WebSphereSamples.ConnPool.EmployeeBMPKey ejbFindByPrimaryKey(WebSphereSamples.ConnPool.EmployeeBMPKey primaryKey) javax.ejb.FinderException {
loadByEmpNo(primaryKey.empNo);
return primaryKey;
}
/**
* ejbLoad method
*/
public void ejbLoad() {
try {
EmployeeBMPKey pk = (EmployeeBMPKey) entityContext.getPrimaryKey();
loadByEmpNo(pk.empNo);
} catch (FinderException fe) {
throw new EJBException("Cannot load Employee state from database.");
}
}
/**
* ejbPassivate method
*/
public void ejbPassivate() {}
/**
* ejbPostCreate method for a BMP entity bean
* @param key WebSphereSamples.ConnPool.EmployeeBMPKey
*/
public void ejbPostCreate(String empNo, String firstName, String lastName, String middleInit, int edLevel) {}
/**
* ejbRemove method
* @exception javax.ejb.RemoveException
*/
public void ejbRemove() throws javax.ejb.RemoveException {
if (ds == null)
GetDS();
String sql = "delete from Employee where empNo=?";
Connection con = null;
PreparedStatement ps = null;
try
{
con = ds.getConnection();
ps = con.prepareStatement(sql);
ps.setString(1, empNo);
if (ps.executeUpdate() != 1){
throw new EJBException("Cannot remove employee: " + empNo);
}
}
catch (SQLException se)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
{
// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Connection is stale: " + se.getMessage());
throw new EJBException(se.getMessage());
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " +
se.getMessage());
throw new EJBException(se.getMessage());
}
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close an
// actual connection, but releases it back to the pool for reuse.
if (ps != null)
{
try
{
ps.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " + e.getMessage());
}
}
if (con != null) {
try
{
con.close();
}
catch (Exception e)
{
System.out.println("Close connection exception: " + e.getMessage());
}
}
}
}
/**
* Get the employee's edLevel
* Creation date: (4/20/2001 3:46:22 PM)
* @return int
*/
public int getEdLevel() {
return edLevel;
}
/**
* getEntityContext method
* @return javax.ejb.EntityContext
*/
public javax.ejb.EntityContext getEntityContext() {
return entityContext;
}
/**
* Get the employee's first name
* Creation date: (4/19/2001 1:34:47 PM)
* @return java.lang.String
*/
public java.lang.String getFirstName() {
return firstName;
}
/**
* Get the employee's last name
* Creation date: (4/19/2001 1:35:41 PM)
* @return java.lang.String
*/
public java.lang.String getLastName() {
return lastName;
}
/**
* get the employee's middle initial
* Creation date: (4/19/2001 1:36:15 PM)
* @return char
*/
public String getMiddleInit() {
return middleInit;
}
/**
* Lookup the DataSource from JNDI
* Creation date: (4/19/2001 3:28:15 PM)
*/
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
}
catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Load the employee from the database
* Creation date: (4/19/2001 3:44:07 PM)
* @param empNo java.lang.String
*/
private void loadByEmpNo(String empNoKey) throws javax.ejb.FinderException{
String sql = "select empno, firstnme, midinit, lastname, edLevel from employee where empno = ?";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
if (ds == null) getDS();
try
{
// Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
ps = conn.prepareStatement(sql);
ps.setString(1, empNoKey);
rs = ps.executeQuery();
if (rs.next()) {
empNo= rs.getString(1);
firstName=rs.getString(2);
middleInit=rs.getString(3);
lastName=rs.getString(4);
edLevel=rs.getInt(5);
}
else
{
throw new ObjectNotFoundException("Cannot find employee number " +
empNoKey);
}
}
catch (SQLException se)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
{
// This exception indicates that the connection to the database is no longer valid.
// Roll back the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Connection is stale: " + se.getMessage());
throw new FinderException(se.getMessage());
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " +
se.getMessage());
throw new FinderException(se.getMessage());
}
}
finally
{
// Always close the connection in a finally statement to ensure
// proper closure in all cases. Closing the connection does not
// close an actual connection, but releases it back to the pool
// for reuse.
if (rs != null)
{
try
{
rs.close();
}
catch (Exception e)
{
System.out.println("Close Resultset Exception: " + e.getMessage());
}
}
if (ps != null)
{
try
{
ps.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " + e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close();
}
catch (Exception e)
{
System.out.println("Close connection exception: " + e.getMessage());
}
}
}
}
/**
* set the employee's education level
* Creation date: (4/20/2001 3:46:22 PM)
* @param newEdLevel int
*/
public void setEdLevel(int newEdLevel) {
edLevel = newEdLevel;
}
/**
* setEntityContext method
* @param ctx javax.ejb.EntityContext
*/
public void setEntityContext(javax.ejb.EntityContext ctx) {
entityContext = ctx;
}
/**
* set the employee's first name
* Creation date: (4/19/2001 1:34:47 PM)
* @param newFirstName java.lang.String
*/
public void setFirstName(java.lang.String newFirstName) {
firstName = newFirstName;
}
/**
* set the employee's last name
* Creation date: (4/19/2001 1:35:41 PM)
* @param newLastName java.lang.String
*/
public void setLastName(java.lang.String newLastName) {
lastName = newLastName;
}
/**
* set the employee's middle initial
* Creation date: (4/19/2001 1:36:15 PM)
* @param newMiddleInit char
*/
public void setMiddleInit(String newMiddleInit) {
middleInit = newMiddleInit;
}
/**
* unsetEntityContext method
*/
public void unsetEntityContext() {
entityContext = null;
}
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is an Enterprise Java Bean Remote Interface
*/
public interface EmployeeBMP extends javax.ejb.EJBObject {
/**
*
* @return int
*/
int getEdLevel() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getFirstName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getLastName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getMiddleInit() throws java.rmi.RemoteException;
/**
*
* @return void
* @param newEdLevel int
*/
void setEdLevel(int newEdLevel) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newFirstName java.lang.String
*/
void setFirstName(java.lang.String newFirstName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newLastName java.lang.String
*/
void setLastName(java.lang.String newLastName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newMiddleInit java.lang.String
*/
void setMiddleInit(java.lang.String newMiddleInit) throws java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is an Enterprise Java Bean Remote Interface
*/
public interface EmployeeBMP extends javax.ejb.EJBObject {
/**
*
* @return int
*/
int getEdLevel() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getFirstName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getLastName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getMiddleInit() throws java.rmi.RemoteException;
/**
*
* @return void
* @param newEdLevel int
*/
void setEdLevel(int newEdLevel) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newFirstName java.lang.String
*/
void setFirstName(java.lang.String newFirstName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newLastName java.lang.String
*/
void setLastName(java.lang.String newLastName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newMiddleInit java.lang.String
*/
void setMiddleInit(java.lang.String newMiddleInit) throws java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* This is a Primary Key Class for the Entity Bean
**/
public class EmployeeBMPKey implements java.io.Serializable {
public String empNo;
final static long serialVersionUID = 3206093459760846163L;
/**
* EmployeeBMPKey() constructor
*/
public EmployeeBMPKey() {
}
/**
* EmployeeBMPKey(String key) constructor
*/
public EmployeeBMPKey(String key) {
empNo = key;
}
/**
* equals method
* - user must provide a proper implementation for the equal method. The generated
* method assumes the key is a String object.
*/
public boolean equals (Object o) {
if (o instanceof EmployeeBMPKey)
return empNo.equals(((EmployeeBMPKey)o).empNo);
else
return false;
}
/**
* hashCode method
* - user must provide a proper implementation for the hashCode method. The generated
* method assumes the key is a String object.
*/
public int hashCode () {
return empNo.hashCode();
例: データ・アクセス例外の処理 - ConnectionWaitTimeoutException (JDBC API 用)
このコード例は、アプリケーション・サーバーが、 JDBC アプリケーションに ConnectionWaitTimeoutException を発行する条件を指定す る方法を示しています。
ConnectionWaitTimeoutException がキャッチされると、すべての場合においてリカバリーのために行えることはほとんどありません。
public void test1() {
java.sql.Connection conn = null;
java.sql.Statement stmt = null;
java.sql.ResultSet rs = null;
try {
// Look for datasource
java.util.Properties props = new java.util.Properties();
props.put(
javax.naming.Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
ic = new javax.naming.InitialContext(props);
javax.sql.DataSource ds1 = (javax.sql.DataSource) ic.lookup(jndiString);
// Get Connection.
conn = ds1.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from mytable where this = 54");
}
catch (java.sql.SQLException sqlX) {
if (sqlX instanceof com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException
|| sqlX instanceof java.sql.SQLTransientConnectionException
&& sqlX.getCause() instanceof com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException)
{
//notify the user that the system could not provide a
//connection to the database. This usually happens when the
//connection pool is full and there is no connection
//available for to share.
}
else
{
// handle other database problems.
}
}
finally {
if (rs != null)
try {
rs.close();
}
catch (java.sql.SQLException sqle1) {
}
if (stmt != null)
try {
stmt.close();
}
catch (java.sql.SQLException sqle1) {
}
if (conn != null)
try {
conn.close();
}
catch (java.sql.SQLException sqle1) {
}
}
}
例: データ・アクセス例外の処理 - ConnectionWaitTimeoutException (Java EE コネクター・アーキテクチャー用)
このコード例は、WebSphere Application Server が、JCA アプリケーションに ConnectionWaitTimeout 例外を発行する条件を指定する 方法を示しています。
ConnectionWaitTimeout 例外がキャッチされると、すべての場合においてリカバリーのために行えることはほとんどありません。
次のコード・フラグメントは、 Java Platform, Enterprise Edition (Java EE) コネクター・アーキテクチャー (JCA) におけるこの例外の使用方法を示しています。
/**
* This method does a simple Connection test.
*/
public void testConnection()
throws javax.naming.NamingException, javax.resource.ResourceException, com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException {
javax.resource.cci.ConnectionFactory factory = null;
javax.resource.cci.Connection conn = null;
javax.resource.cci.ConnectionMetaData metaData = null;
try {
// lookup the connection factory
if (verbose) System.out.println("Look up the connection factory...");
try {
factory =
(javax.resource.cci.ConnectionFactory) (new InitialContext()).lookup("java:comp/env/eis/Sample");
}
catch (javax.naming.NamingException ne) {
// Connection factory cannot be looked up.
throw ne;
}
// Get connection
if (verbose) System.out.println("Get the connection...");
conn = factory.getConnection();
// Get ConnectionMetaData
metaData = conn.getMetaData();
// Print out the metadata Information.
System.out.println("EISProductName" is + metaData.getEISProductName());
}
catch (com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException cwtoe) {
// Connection Wait Timeout
throw cwtoe;
}
catch (javax.resource.ResourceException re) {
// Something wrong with connections.
throw re;
}
finally {
if (conn != null) {
try {
conn.close();
}
catch (javax.resource.ResourceException re) {
}
}
}
}
例: データ・アクセス例外の処理 - DataStoreHelper でのエラー・マッピング
アプリケーション・サーバーには、さまざまなデータベース SQL エラー・コードをアプリケーション・サーバーの該当する例外にマッピングするための DataStoreHelper インターフェースがあります。
エラー・マッピングが必要なのは、同じ問題を表すと思われるものが、さまざまなデータベース・ベンダーによって、異なる SQL エラーおよびコードで提供されていることがあるためです。 例えば、失効した接続例外のコードが、データベースによって異なる場合があります。 DB2 SQLCODE が 1015、1034、1036 などの場合は、データベ ースに一時的に問題があるため、接続が使用できなくなっていることを示して います。 また、Oracle SQLCODE では 28、3113、3114 などの場合に、 同じ状況を示しています。
これらのエラー・コードを標準的な例外にマッピングすることにより整合性が保たれるため、 アプリケーションを異なるアプリケーション・サーバーのインストール間で移植することができます。次のコード・セグメントは、 エラー・マップに 2 つのエラー・コードを追加する方法を示しています。public class NewDSHelper extends GenericDataStoreHelper
{
public NewDSHelper(java.util.Properties dataStoreHelperProperties)
{
super(dataStoreHelperProperties);
java.util.Hashtable myErrorMap = null;
myErrorMap = new java.util.Hashtable();
myErrorMap.put(new Integer(-803), myDuplicateKeyException.class);
myErrorMap.put(new Integer(-1015), myStaleConnectionException.class);
myErrorMap.put("S1000", MyTableNotFoundException.class);
setUserDefinedMap(myErrorMap);
...
}
}
エラー検出モデルと呼ばれる構成オプションは、エラー・マップの使用方法を制御します。 V6 以前では、エラー検出モデルに使用可能なオプションは、例外マッピングしかありませんでした。 V7 以降では、例外検査と呼ばれる別のオプションも使用可能です。 例外マッピング・モデルでは、アプリケーション・サーバーがエラー・マップを調べて、 例外を、エラー・マップにリストされている該当する例外タイプに置換します。 例外検査モデルでは、アプリケーション・サーバーは、その固有の目的のために、やはりエラー・マップを調べますが、例外の置換は行いません。 例外マッピングを引き続き使用する場合、何も変更する必要はありません。 例外マッピングがデフォルトのエラー検出モデルです。 例外検査モデルを使用する場合は、関連リンクにある『例外チェック・モデルを使用するためのエラー検出モデルの変更』を参照してください。
データベースのデッドロックおよび外部キーの競合
特定の SQL エラー・メッセージが繰り返されるのは、例えば データベースの参照保全性違反といった問題があるためです。これを回避するには、コンテナー管理パーシスタンス (CMP) シーケンスのグループ化機能を使用します。
データベースの参照保全性違反による外部キーの競合を原因とする例外データベースの参照保全性 (RI) ポリシーは、データベース・テーブルへのデータの書き込みやデータベース・テーブルからのデータの削除の方法に関する規則を規定しており、リレーショナルの整合性を保守します。 ただし、Bean パーシスタンスを管理するためのランタイム要件によって、エンタープライズ JavaBeans (EJB) アプリケーションは RI 規則に違反し、データベースの例外を起こすことがあります。
The insert or update value of the FOREIGN KEY table1.name_of_foreign_key_constraint
is not equal to any value of the parent key of the parent table.
またはA parent row cannot be deleted because the relationship table1.name_of_foreign_key_constraint
is not equal to any value of the parent key of the parent table.
これらの例外を回避するため、エンティティー Bean が Bean 用にシーケンス・グループを定義するこ とでリレーショナル・データベース・テーブルを更新する配列を指定する必要があります。
オプティミスティック並行性制御スキームが原因で起こるデッドロックによる例外さらに、シーケンスのグループ化により、オプティミスティック並行性制御のために構成されているエンティティー Bean のトランザクション・ロールバック例外の発生を最小に抑えることができます。オプティミスティック並行性制御命令では、最大数のトランザクションが一貫してデータにアクセスできるように、最小の時間でデータベース・ロックが行われます。 このように使用可能度の高いデータベースでの並行トランザクションは、同じテーブル行のロック、およびデッドロックの作成を試みることが可能です。生じた例外は、以下 (DB2 稼働の環境で生成されたもの) と同様のメッセージを生成する可能性があります。
Unsuccessful execution caused by deadlock or timeout.
シーケンスのグループ化フィーチャーを使用して、データベースのデッドロックが起こりにくいように Bean パーシスタンスを配列します。