Utilisation du service de requête dynamique

Parfois, dans le processus de développement, il est préférable de faire appel au service de requête dynamique plutôt qu'au service de requête EJB normale (Enterprise JavaBeans), également appelée requête de déploiement. Pendant les tests, par exemple, le service de requête dynamique peut être utilisé lors de l'exécution de l'application. Vous ne serez donc pas obligé de redéployer votre application.

Pourquoi et quand exécuter cette tâche

Voici la liste des principales raisons pour lesquelles il est préférable de faire appel au service de requête dynamique plutôt qu'au service de requête EJB normale :
  • Vous devez définir une requête pour l'exécution de l'application et non pour le déploiement.
  • Vous devez renvoyer plusieurs zones CMP ou CMR à partir d'une requête (un seul élément peut être indiqué dans la clause SELECT pour les requêtes de déploiement). Pour plus d'informations, voir la rubrique initulée Exemple : Requêtes EJB.
  • Vous souhaiter renvoyer une expression calculée dans la requête.
  • Vous voulez utiliser des méthodes d'objet et de bean dans l'instruction de requête. Pour plus d'informations, voir la rubrique intitulée Expressions de chemin.
  • Vous voulez tester de manière interactive une requête EJB au cours du développement sans devoir redéployer l'application à chaque fois que vous mettez à jour une requête de recherche ou de sélection.

L'API de requête dynamique est un bean session sans état. son utilisation est similaire à celle de n'importe quel autre bean d'application EJB J2EE. Il est inclus dans com.ibm.websphere.ejbquery du module de l'API.

Le bean de requête dynamique dispose à la fois d'une interface distante et d'une interface locale. Si vous voulez renvoyer des références d'EJB distantes à partir de la requête, ou si l'instruction de la requête contient des méthodes distantes, vous devez utiliser l'interface distante de la requête :

remote interface = com.ibm.websphere.ejbquery.Query
interface home distante = com.ibm.websphere.ejbquery.QueryHome

Si vous voulez renvoyer des références d'EJB locales à partir de la requête, ou si l'instruction de la requête contient des méthodes locales, vous devez utiliser l'interface locale de la requête :

local interface = com.ibm.websphere.ejbquery.QueryLocal
interface home locale = com.ibm.websphere.ejbquery.QueryLocalHome

Etant donné qu'elle utilise moins de mémoire du serveur d'applications, l'interface locale garantit de meilleures performances d'EJB globales que l'interface distante.

