Développement de code client appelant des méthodes asynchrones d'EJB
Vous pouvez utiliser l'exemple de code fourni dans cette rubrique pour développer votre propre version d'un code client appelant des méthodes asynchrones d'EJB.
Avant de commencer
public interface AcmeRemoteInterface {
void fireAndForgetMethod ();
Future<Integer> methodWithResults() throws AcmeException1, AcmeException2;
}
@Stateless
@Remote(AcmeRemoteInterface.class)
@Asynchronous
public class AcmeAsyncBean {
public void fireAndForgetMethod () {
// exécuter un travail non critique
}
public Integer methodWithResults() {
Integer result;
// exécuter un travail, puis retourner les résultats
return result;
}
}
Pourquoi et quand exécuter cette tâche
Procédure
- Créez un code client qui appelle une méthode asynchrone ne renvoyant pas de
résultat, autrement connue sous le nom de méthode fire and forget (littéralement, déclencher et oublier).
Ce type de méthode asynchrone ne peut conduire à des exceptions dans l'application.
En revanche, des exceptions du système peuvent se produire et doivent être résolues.
@EJB AcmeRemoteInterface myAsyncBean; try { myAsyncBean.fireAndForgetMethod(); } catch (EJBException ejbex) { // La méthode asynchrone n'a jamais été distribuée, gérer l'erreur système }
- Créez un code client qui appelle une méthode asynchrone renvoyant
un résultat.
- Créer un code client qui appelle une méthode asynchrone et attend jusqu'à
cinq secondes de recevoir le résultats (l'unité d'exécution du client est bloquée
pendant cette attente). Les besoins de gestion des exceptions sont les mêmes
qu'à l'étape précédente. Exemple :
myResult = myFutureResult.get(5, TimeUnit.SECONDS);
- Créez un code client qui appelle une méthode asynchrone dont le
résultat n'est pas obtenu immédiatement. Une fois que la méthode a terminé son exécution, le client récupère le
résultat. Ce procédé évite de bloquer l'unité d'exécution du client ; celui-ci est
libre d'exécuter d'autres tâches tout en interrogeant périodiquement un objet pour
déterminer si le résultat est disponible. Les besoins de gestion des exceptions sont les mêmes
qu'aux étapes précédentes. Dans cet exemple, le client interroge périodiquement
l'objet Future<V> pour savoir si la méthode asynchrone a terminé son exécution. Exemple :
while (!myFutureResult.isDone()) { // Exécuter un autre travail en attendant que l'exécution de la méthode asynchrone soit terminée. } // Cet appel ne sera pas bloqué car la valeur true a été renvoyée par isDone. myResult = myFutureResult.get();
- Créer un code client qui appelle une méthode asynchrone et attend jusqu'à
cinq secondes de recevoir le résultats (l'unité d'exécution du client est bloquée
pendant cette attente). Les besoins de gestion des exceptions sont les mêmes
qu'à l'étape précédente. Exemple :
- Créez un code client pour gérer les exceptions de l'application. Le code client appelle une méthode asynchrone qui renvoie
une exception de l'application dans l'objet Future<V>. L'exemple suivant montre le code de gestion nécessaire pour déterminer
quelle exception s'est produite dans l'application.
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer>>myFutureResult = null; Integer myResult = null; try { myFutureResult = myAsyncBean.methodWithResults(); } catch (EJBException ejbx) { // La méthode asynchrone n'a jamais été distribuée ; gérer l'exception } // La méthode a finalement été distribuée. Attendre le résultat. try { myResult = myFutureResult.get(); } catch (ExecutionException ex) { // Déterminer quelle exception de l'application s'est produite durant // l'appel de méthode asynchrone. Throwable theCause = ex.getCause(); if (theCause instanceof AcmeException1) { // Gérer AcmeException1 } else if (theCause instanceof AcmeException2) { // Gérer AcmeException2 } else { // Gérer les autres causes. } } catch ( ... ) { // Gérer une autre exception. }
- Créer un code client pour identifier les exceptions système qui ont été
émises par l'appel de méthode asynchrone durant l'exécution.
L'exemple suivant montre le code de gestion nécessaire pour déterminer
si une exception système s'est produite.
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer>>myFutureResult = null; Integer myResult = null; try { myFutureResult = myAsyncBean.methodWithResults(); } catch (EJBException ejbx) { // La méthode asynchrone n'a pas été distribuée ; gérer l'exception } // Au bout du compte, la méthode sera distribuée, donc bloquer maintenant et attendre le résultat try { myResult = myFutureResult.get(); } catch (ExecutionException ex) { // Trouver la classe d'exception qui a été instanciée durant l'exécution de la méthode asynchrone Throwable theCause = ex.getCause(); if (theCause instanceof EJBException) { // Gérer l'EJBException, qui peut contenir une exception système // s'étant produite durant l'exécution de la méthode asynchrone. Throwable theRootCause = theCause.getCause(); if (theRootCause != null) { // Gérer l'exception système } } else ... // Gérer les autres causes } catch ( ... ) { // Gérer les autres exceptions }
- Au besoin, créez un code client pour annuler un appel
de méthode asynchrone. Si la tentative d'annulation réussit, la méthode Future.isCancelled
renvoie true et tout appel à la méthode Future.get se traduit par une CancellationException. L'exemple suivant montre le code nécessaire pour annuler
un appel de méthode asynchrone.
@EJB AcmeRemoteInterface myAsyncBean; Future<Integer> myFutureResult = myFutureResult.methodWithResults(); Integer myResult; if (myFutureResult.cancel(true)) { // La méthode asynchrone n'a pas été distribuée. } else { // La méthode asynchrone a déjà commencé à s'exécuter. Le bean peut encore tester // si une annulation de l'appel a été tentée. } if (myFutureResult.isCancelled()) { // La méthode asynchrone n'a pas commencé à s'exécuter, car la méthode cancel // a renvoyé true dans une précédente ligne de l'exemple. } try { myResult = myFutureResult.get(); } catch (CancellationException ex) { // Gérer l'exception qui est émise car la méthode cancel a renvoyé true // dans une précédente ligne de l'exemple. }
- Au besoin, créer un code de bean pour tester si un client a tenté d'annuler
l'appel de méthode asynchrone.
L'exemple suivant montre le code de bean nécessaire pour tester si un client a tenté d'annuler
l'appel de méthode asynchrone. Si le client a tenté d'annuler le travail, la méthode
SessionContext.wasCancelCalled
renvoie true et le code du bean peut éviter un travail inutile.
@Resource SessionContext myContext; public Future<Integer> methodWithResults() { for (int i = 0; i < 3; i++) { // Exécuter une partie (et une seule) d'un travail à exécution longue. // Avant de continuer, vérifier si le client a tenté d'annuler ce travail. if (myContext.wasCancelCalled()) { throw new AcmeCancelCalledException(); } } // ... }
- Retournez les multiples valeurs de sortie de l'appel de méthode asynchrone.
Dans certains cas, une méthode doit retourner plusieurs éléments de données.
L'un des moyens d'accomplir cette tâche est d'utiliser la sémantique de passage par référence. Le principe est le suivant : un objet est passé comme paramètre à la méthode, puis il est mis à jour par celle-ci et sa nouvelle valeur est mise à la disposition du client. Cette approche fonctionne pour les méthodes asynchrones, mais elle n'est pas optimale.
Pour retourner plusieurs éléments de données, créez un encapsuleur (wrapper) à l'intérieur de l'objet Future qui est renvoyé par la méthode. Le rôle de cet encapsuleur est de contenir des variables d'instances qui elles-mêmes contiennent les différents éléments de données qui doivent être retournés. La méthode asynchrone écrit ces éléments de données dans l'objet encapsuleur et renvoie celui-ci dans l'objet Future ; ensuite, le code client extrait ces données de l'objet Future.
Le fait d'incorporer plusieurs éléments de données dans un objet encapsuleur permet, localement ou à distance, d'identifier précisément à quel moment les résultats sont disponibles. Par opposition, la technique traditionnelle du passage par référence ne permet pas au client de déterminer facilement à quel moment les résultats sont prêts. L'objet passé n'est pas mis à jour tant que la méthode asynchrone n'a pas terminé son exécution et, pour déterminer si c'est le cas, le client n'a pas d'autre possibilité que d'interroger l'objet Future en utilisant sa méthode Future.isDone() ou Future.get().
// Voici l'objet de résultats qui est retourné par la méthode asynchrone. // Cet objet est encapsulé dans un objet Future et contient les deux éléments de données // qui doivent être renvoyés par la méthode. class ResultObject { public Boolean myResult; public String myInfo; }
// Voici le code de la méthode asynchrone qui obtient les résultats et les renvoie. @Asynchronous public Future<ResultObject> asyncMethod1(Object someInputData) { boolean result = doSomeStuff(); String info = doSomeMoreStuff(); ResultObject theResult = new ResultObject(); theResult.myResult = result; theResult.myInfo = info; return new javax.ejb.AsyncResult<ResultObject>(theResult); }
// Voici le code client qui obtient l'encapsuleur ResultObject et en extrait les données nécessaires. Future<ResultObject> myFutureResult = myBeanRef.asyncMethod1(someInputData); ResultObject theResult = myFutureResult.get(); boolean didItWork = theResult.myResult; String explanation = theResult.myInfo;
Sous-rubriques
Modèle de programmation de client pour les méthodes asynchrones EJB
Comme indiqué dans la spécification Enterprise JavaBeans (EJB) 3.1, vous pouvez appeler des méthodes asynchrones EJB à travers les types d'interface suivants : locale métier, distante métier, vue sans interface. Les appels via une vue de client EJB 2.1 ou une vue de service Web ne sont pas autorisés.Modèle de programmation de client pour les méthodes asynchrones EJB
Comme indiqué dans la spécification Enterprise JavaBeans (EJB) 3.1, vous pouvez appeler des méthodes asynchrones EJB à travers les types d'interface suivants : locale métier, distante métier, vue sans interface. Les appels via une vue de client EJB 2.1 ou une vue de service Web ne sont pas autorisés.


http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tejb_clientcode
Nom du fichier : tejb_clientcode.html