Exceptions concernant l'accès aux données
Tous les beans CMP (container-managed persistence) de bean enterprise de la spécification Enterprise JavaBeans (EJB) 2.x reçoivent une exception EJB standard lorsqu'une opération échoue. Les applications Java™ Database Connectivity (JDBC) reçoivent une exception SQL standard si une opération JDBC échoue. Le produit fournit des exceptions spécifiques à son adaptateur de ressources relationnelles (RRA) pour indiquer que la connexion actuellement détenue n'est plus valide.
- L'exception wait de délai de connexion indique que l'application a attendu le nombre de
secondes spécifié par le paramètre de délai de connexion et n'a pas obtenu de connexion. Cela peut arriver lorsque le pool est à sa taille maximale et que toutes les
connexions sont en cours d'utilisation par d'autres applications pendant
la durée d'attente. De plus, aucune des connexions en cours d'utilisation ne peut être partagée par l'application,
car soit les propriétés de connexion ne concordent pas, soit la connexion se trouve dans une
transaction différente.
Pour une source de données version 4.0, l'objet ConnectionWaitTimeout génère une exception qui est instanciée à partir de la classe com.ibm.ejs.cm.pool.ConnectionWaitTimeoutException.
Pour les fabriques de connexions Java 2 Connector (J2C), l'objet ConnectionWaitTimeout génère une exception de ressource de la classe com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException.
Lorsque le modèle de détection des erreurs est configuré sur le mappage des exceptions, les dernières versions des sources de données génèrent une exception SQL de la sous-classe com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException. Lorsque le modèles de détection des erreurs est configuré sur la vérification des exceptions, les dernières versions des sources de données génèrent une exception SQL de la classe java.sql.SQLTransientConnectionException avec une exception chaînée de la classe com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException.
- Lorsque le modèle de détection des erreurs est configuré sur le mappage des exceptions, l'exception de connexion périmée indique que la connexion n'est plus valide. Lorsque le modèle de détection des erreurs est configuré sur la vérification des exceptions, le pilote de périphérique JDBC génère une exception JDBC 4.0, telle que java.sql.SQLRecoverableException ou java.sql.SQLNonTransientConnectionException, ou spécifie un SQLState approprié pour indiquer que la connexion n'est plus valide. Voir la rubrique des connexions obsolètes pour plus d'informations sur ce type d'exception.
- Les entrées sont délimitées par un point-virgule (;).
- Chaque entrée est constituée d'une clé et d'une valeur, où la clé est un code d'erreur (valeur numérique) ou SQLState qui correspond à du texte entre guillemets.
- Les clés et valeurs sont séparées par = (signe égal).
"S1000"=;1062=com.ibm.websphere.ce.cm.DuplicateKeyException;"08004"=
com.ibm.websphere.ce.cm.StaleConnectionException
Vous pouvez localiser la mappe userDefinedErrorMap dans la console d'administration en sélectionnant la source de données et en configurant les propriétés personnalisées.- Connexions périmées
- Exemple : Gestion de l'exception d'accès aux données - connexion périmée
- Connexion périmée sur des systèmes Linux
- Exemple : Gestion des exceptions de connexion JDBC de servlet
- Exemple : Gestion des exceptions de connexion pour des beans de session dans des transactions de base de données gérées par conteneur
- Exemple : Gestion des exceptions de connexion pour des beans de session dans des transactions de base de données gérées par bean
- Exemple : Gestion des exceptions de connexion pour des beans BMP dans des transactions de base de données gérées par conteneur
- Exemple : Gestion de l'exception d'accès aux données ConnectionWaitTimeoutException (pour l'API JDBC)
- Exemple : Gestion de l'exception d'accès aux données - ConnectionWaitTimeoutException (pour l'architecture Java EE Connector)
- Exemple : Gestion de l'exception d'accès aux données - mappage d'erreurs dans DataStoreHelper
- Interblocage de base de données et conflits de clés externes
Connexions périmées
Ce produit fournit une sous-classe spécifique pour la classe java.sql.SQLException ; elle permet l'utilisation de la mise en pool des connexions pour accéder à la base de données relationnelle. La sous-classe ibm.websphere.ce.cm.StaleConnectionException est incluse dans la source de données WebSphere 4.0, ainsi que dans une version plus récente de la source de données, qui utilise un adaptateur de ressources relationnelles (RRA). Cette classe permet d'indiquer que la connexion actuellement suspendue n'est plus valide.
- L'application tente d'obtenir une connexion mais sans succès, comme lorsque la base de données n'est pas lancée.
- Une connexion n'est plus utilisable en raison d'une défaillance de la base de données. Lorsqu'une application tente d'utiliser une connexion qu'elle a précédemment obtenue, cette connexion n'est plus valide. Dans ce cas, toutes les connexions en cours d'utilisation par l'application peuvent présenter cette erreur lorsqu'elles tentent d'utiliser la connexion physique en échec.
- L'application tente d'utiliser une connexion, mais celle-ci est devenue orpheline (car l'application ne l'a pas utilisée dans un délai égal à deux fois la valeur du paramètre Délai d'inutilisation). Ce cas de figure s'applique uniquement aux sources de données version 4.0.
- L'application tente d'utiliser une ressource JDBC, telle qu'une instruction, obtenue sur une connexion périmée.
- Une connexion a été arrêtée par la fonction de nettoyage automatique des connexions pour les sources de données version 4.0 ; elle n'est plus utilisable. Le nettoyage automatique des
connexions est le mode standard de gestion des connexions. Ce mode signifie qu'à la fin d'une transaction, le gestionnaire de transactions
ferme toutes les connexions engagées dans cette transaction. De cette manière, on s'assure d'une part que les connexions
ne sont pas détenues trop longtemps, d'autre part que le pool n'atteint pas prématurément sa taille limite
(nombre maximal de connexions).
Toutefois, lorsque le gestionnaire de transactions ferme les connexions et renvoie la connexion dans le pool de connexions libres une fois qu'une transaction est terminée, aucune répercussion négative ne s'ensuit. Une application ne peut pas obtenir une connexion dans une transaction et de tenter de l'utiliser dans une autre transaction. Si elle tente de le faire, une exception ObjectClosedException, qui est à son tour une exception StaleConnectionException, se produit car la connexion est déjà fermée.
- Si vous paramétrez la taille minimale du pool de connexions sur 0, le pool de connexions vide est conservé lorsque le serveur d'applications est inactif pendant une période prolongée. Cela évite les connexions périmées lors des activités de maintenance sur la base de données.
- Définissez le délai d'inutilisation du pool de connexions sur une valeur inférieure au délai d'expiration du pare-feu. Ainsi, la connexion ne se périme qu'à la fin du délai d'inutilisation et reste utilisable dans le pool disponible.
- Définissez l'intervalle de régulation du pool de connexions sur une valeur inférieure au délai d'inactivité. Plus la valeur est petite, plus la fréquence de vérification par l'unité d'exécution de maintenance du pool est élevée, et plus le compteur d'inactivité est précis. Cependant, des vérifications trop rapprochées peuvent peser sur les performances.
Si vous essayez d'utiliser une connexion orpheline ou une connexion rendue indisponible par un nettoyage de connexion automatique, une exception de connexion obsolète indique que l'application a essayé d'utiliser une connexion qui a déjà été replacée dans le pool de connexions. Elle n'indique pas un véritable problème avec la connexion elle-même. Cependant, dans d'autres cas, l'exception "StaleConnection" indique que la connexion à la base de données est incorrecte, voire périmée. Lorsqu'une connexion est périmée, elle ne peut pas être récupérée et elle doit être complètement fermée plutôt que d'être réintégrée au pool de connexions libres.
Détection des connexions périméesLorsqu'une connexion à la base de données devient périmée, toute opération tentée sur cette connexion conduit au lancement d'une exception SQL par le pilote JDBC. Comme l'exception SQL est plutôt générique, elle s'accompagne de codes d'état et d'erreur que vous pouvez utiliser pour déterminer sa signification plus précise. Cependant, chaque fournisseur de base de données donne un sens différent à ces codes. C'est pourquoi l'environnement d'exécution de la fonction de mise en pool des connexions tient à jour une table indiquant quels codes SQLState et d'erreur représentent une exception StaleConnection pour chaque fournisseur de base de données pris en charge. Lorsque la fonction de mise en pool des connexions reçoit une exception SQL, elle vérifie si cette dernière se rapporte à une connexion périmée liée au serveur de base de données utilisé.
Reprise après péremption des connexions- Si ce modèle est configuré sur le mappage des exceptions, le serveur d'applications remplace l'exception générée par le pilote JDBC par "StaleConnectionException". Dans ce cas, l'application peut intercepter une exception "StaleConnection".
- Si le modèle de détection d'erreurs est défini sur la vérification des exceptions, le serveur d'applications consulte toujours la mappe d'erreurs dans le cadre de la gestion du pool de connexions, mais ne remplace pas l'exception. Dans ce cas, l'application ne devrait intercepter aucune exception "StaleConnection".
Comme il existe des différences entre ces deux modèles de détection d'erreurs, le serveur d'applications fournit une API permettant aux applications d'identifier les connexions périmées, dans un cas comme dans l'autre. Cette API se nomme com.ibm.websphere.rsadapter.WSCallHelper.getDataStoreHelper(datasource).isConnectionError(sqlexception).
Cela dit, les applications ne sont pas obligées d'identifier une exception "StaleConnection" de manière explicite. En effet, elles doivent simplement intercepter les exceptions java.sql.SQLException, sachant que l'exception "StaleConnection" or celle que génère le pilote JDBC héritent toujours de ses données. L'exception "StaleConnection", qui peut résulter de n'importe quelle méthode déclarée pour déclencher une exception SQL, est interceptée automatiquement dans le bloc catch général. Cependant, l'identification explicite des exceptions "StaleConnection" permet à une application de récupérer en cas de connexion défectueuse. Lorsque le code d'application identifie une exception "StaleConnection", il doit effectuer une procédure explicite pour récupérer, telle que la relance d'une opération dans le cadre d'une nouvelle transaction ou d'une nouvelle connexion.
Exemple : Gestion de l'exception d'accès aux données - connexion périmée
Les exemples de code qui suivent expliquent comment résoudre par programme les exceptions de connexion périmée pour différents types de clients d'accès aux données au sein de différents scénarios de transaction.
Lorsqu'une application reçoit une exception de connexion périmée dans une opération sur la base de données, cela indique que la connexion actuellement détenue n'est plus valide. Bien qu'il soit possible de recevoir une exception de connexion périmée sur une opération de base de données, son lancement se produit le plus souvent après la première obtention de la connexion. Comme les connexions sont mises en pool, une défaillance de la base de données n'est détectée que lors de l'opération qui suit immédiatement l'obtention de la connexion, car c'est à l'occasion de cette opération qu'a lieu la première tentative de communication avec la base de données. La connexion n'est identifiée comme périmée que lorsqu'une défaillance est détectée. L'exception de connexion périmée se produit moins souvent si chaque méthode qui accède à la base de données obtient une nouvelle connexion du pool.

Avant que l'application n'obtienne une nouvelle connexion pour retenter l'opération, annulez la transaction dans laquelle la connexion en échec était impliquée et démarrez une nouvelle transaction. Vous pouvez décomposer les détails dans cette section dans les catégories suivantes :
- Objets fonctionnant dans un contexte de transaction global géré par bean démarrés dans la même méthode que l'accès à la base de données
- Un servlet ou un bean session
avec transactions BMT (Bean-Managed Transactions) peut démarrer explicitement une
transaction globale en appelant la méthode begin() sur un objet
javax.transaction.UserTransaction que vous pouvez récupérer soit à partir de JNDI,
soit à partir de l'objet EJBContext du bean.
Pour valider une transaction gérée par le bean, l'application appelle la méthode commit() sur
l'objet UserTransaction. Pour annuler la transaction, l'application
appelle la méthode rollback(). Les beans entity et les beans session non-BMT ne peuvent pas
démarrer explicitement de transactions globales.
Si un objet ayant démarré explicitement une transaction BMT reçoit une exception de connexion périmée sur une opération de la base de données, fermez la connexion et annulez la transaction. A ce stade, vous pouvez décider de commencer une nouvelle transaction, d'obtenir une nouvelle connexion et de retenter l'opération.
Le fragment de code suivant montre un exemple de traitement des exceptions de connexion périmée dans ce cas de figure ://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) ;
- Objets opérant dans le contexte d'une transaction globale non commencée dans la même méthode que l'accès à la base de données.
- Lorsque l'objet qui a reçu l'exception
de connexion périmée ne contrôle pas directement la transaction, comme dans le cas
d'une transaction gérée par le conteneur, il doit marquer la transaction pour annulation, puis indiquer
à son appelant de retenter l'action dans une autre transaction. Dans la plupart des cas, vous pouvez, pour ce faire,
générer une exception de l'application qui indique de retenter
l'opération. Cependant, ce procédé n'est pas toujours autorisé et une méthode est souvent
définie pour générer une exception particulière.
C'est le cas des méthodes ejbLoad() et ejbStore()
sur un bean enterprise. Les deux exemples suivants décrivent
chacun de ces scénarios.
- Exemple 1 : La méthode d'accès à la base de données génère une exception de l'application.
- Lorsque la méthode qui accède à la base de données est libre de générer toute exception nécessaire,
le mieux est d'intercepter l'exception de connexion périmée et de générer une exception
de l'application que vous pouvez interpréter pour relancer la méthode. L'exemple suivant montre un client d'EJB qui appelle une méthode sur un bean entity
avec la démarcation de transaction TX_REQUIRED, ce qui signifie que le conteneur
commence une transaction globale lorsque la méthode insertValue() est appelée :
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 obtient d'abord un bean MyEJB à partir de l'interface home, laquelle est supposée avoir été précédemment obtenue à partir de JNDI (Java Naming and Directory Interface). Il appelle ensuite la méthode insertValue() sur ce bean. Cette méthode obtient une connexion et tente d'insérer une valeur dans une table. Si l'une des méthodes échoue avec une exception de connexion périmée, insertValue() marque la transaction rollbackOnly (ce qui oblige l'appelant à annuler cette transaction) et génère une nouvelle exception retryable connection en nettoyant préalablement les ressources. L'exception de connexion pouvant être réessayée est simplement une exception définie par l'application qui indique à l'appelant de retenter la méthode. L'appelant contrôle l'exception de connexion pouvant être réessayée et, si elle est interceptée, il relance la méthode. Dans cet exemple, étant donné que le conteneur commence et termine la transaction, aucune gestion de transaction n'est nécessaire, tant au niveau du client que du serveur. Bien sûr, le client pourrait démarrer une transaction gérée par le bean et le comportement serait toujours le même, à condition qu'il ait également validé ou annulé la transaction.
- Exemple 2 : La méthode d'accès à la base de données génère une exception onlyRemote ou une exception EJB.
- Toutes les méthodes ne sont pas autorisées à émettre des exceptions définies par l'application. Si vous utilisez la persistance BMP, vous stockez l'état du bean à l'aide des méthodes
ejbLoad() et ejbStore(). Or, les seules exceptions que peuvent émettre
ces méthodes sont java.rmi.Remote et javax.ejb.EJB,
si bien que vous ne pouvez pas utiliser de mécanisme analogue à celui de
l'exemple précédent.Si vous utilisez la persistance CMP, le conteneur gère la persistance du bean et c'est donc lui qui "voit" l'exception de connexion périmée. Si une connexion périmée est détectée, l'exception renvoyée au client est une exception distante et un simple bloc catch ne suffit donc pas. Il existe pourtant un moyen de déterminer si la cause racine d'une exception distante est une exception de connexion périmée. Lorsqu'une exception distante est générée pour encapsuler une autre exception, l'exception d'origine est généralement conservée. Toutes les instances d'exception distante ont une propriété "detail" qui est du type java.lang.Throwable. Grâce à cette propriété, vous pouvez remonter jusqu'à l'exception d'origine et, s'il s'agit d'une exception de connexion périmée, retenter la transaction. En réalité, lorsque l'une de ces exceptions distantes passe d'une API JVM (Java Virtual Machine) à une autre, la propriété "detail" est perdue. Il est donc préférable de démarrer une transaction dans le même serveur que celui où l'accès à la base de données a lieu. Pour cette raison, l'exemple suivant montre un bean entity auquel accède un bean session avec une démarcation de transaction gérée par le 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 } } } }
Dans mySessionBMTMethod() de l'exemple précédent :- Le bean session obtient d'abord un objet UserTransaction du contexte de session, puis il commence une transaction globale.
- Ensuite, il appelle une méthode sur le bean entity, ce qui provoque l'appel de la méthode ejbLoad(). Si ejbLoad() s'exécute correctement, le client valide la transaction, ce qui déclenche l'appel d'ejbStore().
- Dans ejbStore(), l'unité d'exécution d'entité obtient une connexion et écrit son état dans la base de données ; si la connexion extraite est périmée, la transaction est marquée rollbackOnly et une nouvelle EJBException qui encapsule RetryableConnectionException est émise. Cette exception est alors interceptée par le client, qui nettoie les ressources JDBC, annule la transaction et appelle la méthode causedByStaleConnection(), qui détermine si une exception de connexion périmée est "cachée" quelque part dans cette exception.
- Si la méthode renvoie "true", le fanion retry est positionné à "true" et la transaction est retentée ; sinon, l'exception est de nouveau transmise à l'appelant.
- La méthode causedByStaleConnection() examine la chaîne d'attributs de la propriété "detail" pour trouver l'exception d'origine. Le temps que l'exception parvienne finalement au client, plusieurs autres encapsulations d'exceptions peuvent se produire. Aussi, la méthode continue à chercher jusqu'à ce qu'elle trouve une exception de connexion périmée et renvoie true ; sinon, il n'y a pas d'exception de connexion périmée dans la liste et la méthode renvoie false.
- Si vous parlez à un bean CMP et non pas à un bean BMP, le bean session est identique. La méthode ejbStore() du bean CMP serait vraisemblablement vide et le conteneur après l'avoir appelée assurerait la persistance du bean avec le code généré.
- Si une exception de connexion périmée se produisait lors de l'opération de persistance, elle serait encapsulée avec une exception distante et renvoyée à l'appelant. Comme précédemment, la méthode causedByStaleConnection() examinerait la chaîne d'exceptions et trouverait l'exception d'origine, qui serait une exception de connexion périmée.
- Objets fonctionnant dans un contexte de transaction local
- Lorsqu'une opération
sur la base de données a lieu en dehors du contexte d'une transaction globale, une transaction locale
est implicitement commencée par le conteneur.
C'est le cas des servlets et des JSP qui ne commencent
pas les transactions avec l'interface UserTransaction, ainsi que des Enterprise JavaBeans
qui s'exécutent dans un contexte de transaction non spécifié. Comme avec les
transactions globales, vous devez annuler la transaction locale avant de retenter l'opération. Dans tous ces cas, le confinement de transaction locale (LTC) se termine généralement lorsque la méthode
métier prend fin. La seule exception à cette règle est le cas où vous utilisez des
sessions d'activité. Vous devez en effet mettre fin à la session d'activité avant de tenter
d'obtenir une nouvelle connexion.
Lorsque la transaction locale a lieu dans un EJB s'exécutant dans un contexte de transaction non spécifié, l'objet client de l'EJB, situé en dehors du confinement de la transaction locale, peut utiliser la technique décrite précédemment pour retenter la transaction. Cependant, lorsque le confinement de la transaction locale se situe dans le cadre d'un servlet ou d'un fichier JSP, il n'y a pas d'objet client disponible pour retenter l'opération. C'est pourquoi il est conseillé d'éviter les opérations sur la base de données dans les servlets et les fichiers JSP, à moins qu'elles ne fassent partie d'une transaction de l'utilisateur.
Connexion périmée sur des systèmes Linux
Vous devez définir un un bouclage pour accéder aux bases de données DB2 depuis le serveur d'applications sur une plateforme Linux.
- Utilisation du pilote JDBC DB2 Universal de type 2 pour se connecter à la base de données DB2 locale
- Utilisation du pilote JDBC DB2 Universal de type 2 pour se connecter à DB2 for z/OS au moyen d'une installation DB2 Connect située sur la même machine que le serveur d'applications. Cet incident ne se produit que si DB2 Connect limite l'exécution des clients locaux au sein d'un agent. (c'est-à-dire si DB2_IN_APP_PROCESS n'est pas la valeur par défaut, ou si la valeur est Yes. Définissez la valeur sur No afin de résoudre le problème et d'éviter d'avoir à réaliser les opérations suivantes.)
'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 //Si vous vous connectez à WASAlias, faites-le par bouclage ; //Si vous vous connectez à WAS, effectuez une connexion "normale". db2 catalog db WASAlias as WAS at node RHOST
Exemple : Gestion des exceptions de connexion JDBC de servlet
L'exemple de code suivant indique comment définir les propriétés de gestion de transaction et de gestion de connexion comme les relances d'opérations, afin de résoudre les exceptions de connexion périmée au sein d'une transaction JDBC de servlet.
- il initialise un servlet
- il recherche une source de données
- il spécifie les messages d'erreur, le nombre de tentatives de connexion et les conditions requises pour les annulations de transaction
//===================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());
}
}
}
Exemple : Gestion des exceptions de connexion pour des beans de session dans des transactions de base de données gérées par conteneur
L'exemple de code suivant indique la manière d'annuler des transactions et d'émettre des exceptions au client de bean dans le cas d'exceptions de connexion périmées.
//===================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);
}
}
Exemple : Gestion des exceptions de connexion pour des beans de session dans des transactions de base de données gérées par bean
L'exemple de code suivant présente les différentes options qui s'offrent à vous pour résoudre les exceptions de connexion périmées. Vous pouvez définir différents paramètres de gestion des transactions et des connexions, tels que le nombre de relances des opérations et le délai d'expiration des connexions.
//===================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;
}
Exemple : Gestion des exceptions de connexion pour des beans BMP dans des transactions de base de données gérées par conteneur
L'exemple de code suivant indique la manière d'annuler des transactions et d'émettre des exceptions au client de bean dans le cas d'exceptions de connexion périmées.
//===================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();
Exemple : Gestion de l'exception d'accès aux données ConnectionWaitTimeoutException (pour l'API JDBC)
Cet échantillon de code démontre comment spécifier les conditions dans lesquelles le serveur d'applications émet l'exception ConnectionWaitTimeoutException pour une application JDBC.
Dans tous les cas où l'exception ConnectionWaitTimeoutException est interceptée, la récupération est pratiquement impossible.
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) {
}
}
}
Exemple : Gestion de l'exception d'accès aux données - ConnectionWaitTimeoutException pour Java EE Connector Architecture
Cet échantillon de code démontre comment spécifier les conditions dans lesquelles WebSphere Application Server émet l'exception ConnectionWaitTimeout pour une application JCA.
Dans tous les cas où l'exception ConnectionWaitTimeout est interceptée, la récupération est pratiquement impossible.
Le fragment de code suivant explique comment utiliser cette exception dans l'architecture Java Platform, Enterprise Edition (Java EE) Connector Architecture (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) {
}
}
}
}
Exemple : Gestion de l'exception d'accès aux données - mappage d'erreurs dans DataStoreHelper
Le serveur d'applications fournit une interface DataStoreHelper qui permet de mapper différents codes d'erreur SQL de base de données vers les exceptions appropriées du serveur d'applications.
Le mappage d'erreurs est nécessaire car les différents fournisseurs de bases de données fournissent parfois des codes et des erreurs SQL différents qui ont pourtant la même signification. Par exemple, l'exception de connexion périmée est associée à différents codes suivant la base de données utilisée. Ainsi, dans DB2, les codes SQL 1015, 1034, 1036, etc. indiquent que la connexion n'est plus disponible en raison d'un problème temporaire affectant la base de données. Les SQLCODE Oracle 28, 3113, 3114, etc., indiquent la même situation.
Mapper ces codes d'erreur vers des exceptions standard permet la cohérence qui assure la compatibilité (portabilité) des applications entre différentes installations du serveur d'applications. Le segment de code suivant illustre comment ajouter deux codes d'erreur à la mappe d'erreurs :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);
...
}
}
L'option de configuration Modèle de détection des erreurs contrôle l'utilisation de la mappage d'erreurs. Dans les versions 6 et antérieures, seule l'option de mappage des exceptions était disponible pour le modèle de détection d'erreurs. Dans les versions 7 et ultérieures, une autre option de contrôles des exceptions est disponible. Dans le modèle de mappage des exceptions, le serveur d'applications consulte la mappe d'erreurs et remplace les exceptions par le type d'exception correspondant répertorié dans la mappe d'erreurs. Dans le modèle de contrôle des exceptions, le serveur d'applications consulte toujours la mappe d'erreurs pour ses propres besoins mais ne remplace pas les exceptions. Si vous voulez continuer à utiliser le mappage d'exceptions, ne changez rien. Le mappage d'exceptions est le modèle de détection d'erreurs par défaut. Si vous voulez utiliser le modèle de vérification des exceptions, voir "Modification du modèle de détection des erreurs pour utiliser le modèle de vérification des exceptions" dans les liens associés.
Interblocage de base de données et conflits de clés externes
La répétition de certains messages d'erreur SQL est symptomatique de certains problèmes, tels que la violation d'intégrité référentielle de la base de données, que vous pouvez éviter en utilisant la fonction de regroupement en séquence CMP (Container Managed Persistence : persistance gérée par conteneur).
Exceptions générées par des conflits de clés externes suite à des violations d'intégrité référentielle de base de donnéesUne règle d'intégrité référentielle (RI) définit comment placer des données dans les tables de la base de données et comment les supprimer pour une cohérence relationnelle. Les conditions d'exécution pour la gestion de la persistance des beans, toutefois, peut amener une application JavaBeans (EJB) à violer les règles RI, ce qui peut générer des exceptions de base de données.
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.
ouA 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.
Pour éviter ces exceptions, vous devez désigner l'ordre dans lequel les beans entity mettent à jour les tables de base de données relationnelles en définissant des groupes de séquence pour ces beans.
Exceptions résultant d'interblocages provoqués par des schémas de contrôle des accès concurrents optimisteDe plus, le regroupement en séquence peut réduire les exceptions d'annulation de transaction pour les beans entity configurés pour le contrôle des accès simultanés optimiste. Le contrôle des accès simultanés optimiste bloque la base de données peu de temps, ainsi un grand nombre de transactions peut avoir accès de manière cohérente aux données. Dans une base de données très disponible, les transactions simultanées peuvent tenter de verrouiller la même ligne de table et créer un interblocage. Les exceptions résultantes peuvent générer des messages similaires aux messages suivants (générés dans un environnement exécutant DB2) :
Unsuccessful execution caused by deadlock or timeout.
Utilisez la fonction de regroupement en séquence pour organiser la persistance des beans afin qu'il y ait moins de risque d'interblocage dans la base de données.