Procédure

  1. Vérifiez que le fichier d'application query.ear est installé sur le serveur d'applications sur lequel votre application doit être exécutée, si ce serveur est différent du serveur d'applications par défaut créé à l'installation du produit.
    Le fichier query.ear se trouve dans le répertoire racine_serveur_app, où <WAS_HOME> est l'emplacement de WebSphere Application Server. Le programme d'installation du produit installe le fichier query.ear sur le serveur d'applications par défaut avec le nom JNDI
    com/ibm/websphere/ejbquery/Query
    (vous, ainsi que l'administrateur système, avez la possibilité de modifier ce nom).
  2. Configurez l'autorisation pour les méthodes executeQuery(), prepareQuery() et executePlan() dans les interfaces de requête distante et locale pour contrôler l'accès aux données critiques (cette étape est nécessaire uniquement si votre application exige une sécurité).

    Etant donné que vous ne pouvez pas contrôler l'utilisation des noms ASN et des zones CMP ou CMR dans une requête EJB dynamique, vous, ou l'administrateur système, devez mettre en place des restrictions relatives à l'emploi des méthodes. Si, par exemple, un utilisateur est autorisé à exécuter la méthode executeQuery, il peut exécuter toute requête dynamique valide. Dans un environnement de production, vous devez restreindre l'accès aux méthodes de l'interface de requête distante.

  3. Rédigez la requête dynamique dans le code du client d'application. Inspirez-vous des rubriques d'exemple suivantes qui indiquent les instructions d'importation à employer : exemple d'utilisation de l'interface distante pour une requête dynamique et exemple d'utilisation de l'interface locale pour une requête dynamique.
  4. Si le bean CMP sur lequel vous souhaitez lancer la requête se trouve sur un autre module, vous devez :
    1. effectuer une recherche à distance sur query.ear
    2. mappper le fichier query.ear vers le serveur sur lequel le bean CMP est installé.
  5. Compilez et exécutez le programme client en plaçant le fichier qryclient.jar dans le chemin de classes.

Exemple

Utilisation de l'interface distante pour une requête dynamique.

Lorsque vous exécutez une requête EJB (Enterprise JavaBeans) dynamique via l'interface distante, vous appelez la méthode executeQuery sur l'interface Query. La méthode executeQuery est dotée de l'attribut de transaction REQUIRED pour cette interface ; il n'est donc pas nécessaire d'établir de manière explicite un contexte de transaction pour l'exécution de la requête.

Lorsque vous exécutez une requête EJB (Enterprise JavaBeans) dynamique via l'interface distante, vous appelez la méthode executeQuery sur l'interface Query. La méthode executeQuery est dotée de l'attribut de transaction REQUIRED pour cette interface ; il n'est donc pas nécessaire d'établir de manière explicite un contexte de transaction pour l'exécution de la requête.

Commencez par les instructions d'importation suivantes :

import com.ibm.websphere.ejbquery.QueryHome;
import com.ibm.websphere.ejbquery.Query;
import com.ibm.websphere.ejbquery.QueryIterator;
import com.ibm.websphere.ejbquery.IQueryTuple;
import com.ibm.websphere.ejbquery.QueryException;

Rédigez ensuite les instructions de requête sous forme d'une chaîne, comme dans l'exemple suivant qui permet d'extraire les noms et les références d'EJB de salariés sous-payés :

String query = 
"select e.name as name , object(e) as emp from EmpBean e where e.salary < 50000"; 

Créez un objet Query à l'aide d'une référence issue de la classe QueryHome (cette classe définit la méthode executeQuery). A noter que dans un souci de simplicité, l'exemple qui suit emploie le nom JNDI de la requête dynamique pour l'objet Query :

InitialContext ic =  new InitialContext(); 

Object obj =  ic.lookup("com/ibm/websphere/ejbquery/Query");

QueryHome  qh = 
 ( QueryHome) javax.rmi.PortableRemoteObject.narrow( obj, QueryHome.class );
Query qb = qh.create();

Vous devez ensuite préciser une taille maximale de l'ensemble de résultats de la requête, définie dans l'objet QueryIterator, qui est inclus dans la classe QueryIterator. Cette classe est comprise dans le package de l'API QueryIterator. Cet exemple définit une taille maximale de l'ensemble de résultats de 99 :

QueryIterator it = qb.executeQuery(query, null, null ,0, 99 );
L'itérateur contient une collection d'objets IQueryTuple, qui sont des enregistrements des valeurs de collection renvoyées Selon les critères de l'instruction de requête de cet exemple, chaque nuplet de ce scénario contient une valeur name et une valeur object(e). Pour afficher le contenu des résultats de la requête, utilisez le code suivant :
while (it.hasNext() ) { 
	IQueryTuple tuple = (IQueryTuple) it.next();
	System.out.print( it.getFieldName(1) );
	String s = (String) tuple.getObject(1);
	System.out.println( s);
	System.out.println( it.getFieldName(2) );
	Emp e = ( Emp) javax.rmi.PortableRemoteObject.narrow( tuple.getObject(2), Emp.class );
	System.out.println( e.getPrimaryKey().toString());
}
Ce programme peut générer une sortie similaire à celle présentée ci-dessous :
name Bob 
emp 1001
name Dave
emp 298003
...
Il convient pour terminer, d'intercepter et de traiter les exceptions éventuelles. Une exception peut être générée si la syntaxe d'une instruction de requête est erronée ou si une erreur se produit lors de l'exécution d'un traitement. L'exemple suivant intercepte et traite ces exceptions :
} catch (QueryException qe) {
    System.out.println("Query Exception "+ qe.getMessage() );
}

Gestion des collections importantes de résultats de la requête de l'interface distante

Si vous prévoyez que la requête renvoie une collection de taille significative, vous pouvez la programmer de sorte qu'elle renvoie les résultats sous forme de plusieurs quantités plus petites, plus facilement gérables. Utilisez les paramètres skipRow et maxRow sur la méthode distante executeQuery pour extraire la réponse en la fractionnant. Exemple :

