Descripteurs de connexions
Un descripteur (handle) de connexion est une représentation d'une connexion physique. Pour pouvoir utiliser une ressource dorsale, telle qu'une base de données relationnelle dans WebSphere Application Server, vous devez obtenir une connexion à cette ressource. Lorsque vous appelez la méthode getConnection(), vous obtenez en retour un descripteur de connexion. Le descripteur n'est pas la connexion physique. Cette dernière est gérée par le gestionnaire de connexions.
Il existe deux configurations majeures qui ont un impact sur l'utilisation et le comportement des descripteurs de connexions. La première est l'élément res-sharing-scope, qui est défini par l'élément resource-ref utilisé pour rechercher la source de données (DataSource) ou la fabrique de connexions (ConnectionFactory). Cette propriété indique au gestionnaire de connexions si la connexion concernée peut être partagée ou non.
- obtient une connexion ;
- fait son travail ;
- valide le travail (si nécessaire) ;
- ferme la connexion.
- obtient une connexion ;
- démarre une transaction globale ;
- accomplit un travail sur la connexion ;
- valide la transaction globale ;
- accomplit un autre travail sur la connexion.
- Le support des descripteurs mis en cache nécessite un surcroît de gestion qui peut affecter les performances. Par exemple, dans une application JDBC, Statements, PreparedStatements et ResultSets sont fermés implicitement après la fin d'une transaction, mais la connexion demeure valide.
- Il est conseillé de ne pas mettre en cache les connexions au-delà des limites des transactions lorsqu'il s'agit de connexions partageables. Dans ce cas, le modèle "obtenir/utiliser/fermer" est préférable.
- La mise en cache des descripteurs de connexion dans des méthodes de servlet est limitée aux ressources JDBC et JMS (Java™ Message Service). les descripteurs de connexion des autres ressources non relationnelles, telles que les objets CICS (Customer Information Control System) ou IMS, ne sont actuellement pas mises en cache dans un servlet. Vous devez obtenir, utiliser et fermer le descripteur de connexion dans chaque appel de méthode. (Cette restriction ne s'applique qu'aux servlets à unité d'exécution simple car les servlets à plusieurs unités d'exécution ne permettent pas la mise en cache de descripteurs de connexion.)
- Vous ne pouvez pas transmettre un descripteur de connexion entre une instance client d'accès aux données et une autre instance client. La transmission entre des instances client crée une situation problématique car une instance utilise un descripteur de connexion référencé par une autre instance. Cette relation ne peut générer que des problèmes car le code de gestion du descripteur traite les tâches pour chaque instance client séparément. Les transmissions de descripteurs de connexion créent donc des scénarios qui déclenchent des exceptions.
Exemple :
- Le code d'application d'une instance client qui reçoit un descripteur transmis ferme le descripteur.
- Si l'instance client qui détient la référence initiale au descripteur tente de le récupérer, le serveur d'applications génère une exception.
Le fragment de code suivant illustre le modèle de mise en cache des connexions.
Connection conn = ds.getConnection();
ut.begin();
conn.prepareStatement("....."); // La connexion s'exécute en mode transaction globale
...
ut.commit();
conn.prepareStatement("....."); // La connexion est toujours valide mais s'exécute en mode autoCommit(True) ;
...
Connexions non partageables
Certaines caractéristiques des descripteurs de connexions obtenus avec un élément res-sharing-scope ayant pour valeur unshareable (non partageable) sont décrites ci-après.- Avantages possibles des connexions non partagées
- Votre application entretient toujours un lien direct avec une connexion physique (connexion gérée).
- Il existe toujours une relation univoque entre le descripteur de connexion et la connexion gérée.
- Dans la plupart des cas, la connexion ne se ferme pas tant que l'application ne la ferme pas elle-même.
- Vous pouvez utiliser un descripteur de connexion non partagée et mis en cache dans plusieurs transactions successives.
- Les connexions non partagées peuvent offrir un gain de performances dans certaines situations dans lesquelles les descripteurs sont mis en cache. L'utilisation d'une connexion non partagée avec mise en cache de son descripteur est moins coûteuse en temps système, car il n'est pas nécessaire de dissocier le descripteur de la connexion gérée (physique) à la fin de la transaction.
- Inconvénients possibles des connexions non partagées
- Utilisation inefficace de vos ressources de connexion. Par exemple, si au sein d'une même transaction vous obtenez plusieurs connexions (avec les mêmes propriétés) utilisant la même source de données ou fabrique de connexions (même référence de ressource), l'utilisation de connexions non partageables conduit à la "consommation" de plusieurs connexions physiques.
- Connexions gâchées. Il est important de ne pas maintenir le descripteur de connexion ouvert plus longtemps que nécessaire (c'est ce qui se passe si votre application omet d'appeler la méthode close()). Tant qu'une connexion non partageable est ouverte, la connexion physique n'est disponible pour aucun autre composant, même si votre application n'est pas en train d'utiliser cette connexion. A l'inverse d'une connexion partageable, un connexion non partageable n'est pas fermée à la fin d'un appel de transaction ou de servlet.
- Remarques sur les blocages. Selon la façon dont vos composants interagissent avec la
base de données dans une transaction, l'utilisation de connexions non partagées peut
engendrer un blocage dans la base de données. Par exemple, au sein de la même
transaction, le composant A obtient une connexion à la source de données X et met
à jour la table 1, puis appelle le composant B qui obtient une connexion à la source
de données X et met à jour/lit la table 1 (ou même pire, la même ligne que le
composant A). Dans certains cas, selon la base de données
utilisée, son schéma de verrouillage et le niveau d'isolement de la transaction, un
blocage peut survenir.
Dans le même cas de figure, mais avec une connexion partagée, aucun blocage ne se produit, car tout le travail est accompli sur la même connexion. Lorsque vous écrivez du code qui utilise des connexions partagées, il est important de noter que vous utilisez une stratégie qui appelle l'exécution de plusieurs tâches élémentaires sur la même connexion, voire au sein de la même transaction. Si vous décidez d'utiliser une connexion non partageable, vous devez définir correctement la valeur de la propriété Nombre maximal de connexions dans la fabrique de connexions ou la source de données. Une exception peut être générée pour les demandes de connexion en attente si vous dépassez la valeur du nombre maximal de connexions, et les connexions non partageables ne se ferment pas tant que le délai d'attente de connexion n'a pas été dépassé.
Connexions partageables
Certaines caractéristiques des descripteurs de connexions obtenus avec un élément res-sharing-scope ayant pour valeur shareable (partageable) sont décrites ci-après.- Avantages possibles des connexions partagées
- Dans une instance de partage de connexion, les composants d'application peuvent partager une connexion gérée (physique) avec un ou plusieurs descripteurs de connexions en fonction de la façon dont le descripteur est obtenu et des propriétés de connexion utilisées.
- Elles peuvent utiliser les ressources plus efficacement. Les connexions partageables
ne sont pas valides en dehors de leur limite de partage. Pour cette raison, à la fin d'une
limite de partage (telle qu'une transaction), le descripteur de connexion n'est plus associé
à la connexion gérée qu'il utilisait dans cette limite de partage (cela s'applique uniquement
lors de l'utilisation du modèle "descripteur mis en cache"). La connexion gérée est
restituée au pool de connexions disponibles pour être réutilisée. Les ressources de
connexion ne sont pas retenues au-delà de la fin de la portée de partage utilisée.
Si le modèle "descripteur mis en cache" est utilisé, le contexte d'exécution du serveur d'applications s'assure qu'à la prochaine utilisation du descripteur dans une nouvelle portée de partage, il sera réassocié à une connexion gérée appropriée à cette nouvelle portée et utilisera les mêmes propriétés que celles avec lesquelles il a été obtenu la première fois. Souvenez-vous qu'il est préférable de ne pas modifier les propriétés sur une connexion partageable. En effet, si des propriétés sont modifiées, d'autres composants qui partagent la même connexion peuvent être confrontés à un comportement inattendu. De plus, en cas d'utilisation de descripteurs mis en cache, la valeur de la propriété modifiée peut ne pas être conservée après un changement de portée de partage.
- Inconvénients possibles des connexions partagées
- Le partage dans un composant unique (tel qu'un bean enterprise et ses objets Java associés) n'est pas toujours pris en charge.
La spécification actuelle laisse aux
adaptateurs de ressources le choix de n'autoriser qu'une seul descripteur de connexion actif à la fois. Si un adaptateur de ressources choisit d'implémenter cette option, le scénario suivant entraînera la génération d'une exception de descripteur non valide : un composant utilisant des connexions partageables obtient une connexion et l'utilise. Sans fermer cette connexion, le composant appelle une classe utilitaire (objet Java) qui obtient un descripteur de connexion pour la même connexion gérée et l'utilise. Etant donné que l'adaptateur de ressources n'autorise qu'un descripteur actif à la fois, le premier descripteur de connexion n'est plus valide. Si l'objet utilitaire revient sans fermer son descripteur, le premier descripteur n'est pas valide et toute tentative d'utilisation de ce dernier entraîne la génération d'une exception.Remarque : Cette exception se produit uniquement en cas d'appel d'un objet utilitaire (objetJava).
Tous les adaptateurs de ressources n'ont pas cette limite ; cela ne se produit que dans certaines implémentations. L'adaptateur RRA ( Relational Resource Adapter) de WebSphere n'a pas cette limite. Aucune source de données utilisée via l'adaptateur RRA n'aura cette limite. Si vous rencontrez un adaptateur de ressources ayant cette limite, vous pouvez vous en affranchir en sérialisant l'accès à la connexion gérée. Si vous fermez toujours votre descripteur de connexion avant d'en obtenir un autre (ou avant d'appeler un code qui obtient un autre descripteur), et si vous le fermez toujours avant le retour d'une méthode, vous pouvez faire en sorte que deux éléments de code partagent la même connexion gérée. Cette connexion ne peut tout simplement pas être utilisée pour les deux événements en même temps.
- Une exception est générée si vous tentez de changer le niveau d'isolement sur une connexion JDBC partageable dans une transaction globale. Pour correctement obtenir des connexions avec des niveaux d'isolement de transaction différents, vous devez configurer la référence de ressource étendue d'IBM®.
- Une application n'est pas autorisée à fermer le descripteur d'une connexion partageable et une erreur se produit si elle tente de le faire. Cependant, cette limite n'est pas importante dans la mesure où vous utilisez l'adaptateur de ressources relationnelles (RRA) de WebSphere.
- Le partage dans un composant unique (tel qu'un bean enterprise et ses objets Java associés) n'est pas toujours pris en charge.
La spécification actuelle laisse aux
adaptateurs de ressources le choix de n'autoriser qu'une seul descripteur de connexion actif à la fois.
Optimisation de l'association des connexions différées
Le gestionnaire de connexions J2C, Java EE Connector (Java Platform, Enterprise Edition) a implémenté la prise en charge des descripteurs intelligents. Cette technologie permet d'allouer un descripteur de connexion à une application bien que la connexion gérée associée à ce descripteur de connexion soit utilisée par d'autres applications (en supposant que cette connexion ne soit pas utilisée par l'application initiale). Ce concept fait partie de la spécification Java EE Connector Architecture (JCA) 1.5. (Vous le trouverez dans le document de la spécification JCA 1.5, à la section intitulée "Lazy Connection Association Optimization.") La prise en charge des descripteurs intelligents permet désormais d'utiliser une méthode sur l'objet ConnectionManager, la méthode LazyAssociatableConnectionManager(), ainsi qu'une nouvelle interface de marqueur, la classe DissociatableManagedConnection. Vous devez configurer le fournisseur de l'adaptateur de ressources pour rendre cette fonctionnalité disponible dans votre environnement. (Dans le cas de l'adaptateur RRA, WebSphere Application Server est lui-même le fournisseur.) Le fragment de code suivant indique comment inclure la prise en charge des descripteurs intelligents :package javax.resource.spi;
import javax.resource.ResourceException;
interface LazyAssociatableConnectionManager { // application server
void associateConnection(
Object connection, ManagedConnectionFactory mcf,
ConnectionRequestInfo info) throws ResourceException;
}
interface DissociatableManagedConnection { // resource adapter
void dissociateConnections() throws ResourceException;
}
Cette interface DissociatableManagedConnection introduit un autre état de l'objet Connection : l'état inactif. Une connexion peut désormais être active, fermée et inactive. L'objet de connexion passe à l'état inactif lorsqu'un objet ManagedConnection correspondant est nettoyé. La connexion reste inactive jusqu'à ce qu'un composant d'application tente de le réutiliser. L'adaptateur de ressources rappelle alors le gestionnaire de connexions pour réassocier la connexion à un objet ManagedConnection actif.