int skipRow=0;
int maxRow=100;
QueryIterator it = null;
do {
	it = qb.executeQuery(query, null, null ,skipRow, maxRow );
	while (it.hasNext() ) { 
	// display result 
	skipRow = skipRow + maxRow;
}
} while ( ! it.isComplete() ) ;
Utilisation de l'interface locale pour une requête dynamique.

Lorsque vous exécutez une requête EJB (Enterprise JavaBeans) dynamique via l'interface locale, vous appelez la méthode executeQuery sur l'interface QueryLocal. Cette dernière ne lance pas de transaction pour la méthode ; il est donc nécessaire d'établir de manière explicite un contexte de transaction pour l'exécution de la requête.

Remarque : Pour ce faire, l'exemple ci-après appelle les méthodes begin() et commit(). Une alternative consiste à imbriquer le code de la requête dans une méthode EJB exécutée dans un contexte de transaction.

Commencez le code de la requête par les instructions d'importation suivantes :

import com.ibm.websphere.ejbquery.QueryLocalHome;
import com.ibm.websphere.ejbquery.QueryLocal;
import com.ibm.websphere.ejbquery.QueryLocalIterator;
import com.ibm.websphere.ejbquery.IQueryTuple;
import com.ibm.websphere.ejbquery.QueryException;

Rédigez ensuite les instructions de requête sous forme d'une chaîne, comme dans l'exemple suivant qui permet d'extraire les noms et les références d'EJB de salariés sous-payés :

String query = 
"select e.name, object(e) from EmpBean e where e.salary < 50000 ";

Créez un objet QueryLocal à l'aide d'une référence issue de la classe QueryLocalHome (cette classe définit la méthode executeQuery). A noter que dans l'exemple qui suit, ejb/query est utilisé comme référence d'EJB locale désignant le nom JNDI de la requête dynamique (com/ibm/websphere/ejbquery/Query) :

InitialContext ic =  new InitialContext(); 
   QueryLocalHome  qh =  ( LocalQueryHome) ic.lookup( "java:comp/env/ejb/query" );
QueryLocal qb = qh.create();

La dernière portion du code initie une transaction, appelle la méthode executeQuery et affiche les résultats de la requête. La classe QueryLocalIterator est instanciée car elle définit l'ensemble de résultats de la requête Cette classe est incluse dans le module de l'API Class QueryIterator. L'itérateur perd sa validité à la fin de la transaction ; vous devez donc l'utiliser dans la même portée de transaction que l'appel executeQuery.

userTransaction.begin();
QueryLocalIterator it = qb.executeQuery(query, null, null);
while (it.hasNext() ) { 
	IQueryTuple tuple = (IQueryTuple) it.next();
	System.out.print( it.getFieldName(1) );
	String s = (String) tuple.getObject(1);
	System.out.println( s);
	System.out.println( it.getFieldName(2) );
	EmpLocal e = ( EmpLocal ) tuple.getObject(2);
	System.out.println( e.getPrimaryKey().toString());
}
userTransaction.commit();

Dans la plupart des cas, l'objet QueryLocalIterator fonctionne à la demande. En effet, il renvoie les données de manière incrémentale : pour chaque extraction d'enregistrement de la base de données, la méthode next() doit être appelée sur l'itérateur (il existe des cas où l'itérateur ne fonctionne pas à la demande. Pour plus d'informations, voir la section relatives aux interfaces de requête locales dans Remarques concernant les performances de requête dynamique).

Etant donné que l'ensemble de résultats de la requête se matérialise de manière incrémentale dans le serveur d'applications, il est aisé de contrôler sa taille. Ainsi, lors d'une exécution test vous pouvez décider que seuls quelques nuplets du résultat de la requête sont nécessaires. Dans ce cas, vous devez utiliser un appel de la méthode close() sur l'objet QueryLocalIterator pour fermer la boucle de la requête. Des ressources SQL sont alors libérées et utilisées par l'itérateur. Dans le cas contraire, ces ressources ne sont pas libérées tant que la totalité de l'ensemble de résultats ne s'est pas accumulée en mémoire ou que la transaction ne s'est par terminée.


Icône indiquant le type de rubrique Rubrique de tâche



Icône d'horodatage Dernière mise à jour: last_date
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tque_dynamic
Nom du fichier : tque_dynamic.html